diff --git a/lib/ansible/modules/network/cloudengine/ce_rollback.py b/lib/ansible/modules/network/cloudengine/ce_rollback.py index fd6a2335c0b..d9edbd659d3 100644 --- a/lib/ansible/modules/network/cloudengine/ce_rollback.py +++ b/lib/ansible/modules/network/cloudengine/ce_rollback.py @@ -115,93 +115,8 @@ end_state: import re from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.cloudengine.ce import get_nc_config, execute_nc_action, ce_argument_spec, run_commands - - -CE_NC_GET_CHECKPOINT = """ - - - - - - - - - - - -""" - -CE_NC_ACTION_ROLLBACK_COMMIT_ID = """ - - - - %s - - - -""" - -CE_NC_ACTION_ROLLBACK_LABEL = """ - - - - %s - - - -""" - -CE_NC_ACTION_ROLLBACK_LAST = """ - - - - %s - - - -""" - -CE_NC_ACTION_ROLLBACK_FILE = """ - - - - %s - - - -""" - -CE_NC_ACTION_SET_COMMIT_ID_LABEL = """ - - - - %s - %s - - - -""" - -CE_NC_ACTION_CLEAR_COMMIT_ID_LABEL = """ - - - - %s - - - -""" - -CE_NC_ACTION_CLEAR_OLDEST_COMMIT_ID = """ - - - - %s - - - -""" +from ansible.module_utils.network.cloudengine.ce import ce_argument_spec, exec_command, run_commands +from ansible.module_utils.network.common.utils import ComplexList class RollBack(object): @@ -211,9 +126,8 @@ class RollBack(object): def __init__(self, argument_spec): self.spec = argument_spec - self.module = None - self.init_module() - + self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True) + self.commands = list() # module input info self.commit_id = self.module.params['commit_id'] self.label = self.module.params['label'] @@ -232,12 +146,20 @@ class RollBack(object): # configuration rollback points info self.rollback_info = None + self.init_module() def init_module(self): """ init module """ + required_if = [('action', 'set', ['commit_id', 'label']), ('action', 'commit', ['label'])] + mutually_exclusive = None + required_one_of = None + if self.action == "rollback": + required_one_of = [['commit_id', 'label', 'filename', 'last']] + elif self.action == "clear": + required_one_of = [['commit_id', 'oldest']] self.module = AnsibleModule( - argument_spec=self.spec, supports_check_mode=True) + argument_spec=self.spec, supports_check_mode=True, required_if=required_if, mutually_exclusive=mutually_exclusive, required_one_of=required_one_of) def check_response(self, xml_str, xml_name): """Check if response message is already succeed.""" @@ -245,25 +167,59 @@ class RollBack(object): if "" not in xml_str: self.module.fail_json(msg='Error: %s failed.' % xml_name) + def cli_add_command(self, command, undo=False): + """add command to self.update_cmd and self.commands""" + self.commands.append("return") + + if self.action == "commit": + self.commands.append("sys") + + self.commands.append(command) + self.updates_cmd.append(command) + + def cli_load_config(self, commands): + """load config by cli""" + + if not self.module.check_mode: + run_commands(self.module, commands) + + def get_config(self, flags=None): + """Retrieves the current config from the device or cache + """ + flags = [] if flags is None else flags + + cmd = 'display configuration ' + cmd += ' '.join(flags) + cmd = cmd.strip() + + rc, out, err = exec_command(self.module, cmd) + if rc != 0: + self.module.fail_json(msg=err) + cfg = str(out).strip() + + return cfg + def get_rollback_dict(self): """ get rollback attributes dict.""" rollback_info = dict() - conf_str = CE_NC_GET_CHECKPOINT - xml_str = get_nc_config(self.module, conf_str) rollback_info["RollBackInfos"] = list() - if "" in xml_str: - return rollback_info - else: - re_find = re.findall(r'.*(.*).*\s*' - r'(.*).*\s*' - r'(.*).*', xml_str) - for mem in re_find: - rollback_info["RollBackInfos"].append( - dict(commitId=mem[0], userLabel=mem[2])) + flags = list() + exp = "commit list" + flags.append(exp) + cfg_info = self.get_config(flags) + if not cfg_info: return rollback_info + cfg_line = cfg_info.split("\n") + for cfg in cfg_line: + if re.findall(r'^\d', cfg): + pre_rollback_info = cfg.split() + rollback_info["RollBackInfos"].append(dict(commitId=pre_rollback_info[1], userLabel=pre_rollback_info[2])) + + return rollback_info + def get_filename_type(self, filename): """Gets the type of filename, such as cfg, zip, dat...""" @@ -285,120 +241,75 @@ class RollBack(object): return None return iftype.lower() - def rollback_commit_id(self): - """rollback comit_id""" + def set_config(self): - cfg_xml = "" - self.updates_cmd.append( - "rollback configuration to commit-id %s" % self.commit_id) - cfg_xml = CE_NC_ACTION_ROLLBACK_COMMIT_ID % self.commit_id - recv_xml = execute_nc_action(self.module, cfg_xml) - self.check_response(recv_xml, "ROLLBACK_COMMITID") - self.changed = True + if self.action == "rollback": + if self.commit_id: + cmd = "rollback configuration to commit-id %s" % self.commit_id + cmd = {"command": cmd, "prompt": r"[Y/N]", "answer": "Y"} + self.cli_add_command(cmd) + if self.label: + cmd = "rollback configuration to label %s" % self.label + cmd = {"command": cmd, "prompt": r"[Y/N]", "answer": "Y"} + self.cli_add_command(cmd) + if self.filename: + cmd = "rollback configuration to file %s" % self.filename + cmd = {"command": cmd, "prompt": r"[Y/N]", "answer": "Y"} + self.cli_add_command(cmd) + if self.last: + cmd = "rollback configuration last %s" % self.last + cmd = {"command": cmd, "prompt": r"[Y/N]", "answer": "Y"} + self.cli_add_command(cmd) + elif self.action == "set": + if self.commit_id and self.label: + cmd = "set configuration commit %s label %s" % (self.commit_id, self.label) + self.cli_add_command(cmd) + elif self.action == "clear": + if self.commit_id: + cmd = "clear configuration commit %s label" % self.commit_id + self.cli_add_command(cmd) + if self.oldest: + cmd = "clear configuration commit oldest %s" % self.oldest + cmd = {"command": cmd, "prompt": r"[Y/N]", "answer": "Y"} + self.cli_add_command(cmd) + elif self.action == "commit": + if self.label: + cmd = "commit label %s" % self.label + self.cli_add_command(cmd) - def rollback_label(self): - """rollback label""" - - cfg_xml = "" - self.updates_cmd.append( - "rollback configuration to label %s" % self.label) - cfg_xml = CE_NC_ACTION_ROLLBACK_LABEL % self.label - recv_xml = execute_nc_action(self.module, cfg_xml) - self.check_response(recv_xml, "ROLLBACK_LABEL") - self.changed = True - - def rollback_filename(self): - """rollback filename""" - - cfg_xml = "" - self.updates_cmd.append( - "rollback configuration to file %s" % self.filename) - cfg_xml = CE_NC_ACTION_ROLLBACK_FILE % self.filename - recv_xml = execute_nc_action(self.module, cfg_xml) - self.check_response(recv_xml, "ROLLBACK_FILENAME") - self.changed = True - - def rollback_last(self): - """rollback last""" - - cfg_xml = "" - self.updates_cmd.append( - "rollback configuration to last %s" % self.last) - cfg_xml = CE_NC_ACTION_ROLLBACK_LAST % self.last - recv_xml = execute_nc_action(self.module, cfg_xml) - self.check_response(recv_xml, "ROLLBACK_LAST") - self.changed = True - - def set_commitid_label(self): - """set commitid label""" - - cfg_xml = "" - self.updates_cmd.append( - "set configuration commit %s label %s" % (self.commit_id, self.label)) - cfg_xml = CE_NC_ACTION_SET_COMMIT_ID_LABEL % ( - self.commit_id, self.label) - recv_xml = execute_nc_action(self.module, cfg_xml) - self.check_response(recv_xml, "SET_COMIMIT_LABEL") - self.changed = True - - def clear_commitid_label(self): - """clear commitid label""" - - cfg_xml = "" - self.updates_cmd.append( - "clear configuration commit %s label" % self.commit_id) - cfg_xml = CE_NC_ACTION_CLEAR_COMMIT_ID_LABEL % self.commit_id - recv_xml = execute_nc_action(self.module, cfg_xml) - self.check_response(recv_xml, "CLEAR_COMMIT_LABEL") - self.changed = True - - def clear_oldest(self): - """clear oldest""" - - cfg_xml = "" - self.updates_cmd.append( - "clear configuration commit oldest %s" % self.oldest) - cfg_xml = CE_NC_ACTION_CLEAR_OLDEST_COMMIT_ID % self.oldest - recv_xml = execute_nc_action(self.module, cfg_xml) - self.check_response(recv_xml, "CLEAR_COMMIT_OLDEST") - self.changed = True - - def commit_label(self): - """commit label""" - - commands = list() - cmd1 = {'output': None, 'command': 'system-view'} - commands.append(cmd1) - - cmd2 = {'output': None, 'command': ''} - cmd2['command'] = "commit label %s" % self.label - commands.append(cmd2) - self.updates_cmd.append( - "commit label %s" % self.label) - run_commands(self.module, commands) - self.changed = True + elif self.action == "display": + self.rollback_info = self.get_rollback_dict() + if self.commands: + self.cli_load_config(self.commands) + self.changed = True def check_params(self): """Check all input params""" # commit_id check + rollback_info = self.rollback_info["RollBackInfos"] if self.commit_id: if not self.commit_id.isdigit(): self.module.fail_json( msg='Error: The parameter of commit_id is invalid.') - # label check - if self.label: - if self.label[0].isdigit(): + info_bool = False + for info in rollback_info: + if info.get("commitId") == self.commit_id: + info_bool = True + if not info_bool: self.module.fail_json( - msg='Error: Commit label which should not start with a number.') - if len(self.label.replace(' ', '')) == 1: - if self.label == '-': + msg='Error: The parameter of commit_id is not exist.') + + if self.action == "clear": + info_bool = False + for info in rollback_info: + if info.get("commitId") == self.commit_id: + if info.get("userLabel") == "-": + info_bool = True + if info_bool: self.module.fail_json( - msg='Error: Commit label which should not be "-"') - if len(self.label.replace(' ', '')) < 1 or len(self.label) > 256: - self.module.fail_json( - msg='Error: Label of configuration checkpoints is a string of 1 to 256 characters.') + msg='Error: This commit_id does not have a label.') # filename check if self.filename: @@ -423,6 +334,47 @@ class RollBack(object): self.module.fail_json( msg='Error: Number of configuration checkpoints is not in the range from 1 to 80.') + # label check + if self.label: + if self.label[0].isdigit(): + self.module.fail_json( + msg='Error: Commit label which should not start with a number.') + if len(self.label.replace(' ', '')) == 1: + if self.label == '-': + self.module.fail_json( + msg='Error: Commit label which should not be "-"') + if len(self.label.replace(' ', '')) < 1 or len(self.label) > 256: + self.module.fail_json( + msg='Error: Label of configuration checkpoints is a string of 1 to 256 characters.') + + if self.action == "rollback": + info_bool = False + for info in rollback_info: + if info.get("userLabel") == self.label: + info_bool = True + if not info_bool: + self.module.fail_json( + msg='Error: The parameter of userLabel is not exist.') + + if self.action == "commit": + info_bool = False + for info in rollback_info: + if info.get("userLabel") == self.label: + info_bool = True + if info_bool: + self.module.fail_json( + msg='Error: The parameter of userLabel is existing.') + + if self.action == "set": + info_bool = False + for info in rollback_info: + if info.get("commitId") == self.commit_id: + if info.get("userLabel") != "-": + info_bool = True + if info_bool: + self.module.fail_json( + msg='Error: The userLabel of this commitid is present and can be reset after deletion.') + def get_proposed(self): """get proposed info""" @@ -439,47 +391,32 @@ class RollBack(object): def get_existing(self): """get existing info""" - if not self.rollback_info: - return - self.existing["RollBackInfos"] = self.rollback_info["RollBackInfos"] + self.existing["RollBackInfos"] = None + else: + self.existing["RollBackInfos"] = self.rollback_info["RollBackInfos"] def get_end_state(self): """get end state info""" - self.end_state = None + rollback_info = self.get_rollback_dict() + if not rollback_info: + self.end_state["RollBackInfos"] = None + else: + self.end_state["RollBackInfos"] = rollback_info["RollBackInfos"] def work(self): """worker""" + self.rollback_info = self.get_rollback_dict() self.check_params() self.get_proposed() - # action mode - if self.action == "rollback": - if self.commit_id: - self.rollback_commit_id() - if self.label: - self.rollback_label() - if self.filename: - self.rollback_filename() - if self.last: - self.rollback_last() - elif self.action == "set": - if self.commit_id and self.label: - self.set_commitid_label() - elif self.action == "clear": - if self.commit_id: - self.clear_commitid_label() - if self.oldest: - self.clear_oldest() - elif self.action == "commit": - if self.label: - self.commit_label() - elif self.action == "display": - self.rollback_info = self.get_rollback_dict() + + self.set_config() self.get_existing() self.get_end_state() + self.results['changed'] = self.changed self.results['proposed'] = self.proposed self.results['existing'] = self.existing