From 0a04a5efc2859fc9f3e1899bbe0dded692cd6ed7 Mon Sep 17 00:00:00 2001 From: Suhas Bharadwaj Date: Mon, 16 Dec 2019 14:44:33 +0530 Subject: [PATCH] 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 --- .../modules/network/nxos/storage/__init__.py | 0 .../network/nxos/storage/nxos_devicealias.py | 499 ++++++++++++ .../modules/network/nxos/storage/nxos_vsan.py | 326 ++++++++ .../network/nxos/storage/nxos_zone_zoneset.py | 722 ++++++++++++++++++ .../nxos_devicealias/defaults/main.yaml | 2 + .../targets/nxos_devicealias/meta/main.yml | 2 + .../targets/nxos_devicealias/tasks/cli.yaml | 27 + .../targets/nxos_devicealias/tasks/main.yaml | 16 + .../nxos_devicealias/tests/common/sanity.yaml | 42 + .../targets/nxos_vsan/defaults/main.yaml | 2 + .../targets/nxos_vsan/meta/main.yml | 2 + .../targets/nxos_vsan/tasks/cli.yaml | 27 + .../targets/nxos_vsan/tasks/main.yaml | 16 + .../nxos_vsan/tests/common/sanity.yaml | 50 ++ .../targets/nxos_vsan/vars/main.yml | 4 + .../nxos_zone_zoneset/defaults/main.yaml | 2 + .../targets/nxos_zone_zoneset/meta/main.yml | 2 + .../targets/nxos_zone_zoneset/tasks/cli.yaml | 27 + .../targets/nxos_zone_zoneset/tasks/main.yaml | 16 + .../tests/common/sanity.yaml | 145 ++++ .../targets/nxos_zone_zoneset/vars/main.yml | 4 + .../fixtures/nxos_devicealias/shdadatabse.cfg | 5 + .../fixtures/nxos_devicealias/shdastatus.cfg | 4 + .../nxos_devicealias/shdastatus_mansi.cfg | 4 + .../nxos_devicealias/shdastatuslock.cfg | 6 + .../nxos/fixtures/nxos_vsan/shvsan.cfg | 35 + .../nxos/fixtures/nxos_vsan/shvsanmem.cfg | 30 + .../fixtures/nxos_zone_zoneset/shzone_0.cfg | 8 + .../fixtures/nxos_zone_zoneset/shzone_1.cfg | 8 + .../fixtures/nxos_zone_zoneset/shzone_2.cfg | 6 + .../nxos_zone_zoneset/shzoneset_0.cfg | 10 + .../nxos_zone_zoneset/shzoneset_1.cfg | 9 + .../nxos_zone_zoneset/shzoneset_2.cfg | 7 + .../nxos_zone_zoneset/shzonesetactive_0.cfg | 8 + .../nxos_zone_zoneset/shzonestatus_0.cfg | 23 + .../nxos_zone_zoneset/shzonestatus_1.cfg | 23 + .../nxos_zone_zoneset/shzonestatus_2.cfg | 24 + .../nxos_zone_zoneset/shzonestatus_3.cfg | 24 + .../nxos_zone_zoneset/shzonestatus_4.cfg | 23 + .../modules/network/nxos/storage/__init__.py | 0 .../nxos/storage/test_nxos_devicealias.py | 229 ++++++ .../network/nxos/storage/test_nxos_vsan.py | 237 ++++++ .../nxos/storage/test_nxos_zone_zoneset.py | 496 ++++++++++++ 43 files changed, 3152 insertions(+) create mode 100644 lib/ansible/modules/network/nxos/storage/__init__.py create mode 100644 lib/ansible/modules/network/nxos/storage/nxos_devicealias.py create mode 100644 lib/ansible/modules/network/nxos/storage/nxos_vsan.py create mode 100644 lib/ansible/modules/network/nxos/storage/nxos_zone_zoneset.py create mode 100644 test/integration/targets/nxos_devicealias/defaults/main.yaml create mode 100644 test/integration/targets/nxos_devicealias/meta/main.yml create mode 100644 test/integration/targets/nxos_devicealias/tasks/cli.yaml create mode 100644 test/integration/targets/nxos_devicealias/tasks/main.yaml create mode 100644 test/integration/targets/nxos_devicealias/tests/common/sanity.yaml create mode 100644 test/integration/targets/nxos_vsan/defaults/main.yaml create mode 100644 test/integration/targets/nxos_vsan/meta/main.yml create mode 100644 test/integration/targets/nxos_vsan/tasks/cli.yaml create mode 100644 test/integration/targets/nxos_vsan/tasks/main.yaml create mode 100644 test/integration/targets/nxos_vsan/tests/common/sanity.yaml create mode 100644 test/integration/targets/nxos_vsan/vars/main.yml create mode 100644 test/integration/targets/nxos_zone_zoneset/defaults/main.yaml create mode 100644 test/integration/targets/nxos_zone_zoneset/meta/main.yml create mode 100644 test/integration/targets/nxos_zone_zoneset/tasks/cli.yaml create mode 100644 test/integration/targets/nxos_zone_zoneset/tasks/main.yaml create mode 100644 test/integration/targets/nxos_zone_zoneset/tests/common/sanity.yaml create mode 100644 test/integration/targets/nxos_zone_zoneset/vars/main.yml create mode 100644 test/units/modules/network/nxos/fixtures/nxos_devicealias/shdadatabse.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_devicealias/shdastatus.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_devicealias/shdastatus_mansi.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_devicealias/shdastatuslock.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_vsan/shvsan.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_vsan/shvsanmem.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzone_0.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzone_1.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzone_2.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzoneset_0.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzoneset_1.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzoneset_2.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonesetactive_0.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_0.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_1.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_2.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_3.cfg create mode 100644 test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_4.cfg create mode 100644 test/units/modules/network/nxos/storage/__init__.py create mode 100644 test/units/modules/network/nxos/storage/test_nxos_devicealias.py create mode 100644 test/units/modules/network/nxos/storage/test_nxos_vsan.py create mode 100644 test/units/modules/network/nxos/storage/test_nxos_zone_zoneset.py diff --git a/lib/ansible/modules/network/nxos/storage/__init__.py b/lib/ansible/modules/network/nxos/storage/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ansible/modules/network/nxos/storage/nxos_devicealias.py b/lib/ansible/modules/network/nxos/storage/nxos_devicealias.py new file mode 100644 index 00000000000..b76aa9f8831 --- /dev/null +++ b/lib/ansible/modules/network/nxos/storage/nxos_devicealias.py @@ -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() diff --git a/lib/ansible/modules/network/nxos/storage/nxos_vsan.py b/lib/ansible/modules/network/nxos/storage/nxos_vsan.py new file mode 100644 index 00000000000..f0cde105a2b --- /dev/null +++ b/lib/ansible/modules/network/nxos/storage/nxos_vsan.py @@ -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() diff --git a/lib/ansible/modules/network/nxos/storage/nxos_zone_zoneset.py b/lib/ansible/modules/network/nxos/storage/nxos_zone_zoneset.py new file mode 100644 index 00000000000..49ddd77f390 --- /dev/null +++ b/lib/ansible/modules/network/nxos/storage/nxos_zone_zoneset.py @@ -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() diff --git a/test/integration/targets/nxos_devicealias/defaults/main.yaml b/test/integration/targets/nxos_devicealias/defaults/main.yaml new file mode 100644 index 00000000000..5f709c5aac1 --- /dev/null +++ b/test/integration/targets/nxos_devicealias/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +testcase: "*" diff --git a/test/integration/targets/nxos_devicealias/meta/main.yml b/test/integration/targets/nxos_devicealias/meta/main.yml new file mode 100644 index 00000000000..42c635d6d29 --- /dev/null +++ b/test/integration/targets/nxos_devicealias/meta/main.yml @@ -0,0 +1,2 @@ +# dependencies: +# - prepare_nxos_tests diff --git a/test/integration/targets/nxos_devicealias/tasks/cli.yaml b/test/integration/targets/nxos_devicealias/tasks/cli.yaml new file mode 100644 index 00000000000..9b62eaba65e --- /dev/null +++ b/test/integration/targets/nxos_devicealias/tasks/cli.yaml @@ -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 diff --git a/test/integration/targets/nxos_devicealias/tasks/main.yaml b/test/integration/targets/nxos_devicealias/tasks/main.yaml new file mode 100644 index 00000000000..eb3f9ca07c4 --- /dev/null +++ b/test/integration/targets/nxos_devicealias/tasks/main.yaml @@ -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 + \ No newline at end of file diff --git a/test/integration/targets/nxos_devicealias/tests/common/sanity.yaml b/test/integration/targets/nxos_devicealias/tests/common/sanity.yaml new file mode 100644 index 00000000000..26d7f681980 --- /dev/null +++ b/test/integration/targets/nxos_devicealias/tests/common/sanity.yaml @@ -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" diff --git a/test/integration/targets/nxos_vsan/defaults/main.yaml b/test/integration/targets/nxos_vsan/defaults/main.yaml new file mode 100644 index 00000000000..55a93fc23dc --- /dev/null +++ b/test/integration/targets/nxos_vsan/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +testcase: "*" \ No newline at end of file diff --git a/test/integration/targets/nxos_vsan/meta/main.yml b/test/integration/targets/nxos_vsan/meta/main.yml new file mode 100644 index 00000000000..42c635d6d29 --- /dev/null +++ b/test/integration/targets/nxos_vsan/meta/main.yml @@ -0,0 +1,2 @@ +# dependencies: +# - prepare_nxos_tests diff --git a/test/integration/targets/nxos_vsan/tasks/cli.yaml b/test/integration/targets/nxos_vsan/tasks/cli.yaml new file mode 100644 index 00000000000..9b62eaba65e --- /dev/null +++ b/test/integration/targets/nxos_vsan/tasks/cli.yaml @@ -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 diff --git a/test/integration/targets/nxos_vsan/tasks/main.yaml b/test/integration/targets/nxos_vsan/tasks/main.yaml new file mode 100644 index 00000000000..eb3f9ca07c4 --- /dev/null +++ b/test/integration/targets/nxos_vsan/tasks/main.yaml @@ -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 + \ No newline at end of file diff --git a/test/integration/targets/nxos_vsan/tests/common/sanity.yaml b/test/integration/targets/nxos_vsan/tests/common/sanity.yaml new file mode 100644 index 00000000000..a4bd5e2df07 --- /dev/null +++ b/test/integration/targets/nxos_vsan/tests/common/sanity.yaml @@ -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 diff --git a/test/integration/targets/nxos_vsan/vars/main.yml b/test/integration/targets/nxos_vsan/vars/main.yml new file mode 100644 index 00000000000..2e3bcbadef7 --- /dev/null +++ b/test/integration/targets/nxos_vsan/vars/main.yml @@ -0,0 +1,4 @@ +vsan1: 922 +vsan2: 923 +intA1: fc1/1 +intB1: fc1/2 diff --git a/test/integration/targets/nxos_zone_zoneset/defaults/main.yaml b/test/integration/targets/nxos_zone_zoneset/defaults/main.yaml new file mode 100644 index 00000000000..55a93fc23dc --- /dev/null +++ b/test/integration/targets/nxos_zone_zoneset/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +testcase: "*" \ No newline at end of file diff --git a/test/integration/targets/nxos_zone_zoneset/meta/main.yml b/test/integration/targets/nxos_zone_zoneset/meta/main.yml new file mode 100644 index 00000000000..42c635d6d29 --- /dev/null +++ b/test/integration/targets/nxos_zone_zoneset/meta/main.yml @@ -0,0 +1,2 @@ +# dependencies: +# - prepare_nxos_tests diff --git a/test/integration/targets/nxos_zone_zoneset/tasks/cli.yaml b/test/integration/targets/nxos_zone_zoneset/tasks/cli.yaml new file mode 100644 index 00000000000..9b62eaba65e --- /dev/null +++ b/test/integration/targets/nxos_zone_zoneset/tasks/cli.yaml @@ -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 diff --git a/test/integration/targets/nxos_zone_zoneset/tasks/main.yaml b/test/integration/targets/nxos_zone_zoneset/tasks/main.yaml new file mode 100644 index 00000000000..eb3f9ca07c4 --- /dev/null +++ b/test/integration/targets/nxos_zone_zoneset/tasks/main.yaml @@ -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 + \ No newline at end of file diff --git a/test/integration/targets/nxos_zone_zoneset/tests/common/sanity.yaml b/test/integration/targets/nxos_zone_zoneset/tests/common/sanity.yaml new file mode 100644 index 00000000000..f08f3ec3653 --- /dev/null +++ b/test/integration/targets/nxos_zone_zoneset/tests/common/sanity.yaml @@ -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 diff --git a/test/integration/targets/nxos_zone_zoneset/vars/main.yml b/test/integration/targets/nxos_zone_zoneset/vars/main.yml new file mode 100644 index 00000000000..2e3bcbadef7 --- /dev/null +++ b/test/integration/targets/nxos_zone_zoneset/vars/main.yml @@ -0,0 +1,4 @@ +vsan1: 922 +vsan2: 923 +intA1: fc1/1 +intB1: fc1/2 diff --git a/test/units/modules/network/nxos/fixtures/nxos_devicealias/shdadatabse.cfg b/test/units/modules/network/nxos/fixtures/nxos_devicealias/shdadatabse.cfg new file mode 100644 index 00000000000..cc526a71463 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_devicealias/shdadatabse.cfg @@ -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 + diff --git a/test/units/modules/network/nxos/fixtures/nxos_devicealias/shdastatus.cfg b/test/units/modules/network/nxos/fixtures/nxos_devicealias/shdastatus.cfg new file mode 100644 index 00000000000..7db8803456c --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_devicealias/shdastatus.cfg @@ -0,0 +1,4 @@ +Fabric Distribution : Enabled +Database:- Device Aliases 3831 Mode: Enhanced + Checksum: 0xdc7b6c6c124abd8fe28cf6a1ab293c + diff --git a/test/units/modules/network/nxos/fixtures/nxos_devicealias/shdastatus_mansi.cfg b/test/units/modules/network/nxos/fixtures/nxos_devicealias/shdastatus_mansi.cfg new file mode 100644 index 00000000000..aa399b64106 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_devicealias/shdastatus_mansi.cfg @@ -0,0 +1,4 @@ +Fabric Distribution : Disabled +Database:- Device Aliases 3831 Mode: Basic + Checksum: 0xdc7b6c6c124abd8fe28cf6a1ab293c + diff --git a/test/units/modules/network/nxos/fixtures/nxos_devicealias/shdastatuslock.cfg b/test/units/modules/network/nxos/fixtures/nxos_devicealias/shdastatuslock.cfg new file mode 100644 index 00000000000..65cb052f5fe --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_devicealias/shdastatuslock.cfg @@ -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 + diff --git a/test/units/modules/network/nxos/fixtures/nxos_vsan/shvsan.cfg b/test/units/modules/network/nxos/fixtures/nxos_vsan/shvsan.cfg new file mode 100644 index 00000000000..035351a9f60 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_vsan/shvsan.cfg @@ -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 + + diff --git a/test/units/modules/network/nxos/fixtures/nxos_vsan/shvsanmem.cfg b/test/units/modules/network/nxos/fixtures/nxos_vsan/shvsanmem.cfg new file mode 100644 index 00000000000..c57c72a2f04 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_vsan/shvsanmem.cfg @@ -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 + + diff --git a/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzone_0.cfg b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzone_0.cfg new file mode 100644 index 00000000000..14b431b9b0f --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzone_0.cfg @@ -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 + diff --git a/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzone_1.cfg b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzone_1.cfg new file mode 100644 index 00000000000..73d58c51e8d --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzone_1.cfg @@ -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 + diff --git a/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzone_2.cfg b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzone_2.cfg new file mode 100644 index 00000000000..530266d4cad --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzone_2.cfg @@ -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] diff --git a/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzoneset_0.cfg b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzoneset_0.cfg new file mode 100644 index 00000000000..c1b560053d9 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzoneset_0.cfg @@ -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 + diff --git a/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzoneset_1.cfg b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzoneset_1.cfg new file mode 100644 index 00000000000..77d296229c5 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzoneset_1.cfg @@ -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 + diff --git a/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzoneset_2.cfg b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzoneset_2.cfg new file mode 100644 index 00000000000..923f54e4b66 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzoneset_2.cfg @@ -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] diff --git a/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonesetactive_0.cfg b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonesetactive_0.cfg new file mode 100644 index 00000000000..1180410a1a7 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonesetactive_0.cfg @@ -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] + diff --git a/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_0.cfg b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_0.cfg new file mode 100644 index 00000000000..0bfced832bc --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_0.cfg @@ -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 + + diff --git a/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_1.cfg b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_1.cfg new file mode 100644 index 00000000000..bf7a4615fb1 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_1.cfg @@ -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 + + diff --git a/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_2.cfg b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_2.cfg new file mode 100644 index 00000000000..eb0db28eb98 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_2.cfg @@ -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 + + diff --git a/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_3.cfg b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_3.cfg new file mode 100644 index 00000000000..c5c32db0b43 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_3.cfg @@ -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 + + diff --git a/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_4.cfg b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_4.cfg new file mode 100644 index 00000000000..97c3a7156c9 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_zone_zoneset/shzonestatus_4.cfg @@ -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: + + diff --git a/test/units/modules/network/nxos/storage/__init__.py b/test/units/modules/network/nxos/storage/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/units/modules/network/nxos/storage/test_nxos_devicealias.py b/test/units/modules/network/nxos/storage/test_nxos_devicealias.py new file mode 100644 index 00000000000..68080afef27 --- /dev/null +++ b/test/units/modules/network/nxos/storage/test_nxos_devicealias.py @@ -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']) diff --git a/test/units/modules/network/nxos/storage/test_nxos_vsan.py b/test/units/modules/network/nxos/storage/test_nxos_vsan.py new file mode 100644 index 00000000000..5e94601d721 --- /dev/null +++ b/test/units/modules/network/nxos/storage/test_nxos_vsan.py @@ -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']) diff --git a/test/units/modules/network/nxos/storage/test_nxos_zone_zoneset.py b/test/units/modules/network/nxos/storage/test_nxos_zone_zoneset.py new file mode 100644 index 00000000000..ec85dec41fe --- /dev/null +++ b/test/units/modules/network/nxos/storage/test_nxos_zone_zoneset.py @@ -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'])