Server IP : 85.214.239.14 / Your IP : 3.144.6.254 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /usr/lib/python3/dist-packages/ansible_collections/cisco/nxos/plugins/modules/ |
Upload File : |
#!/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 DOCUMENTATION = """ module: nxos_devicealias short_description: Configuration of device alias for Cisco NXOS MDS Switches. description: - Configuration of device alias for Cisco MDS NXOS. version_added: 1.0.0 author: - Suhas Bharadwaj (@srbharadwaj) (subharad@cisco.com) notes: - Tested against Cisco MDS NX-OS 8.4(1) options: distribute: description: - Enable/Disable device-alias distribution type: bool 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 elements: dict 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 elements: dict 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 cisco.nxos.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 """ import string from ansible.module_utils.basic import AnsibleModule from ansible_collections.cisco.nxos.plugins.module_utils.network.nxos.nxos import ( load_config, run_commands, ) __metaclass__ = type VALID_DA_CHARS = ("-", "_", "$", "^") 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 for character in name: if not character.isalnum() and character not in VALID_DA_CHARS: 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, does not 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 alphanumeric chars, " + "it must start with a letter, and can only contain these characters: " + ", ".join(["'{0}'".format(c) for c in VALID_DA_CHARS]), ) 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 alphanumeric chars, " + "it must start with a letter, and can only contain these characters: " + ", ".join(["'{0}'".format(c) for c in VALID_DA_CHARS]), ) if not isNameValid(newname): module.fail_json( msg="This pwwn name is invalid : " + str(newname) + ". Note that name cannot be more than 64 alphanumeric chars, " + "it must start with a letter, and can only contain these characters: " + ", ".join(["'{0}'".format(c) for c in VALID_DA_CHARS]), ) # 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()