diff --git a/lib/ansible/modules/network/cloudengine/ce_vrrp.py b/lib/ansible/modules/network/cloudengine/ce_vrrp.py new file mode 100644 index 00000000000..7802f13b2e9 --- /dev/null +++ b/lib/ansible/modules/network/cloudengine/ce_vrrp.py @@ -0,0 +1,1402 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# + +ANSIBLE_METADATA = {'status': ['preview'], + 'supported_by': 'community', + 'metadata_version': '1.0'} + +DOCUMENTATION = ''' +--- +module: ce_vrrp +version_added: "2.4" +short_description: Manages VRRP interfaces on HUAWEI CloudEngine devices. +description: + - Manages VRRP interface attributes on HUAWEI CloudEngine devices. +author: + - Li Yanfeng (@CloudEngine-Ansible) +options: + interface: + description: + - Name of an interface. The value is a string of 1 to 63 characters. + required: false + default: null + vrid: + description: + - VRRP backup group ID. + The value is an integer ranging from 1 to 255. + required: false + default: present + virtual_ip : + description: + - Virtual IP address. The value is a string of 0 to 255 characters. + required: false + default: null + vrrp_type: + description: + - Type of a VRRP backup group. + required: false + choices: ['normal', 'member', 'admin'] + default: null + admin_ignore_if_down: + description: + - mVRRP ignores an interface Down event. + required: false + default: False + admin_vrid: + description: + - Tracked mVRRP ID. The value is an integer ranging from 1 to 255. + required: false + default: null + admin_interface: + description: + - Tracked mVRRP interface name. The value is a string of 1 to 63 characters. + required: false + default: null + admin_flowdown: + description: + - Disable the flowdown function for service VRRP. + required: false + default: False + priority: + description: + - Configured VRRP priority. + The value ranges from 1 to 254. The default value is 100. A larger value indicates a higher priority. + required: false + default: null + version: + description: + - VRRP version. The default version is v2. + required: false + choices: ['v2','v3'] + default: null + advertise_interval: + description: + - Configured interval between sending advertisements, in milliseconds. + Only the master router sends VRRP advertisements. The default value is 1000 milliseconds. + required: false + default: null + preempt_timer_delay: + description: + - Preemption delay. + The value is an integer ranging from 0 to 3600. The default value is 0. + required: false + default: null + gratuitous_arp_interval: + description: + - Interval at which gratuitous ARP packets are sent, in seconds. + The value ranges from 30 to 1200.The default value is 300. + required: false + default: null + recover_delay: + description: + - Delay in recovering after an interface goes Up. + The delay is used for interface flapping suppression. + The value is an integer ranging from 0 to 3600. + The default value is 0 seconds. + required: false + default: null + holding_multiplier: + description: + - The configured holdMultiplier.The value is an integer ranging from 3 to 10. The default value is 3. + required: false + default: null + auth_mode: + description: + - Authentication type used for VRRP packet exchanges between virtual routers. + The values are noAuthentication, simpleTextPassword, md5Authentication. + The default value is noAuthentication. + required: false + choices: ['simple','md5','none'] + default: null + is_plain: + description: + - Select the display mode of an authentication key. + By default, an authentication key is displayed in ciphertext. + required: false + default: False + auth_key: + description: + - This object is set based on the authentication type. + When noAuthentication is specified, the value is empty. + When simpleTextPassword or md5Authentication is specified, the value is a string of 1 to 8 characters + in plaintext and displayed as a blank text for security. + required: false + default: null + fast_resume: + description: + - mVRRP's fast resume mode. + required: false + choices: ['enable','disable'] + default: null + state: + description: + - Specify desired state of the resource. + required: false + default: present + choices: ['present','absent'] + +''' + +EXAMPLES = ''' +- name: vrrp module test + hosts: cloudengine + connection: local + gather_facts: no + vars: + cli: + host: "{{ inventory_hostname }}" + port: "{{ ansible_ssh_port }}" + username: "{{ username }}" + password: "{{ password }}" + transport: cli + + tasks: + + - name: Set vrrp version + ce_vrrp: + version: v3 + provider: "{{ cli }}" + + - name: Set vrrp gratuitous-arp interval + ce_vrrp: + gratuitous_arp_interval: 40 + mlag_id: 4 + provider: "{{ cli }}" + + - name: Set vrrp recover-delay + ce_vrrp: + recover_delay: 10 + provider: "{{ cli }}" + + - name: Set vrrp vrid virtual-ip + ce_vrrp: + interface: 40GE2/0/8 + vrid: 1 + virtual_ip: 10.14.2.7 + provider: "{{ cli }}" + + - name: Set vrrp vrid admin + ce_vrrp: + interface: 40GE2/0/8 + vrid: 1 + vrrp_type: admin + provider: "{{ cli }}" + + - name: Set vrrp vrid fast_resume + ce_vrrp: + interface: 40GE2/0/8 + vrid: 1 + fast_resume: enable + provider: "{{ cli }}" + + - name: Set vrrp vrid holding-multiplier + ce_vrrp: + interface: 40GE2/0/8 + vrid: 1 + holding_multiplier: 4 + provider: "{{ cli }}" + + - name: Set vrrp vrid preempt timer delay + ce_vrrp: + interface: 40GE2/0/8 + vrid: 1 + preempt_timer_delay: 10 + provider: "{{ cli }}" + + - name: Set vrrp vrid admin-vrrp + ce_vrrp: + interface: 40GE2/0/8 + vrid: 1 + admin_interface: 40GE2/0/9 + admin_vrid: 2 + vrrp_type: member + provider: "{{ cli }}" + + - name: Set vrrp vrid authentication-mode + ce_vrrp: + interface: 40GE2/0/8 + vrid: 1 + is_plain: true + auth_mode: simple + auth_key: aaa + provider: "{{ cli }}" +''' + +RETURN = ''' +changed: + description: check to see if a change was made on the device + returned: always + type: boolean + sample: true +proposed: + description: k/v pairs of parameters passed into module + returned: always + type: dict + sample: { + "auth_key": "aaa", + "auth_mode": "simple", + "interface": "40GE2/0/8", + "is_plain": true, + "state": "present", + "vrid": "1" + } +existing: + description: k/v pairs of existing aaa server + returned: always + type: dict + sample: { + "auth_mode": "none", + "interface": "40GE2/0/8", + "is_plain": "false", + "vrid": "1", + "vrrp_type": "normal" + } +end_state: + description: k/v pairs of aaa params after module execution + returned: always + type: dict + sample: { + "auth_mode": "simple", + "interface": "40GE2/0/8", + "is_plain": "true", + "vrid": "1", + "vrrp_type": "normal" + } +updates: + description: command sent to the device + returned: always + type: list + sample: { "interface 40GE2/0/8", + "vrrp vrid 1 authentication-mode simple plain aaa"} +''' + +from xml.etree import ElementTree +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.ce import get_nc_config, set_nc_config, ce_argument_spec + + +CE_NC_GET_VRRP_GROUP_INFO = """ + + + + + %s + %s + + + + +""" + +CE_NC_SET_VRRP_GROUP_INFO_HEAD = """ + + + + + %s + %s + +""" +CE_NC_SET_VRRP_GROUP_INFO_TAIL = """ + + + + + +""" +CE_NC_GET_VRRP_GLOBAL_INFO = """ + + + + + + + + + + + +""" + +CE_NC_SET_VRRP_GLOBAL_HEAD = """ + + + +""" +CE_NC_SET_VRRP_GLOBAL_TAIL = """ + + + + +""" + +CE_NC_GET_VRRP_VIRTUAL_IP_INFO = """ + + + + + %s + %s + + + + + + + + + + +""" +CE_NC_CREATE_VRRP_VIRTUAL_IP_INFO = """ + + + + + %s + %s + + + %s + + + + + + + +""" +CE_NC_DELETE_VRRP_VIRTUAL_IP_INFO = """ + + + + + %s + %s + + + %s + + + + + + + +""" + + +def is_valid_address(address): + """check ip-address is valid""" + + if address.find('.') != -1: + addr_list = address.split('.') + if len(addr_list) != 4: + return False + for each_num in addr_list: + if not each_num.isdigit(): + return False + if int(each_num) > 255: + return False + return True + + return False + + +def get_interface_type(interface): + """Gets the type of interface, such as 10GE, ETH-TRUNK, VLANIF...""" + + if interface is None: + return None + + iftype = None + + if interface.upper().startswith('GE'): + iftype = 'ge' + elif interface.upper().startswith('10GE'): + iftype = '10ge' + elif interface.upper().startswith('25GE'): + iftype = '25ge' + elif interface.upper().startswith('40GE'): + iftype = '40ge' + elif interface.upper().startswith('100GE'): + iftype = '100ge' + elif interface.upper().startswith('ETH-TRUNK'): + iftype = 'eth-trunk' + elif interface.upper().startswith('NULL'): + iftype = 'null' + elif interface.upper().startswith('VLANIF'): + iftype = 'vlanif' + else: + return None + + return iftype.lower() + + +class Vrrp(object): + """ + Manages Manages vrrp information. + """ + + def __init__(self, argument_spec): + self.spec = argument_spec + self.module = None + self.init_module() + + # module input info + self.interface = self.module.params['interface'] + self.vrid = self.module.params['vrid'] + self.virtual_ip = self.module.params['virtual_ip'] + self.vrrp_type = self.module.params['vrrp_type'] + self.admin_ignore_if_down = self.module.params['admin_ignore_if_down'] + self.admin_vrid = self.module.params['admin_vrid'] + self.admin_interface = self.module.params['admin_interface'] + self.admin_flowdown = self.module.params['admin_flowdown'] + self.priority = self.module.params['priority'] + self.version = self.module.params['version'] + self.advertise_interval = self.module.params['advertise_interval'] + self.preempt_timer_delay = self.module.params['preempt_timer_delay'] + self.gratuitous_arp_interval = self.module.params[ + 'gratuitous_arp_interval'] + self.recover_delay = self.module.params['recover_delay'] + self.holding_multiplier = self.module.params['holding_multiplier'] + self.auth_mode = self.module.params['auth_mode'] + self.is_plain = self.module.params['is_plain'] + self.auth_key = self.module.params['auth_key'] + self.fast_resume = self.module.params['fast_resume'] + self.state = self.module.params['state'] + + # vrrp info + self.vrrp_global_info = None + self.virtual_ip_info = None + self.vrrp_group_info = None + + # state + self.changed = False + self.updates_cmd = list() + self.results = dict() + self.existing = dict() + self.proposed = dict() + self.end_state = dict() + + def init_module(self): + """ init module """ + + self.module = AnsibleModule( + argument_spec=self.spec, supports_check_mode=True) + + def get_virtual_ip_info(self): + """ get vrrp virtual ip info.""" + virtual_ip_info = dict() + conf_str = CE_NC_GET_VRRP_VIRTUAL_IP_INFO % (self.vrid, self.interface) + xml_str = get_nc_config(self.module, conf_str) + if "" in xml_str: + return virtual_ip_info + else: + xml_str = xml_str.replace('\r', '').replace('\n', '').\ + replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\ + replace('xmlns="http://www.huawei.com/netconf/vrp"', "") + virtual_ip_info["vrrpVirtualIpInfos"] = list() + root = ElementTree.fromstring(xml_str) + vrrp_virtual_ip_infos = root.findall( + "data/vrrp/vrrpGroups/vrrpGroup/virtualIps/virtualIp") + if vrrp_virtual_ip_infos: + for vrrp_virtual_ip_info in vrrp_virtual_ip_infos: + virtual_ip_dict = dict() + for ele in vrrp_virtual_ip_info: + if ele.tag in ["virtualIpAddress"]: + virtual_ip_dict[ele.tag] = ele.text + virtual_ip_info["vrrpVirtualIpInfos"].append( + virtual_ip_dict) + return virtual_ip_info + + def get_vrrp_global_info(self): + """ get vrrp global info.""" + + vrrp_global_info = dict() + conf_str = CE_NC_GET_VRRP_GLOBAL_INFO + xml_str = get_nc_config(self.module, conf_str) + if "" in xml_str: + return vrrp_global_info + else: + xml_str = xml_str.replace('\r', '').replace('\n', '').\ + replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\ + replace('xmlns="http://www.huawei.com/netconf/vrp"', "") + + root = ElementTree.fromstring(xml_str) + global_info = root.findall( + "data/vrrp/vrrpGlobalCfg") + + if global_info: + for tmp in global_info: + for site in tmp: + if site.tag in ["gratuitousArpTimeOut", "gratuitousArpFlag", "recoverDelay", "version"]: + vrrp_global_info[site.tag] = site.text + return vrrp_global_info + + def get_vrrp_group_info(self): + """ get vrrp group info.""" + + vrrp_group_info = dict() + conf_str = CE_NC_GET_VRRP_GROUP_INFO % (self.interface, self.vrid) + xml_str = get_nc_config(self.module, conf_str) + if "" in xml_str: + return vrrp_group_info + else: + xml_str = xml_str.replace('\r', '').replace('\n', '').\ + replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\ + replace('xmlns="http://www.huawei.com/netconf/vrp"', "") + + root = ElementTree.fromstring(xml_str) + global_info = root.findall( + "data/vrrp/vrrpGroups/vrrpGroup") + + if global_info: + for tmp in global_info: + for site in tmp: + if site.tag in ["ifName", "vrrpId", "priority", "advertiseInterval", "preemptMode", "delayTime", + "authenticationMode", "authenticationKey", "vrrpType", "adminVrrpId", + "adminIfName", "adminIgnoreIfDown", "isPlain", "unflowdown", "fastResume", + "holdMultiplier"]: + vrrp_group_info[site.tag] = site.text + return vrrp_group_info + + def check_params(self): + """Check all input params""" + + # interface check + if self.interface: + intf_type = get_interface_type(self.interface) + if not intf_type: + self.module.fail_json( + msg='Error: Interface name of %s ' + 'is error.' % self.interface) + + # vrid check + if self.vrid: + if not self.vrid.isdigit(): + self.module.fail_json( + msg='Error: The value of vrid is an integer.') + if int(self.vrid) < 1 or int(self.vrid) > 255: + self.module.fail_json( + msg='Error: The value of vrid ranges from 1 to 255.') + + # virtual_ip check + if self.virtual_ip: + if not is_valid_address(self.virtual_ip): + self.module.fail_json( + msg='Error: The %s is not a valid ip address.' % self.virtual_ip) + + # admin_vrid check + if self.admin_vrid: + if not self.admin_vrid.isdigit(): + self.module.fail_json( + msg='Error: The value of admin_vrid is an integer.') + if int(self.admin_vrid) < 1 or int(self.admin_vrid) > 255: + self.module.fail_json( + msg='Error: The value of admin_vrid ranges from 1 to 255.') + + # admin_interface check + if self.admin_interface: + intf_type = get_interface_type(self.admin_interface) + if not intf_type: + self.module.fail_json( + msg='Error: Admin interface name of %s ' + 'is error.' % self.admin_interface) + + # priority check + if self.priority: + if not self.priority.isdigit(): + self.module.fail_json( + msg='Error: The value of priority is an integer.') + if int(self.priority) < 1 or int(self.priority) > 254: + self.module.fail_json( + msg='Error: The value of priority ranges from 1 to 254. The default value is 100.') + + # advertise_interval check + if self.advertise_interval: + if not self.advertise_interval.isdigit(): + self.module.fail_json( + msg='Error: The value of advertise_interval is an integer.') + if int(self.advertise_interval) < 1 or int(self.advertise_interval) > 255000: + self.module.fail_json( + msg='Error: The value of advertise_interval ranges from 1 to 255000. The default value is 1000.') + + # preempt_timer_delay check + if self.preempt_timer_delay: + if not self.preempt_timer_delay.isdigit(): + self.module.fail_json( + msg='Error: The value of preempt_timer_delay is an integer.') + if int(self.preempt_timer_delay) < 1 or int(self.preempt_timer_delay) > 3600: + self.module.fail_json( + msg='Error: The value of preempt_timer_delay ranges from 1 to 3600. The default value is 0.') + + # holding_multiplier check + if self.holding_multiplier: + if not self.holding_multiplier.isdigit(): + self.module.fail_json( + msg='Error: The value of holding_multiplier is an integer.') + if int(self.holding_multiplier) < 3 or int(self.holding_multiplier) > 10: + self.module.fail_json( + msg='Error: The value of holding_multiplier ranges from 3 to 10. The default value is 3.') + + # auth_key check + if self.auth_key: + if len(self.auth_key) > 16 \ + or len(self.auth_key.replace(' ', '')) < 1: + self.module.fail_json( + msg='Error: The length of auth_key is not in the range from 1 to 16.') + + def is_virtual_ip_change(self): + """whether virtual ip change""" + + if not self.virtual_ip_info: + return True + + for info in self.virtual_ip_info["vrrpVirtualIpInfos"]: + if info["virtualIpAddress"] == self.virtual_ip: + return False + return True + + def is_virtual_ip_exist(self): + """whether virtual ip info exist""" + + if not self.virtual_ip_info: + return False + + for info in self.virtual_ip_info["vrrpVirtualIpInfos"]: + if info["virtualIpAddress"] == self.virtual_ip: + return True + return False + + def is_vrrp_global_info_change(self): + """whether vrrp global attribute info change""" + + if not self.vrrp_global_info: + return True + + if self.gratuitous_arp_interval: + if self.vrrp_global_info["gratuitousArpFlag"] == "false": + self.module.fail_json(msg="Error: gratuitousArpFlag is false.") + if self.vrrp_global_info["gratuitousArpTimeOut"] != self.gratuitous_arp_interval: + return True + if self.recover_delay: + if self.vrrp_global_info["recoverDelay"] != self.recover_delay: + return True + if self.version: + if self.vrrp_global_info["version"] != self.version: + return True + return False + + def is_vrrp_global_info_exist(self): + """whether vrrp global attribute info exist""" + + if self.gratuitous_arp_interval or self.recover_delay or self.version: + if self.gratuitous_arp_interval: + if self.vrrp_global_info["gratuitousArpFlag"] == "false": + self.module.fail_json( + msg="Error: gratuitousArpFlag is false.") + if self.vrrp_global_info["gratuitousArpTimeOut"] != self.gratuitous_arp_interval: + return False + if self.recover_delay: + if self.vrrp_global_info["recoverDelay"] != self.recover_delay: + return False + if self.version: + if self.vrrp_global_info["version"] != self.version: + return False + return True + + return False + + def is_vrrp_group_info_change(self): + """whether vrrp group attribute info change""" + + if self.vrrp_type: + if self.vrrp_group_info["vrrpType"] != self.vrrp_type: + return True + if self.admin_ignore_if_down: + if self.vrrp_group_info["adminIgnoreIfDown"] != self.admin_ignore_if_down: + return True + if self.admin_vrid: + if self.vrrp_group_info["adminVrrpId"] != self.admin_vrid: + return True + if self.admin_interface: + if self.vrrp_group_info["adminIfName"] != self.admin_interface: + return True + if self.admin_flowdown: + if self.vrrp_group_info["unflowdown"] != self.admin_flowdown: + return True + if self.priority: + if self.vrrp_group_info["priority"] != self.priority: + return True + if self.fast_resume: + fast_resume = "false" + if self.fast_resume == "enable": + fast_resume = "true" + if self.vrrp_group_info["fastResume"] != fast_resume: + return True + if self.advertise_interval: + if self.vrrp_group_info["advertiseInterval"] != self.advertise_interval: + return True + if self.preempt_timer_delay: + if self.vrrp_group_info["delayTime"] != self.preempt_timer_delay: + return True + if self.holding_multiplier: + if self.vrrp_group_info["holdMultiplier"] != self.holding_multiplier: + return True + if self.auth_mode: + if self.vrrp_group_info["authenticationMode"] != self.auth_mode: + return True + if self.auth_key: + return True + if self.is_plain: + if self.vrrp_group_info["isPlain"] != self.is_plain: + return True + + return False + + def is_vrrp_group_info_exist(self): + """whether vrrp group attribute info exist""" + + if self.vrrp_type: + if self.vrrp_group_info["vrrpType"] != self.vrrp_type: + return False + if self.admin_ignore_if_down: + if self.vrrp_group_info["adminIgnoreIfDown"] != self.admin_ignore_if_down: + return False + if self.admin_vrid: + if self.vrrp_group_info["adminVrrpId"] != self.admin_vrid: + return False + if self.admin_interface: + if self.vrrp_group_info["adminIfName"] != self.admin_interface: + return False + if self.admin_flowdown: + if self.vrrp_group_info["unflowdown"] != self.admin_flowdown: + return False + if self.priority: + if self.vrrp_group_info["priority"] != self.priority: + return False + if self.fast_resume: + fast_resume = "false" + if self.fast_resume == "enable": + fast_resume = "true" + if self.vrrp_group_info["fastResume"] != fast_resume: + return False + if self.advertise_interval: + if self.vrrp_group_info["advertiseInterval"] != self.advertise_interval: + return False + if self.preempt_timer_delay: + if self.vrrp_group_info["delayTime"] != self.preempt_timer_delay: + return False + if self.holding_multiplier: + if self.vrrp_group_info["holdMultiplier"] != self.holding_multiplier: + return False + if self.auth_mode: + if self.vrrp_group_info["authenticationMode"] != self.auth_mode: + return False + if self.is_plain: + if self.vrrp_group_info["isPlain"] != self.is_plain: + return False + return True + + def create_virtual_ip(self): + """create virtual ip info""" + + if self.is_virtual_ip_change(): + conf_str = CE_NC_CREATE_VRRP_VIRTUAL_IP_INFO % ( + self.vrid, self.interface, self.virtual_ip) + recv_xml = set_nc_config(self.module, conf_str) + if "" not in recv_xml: + self.module.fail_json( + msg='Error: create virtual ip info failed.') + + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "vrrp vrid %s virtual-ip %s" % (self.vrid, self.virtual_ip)) + self.changed = True + + def delete_virtual_ip(self): + """delete virtual ip info""" + + if self.is_virtual_ip_exist(): + conf_str = CE_NC_DELETE_VRRP_VIRTUAL_IP_INFO % ( + self.vrid, self.interface, self.virtual_ip) + recv_xml = set_nc_config(self.module, conf_str) + if "" not in recv_xml: + self.module.fail_json( + msg='Error: delete virtual ip info failed.') + + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "undo vrrp vrid %s virtual-ip %s " % (self.vrid, self.virtual_ip)) + self.changed = True + + def set_vrrp_global(self): + """set vrrp global attribute info""" + + if self.is_vrrp_global_info_change(): + conf_str = CE_NC_SET_VRRP_GLOBAL_HEAD + if self.gratuitous_arp_interval: + conf_str += "%s" % self.gratuitous_arp_interval + if self.recover_delay: + conf_str += "%s" % self.recover_delay + if self.version: + conf_str += "%s" % self.version + conf_str += CE_NC_SET_VRRP_GLOBAL_TAIL + recv_xml = set_nc_config(self.module, conf_str) + if "" not in recv_xml: + self.module.fail_json( + msg='Error: set vrrp global atrribute info failed.') + + if self.gratuitous_arp_interval: + self.updates_cmd.append( + "vrrp gratuitous-arp interval %s" % self.gratuitous_arp_interval) + + if self.recover_delay: + self.updates_cmd.append( + "vrrp recover-delay %s" % self.recover_delay) + + if self.version: + version = "3" + if self.version == "v2": + version = "2" + self.updates_cmd.append("vrrp version %s" % version) + self.changed = True + + def delete_vrrp_global(self): + """delete vrrp global attribute info""" + + if self.is_vrrp_global_info_exist(): + conf_str = CE_NC_SET_VRRP_GLOBAL_HEAD + if self.gratuitous_arp_interval: + if self.gratuitous_arp_interval == "120": + self.module.fail_json( + msg='Error: The default value of gratuitous_arp_interval is 120.') + gratuitous_arp_interval = "120" + conf_str += "%s" % gratuitous_arp_interval + if self.recover_delay: + if self.recover_delay == "0": + self.module.fail_json( + msg='Error: The default value of recover_delay is 0.') + recover_delay = "0" + conf_str += "%s" % recover_delay + if self.version: + if self.version == "v2": + self.module.fail_json( + msg='Error: The default value of version is v2.') + version = "v2" + conf_str += "%s" % version + conf_str += CE_NC_SET_VRRP_GLOBAL_TAIL + recv_xml = set_nc_config(self.module, conf_str) + if "" not in recv_xml: + self.module.fail_json( + msg='Error: set vrrp global atrribute info failed.') + if self.gratuitous_arp_interval: + self.updates_cmd.append("undo vrrp gratuitous-arp interval") + + if self.recover_delay: + self.updates_cmd.append("undo vrrp recover-delay") + + if self.version == "v3": + self.updates_cmd.append("undo vrrp version") + self.changed = True + + def set_vrrp_group(self): + """set vrrp group attribute info""" + + if self.is_vrrp_group_info_change(): + conf_str = CE_NC_SET_VRRP_GROUP_INFO_HEAD % ( + self.interface, self.vrid) + if self.vrrp_type: + conf_str += "%s" % self.vrrp_type + if self.admin_vrid: + conf_str += "%s" % self.admin_vrid + if self.admin_interface: + conf_str += "%s" % self.admin_interface + if self.admin_flowdown is True or self.admin_flowdown is False: + admin_flowdown = "false" + if self.admin_flowdown is True: + admin_flowdown = "true" + conf_str += "%s" % admin_flowdown + if self.priority: + conf_str += "%s" % self.priority + if self.vrrp_type == "admin": + if self.admin_ignore_if_down is True or self.admin_ignore_if_down is False: + admin_ignore_if_down = "false" + if self.admin_ignore_if_down is True: + admin_ignore_if_down = "true" + conf_str += "%s" % admin_ignore_if_down + if self.fast_resume: + fast_resume = "false" + if self.fast_resume == "enable": + fast_resume = "true" + conf_str += "%s" % fast_resume + if self.advertise_interval: + conf_str += "%s" % self.advertise_interval + if self.preempt_timer_delay: + conf_str += "%s" % self.preempt_timer_delay + if self.holding_multiplier: + conf_str += "%s" % self.holding_multiplier + if self.auth_mode: + conf_str += "%s" % self.auth_mode + if self.auth_key: + conf_str += "%s" % self.auth_key + if self.auth_mode == "simple": + is_plain = "false" + if self.is_plain is True: + is_plain = "true" + conf_str += "%s" % is_plain + + conf_str += CE_NC_SET_VRRP_GROUP_INFO_TAIL + recv_xml = set_nc_config(self.module, conf_str) + if "" not in recv_xml: + self.module.fail_json( + msg='Error: set vrrp group atrribute info failed.') + + if self.interface and self.vrid: + if self.vrrp_type == "admin": + if self.admin_ignore_if_down is True: + self.updates_cmd.append( + "interface %s" % self.interface) + self.updates_cmd.append( + "vrrp vrid %s admin ignore-if-down" % self.vrid) + else: + self.updates_cmd.append( + "interface %s" % self.interface) + self.updates_cmd.append( + "vrrp vrid %s admin" % self.vrid) + + if self.priority: + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "vrrp vrid %s priority %s" % (self.vrid, self.priority)) + + if self.fast_resume == "enable": + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "vrrp vrid %s fast-resume" % self.vrid) + if self.fast_resume == "disable": + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "undo vrrp vrid %s fast-resume" % self.vrid) + + if self.advertise_interval: + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append("vrrp vrid %s timer advertise %s" % ( + self.vrid, self.advertise_interval)) + + if self.preempt_timer_delay: + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append("vrrp vrid %s preempt timer delay %s" % (self.vrid, + self.preempt_timer_delay)) + + if self.holding_multiplier: + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "vrrp vrid %s holding-multiplier %s" % (self.vrid, self.holding_multiplier)) + + if self.admin_vrid and self.admin_interface: + if self.admin_flowdown is True: + self.updates_cmd.append( + "interface %s" % self.interface) + self.updates_cmd.append("vrrp vrid %s track admin-vrrp interface %s vrid %s unflowdown" % + (self.vrid, self.admin_interface, self.admin_vrid)) + else: + self.updates_cmd.append( + "interface %s" % self.interface) + self.updates_cmd.append("vrrp vrid %s track admin-vrrp interface %s vrid %s" % + (self.vrid, self.admin_interface, self.admin_vrid)) + + if self.auth_mode and self.auth_key: + if self.auth_mode == "simple": + if self.is_plain is True: + self.updates_cmd.append( + "interface %s" % self.interface) + self.updates_cmd.append("vrrp vrid %s authentication-mode simple plain %s" % + (self.vrid, self.auth_key)) + else: + self.updates_cmd.append( + "interface %s" % self.interface) + self.updates_cmd.append("vrrp vrid %s authentication-mode simple cipher %s" % + (self.vrid, self.auth_key)) + if self.auth_mode == "md5": + self.updates_cmd.append( + "interface %s" % self.interface) + self.updates_cmd.append( + "vrrp vrid %s authentication-mode md5 %s" % (self.vrid, self.auth_key)) + self.changed = True + + def delete_vrrp_group(self): + """delete vrrp group attribute info""" + + if self.is_vrrp_group_info_exist(): + conf_str = CE_NC_SET_VRRP_GROUP_INFO_HEAD % ( + self.interface, self.vrid) + if self.vrrp_type: + vrrp_type = self.vrrp_type + if self.vrrp_type == "admin": + vrrp_type = "normal" + if self.vrrp_type == "member" and self.admin_vrid and self.admin_interface: + vrrp_type = "normal" + conf_str += "%s" % vrrp_type + if self.priority: + if self.priority == "100": + self.module.fail_json( + msg='Error: The default value of priority is 100.') + priority = "100" + conf_str += "%s" % priority + + if self.fast_resume: + fast_resume = "false" + if self.fast_resume == "enable": + fast_resume = "true" + conf_str += "%s" % fast_resume + if self.advertise_interval: + if self.advertise_interval == "1000": + self.module.fail_json( + msg='Error: The default value of advertise_interval is 1000.') + advertise_interval = "1000" + conf_str += "%s" % advertise_interval + if self.preempt_timer_delay: + if self.preempt_timer_delay == "0": + self.module.fail_json( + msg='Error: The default value of preempt_timer_delay is 0.') + preempt_timer_delay = "0" + conf_str += "%s" % preempt_timer_delay + if self.holding_multiplier: + if self.holding_multiplier == "0": + self.module.fail_json( + msg='Error: The default value of holding_multiplier is 3.') + holding_multiplier = "3" + conf_str += "%s" % holding_multiplier + if self.auth_mode: + auth_mode = self.auth_mode + if self.auth_mode == "md5" or self.auth_mode == "simple": + auth_mode = "none" + conf_str += "%s" % auth_mode + + conf_str += CE_NC_SET_VRRP_GROUP_INFO_TAIL + recv_xml = set_nc_config(self.module, conf_str) + if "" not in recv_xml: + self.module.fail_json( + msg='Error: set vrrp global atrribute info failed.') + if self.interface and self.vrid: + if self.vrrp_type == "admin": + self.updates_cmd.append( + "undo vrrp vrid %s admin" % self.vrid) + + if self.priority: + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "undo vrrp vrid %s priority" % self.vrid) + + if self.fast_resume: + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "undo vrrp vrid %s fast-resume" % self.vrid) + + if self.advertise_interval: + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "undo vrrp vrid %s timer advertise" % self.vrid) + + if self.preempt_timer_delay: + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "undo vrrp vrid %s preempt timer delay" % self.vrid) + + if self.holding_multiplier: + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "undo vrrp vrid %s holding-multiplier" % self.vrid) + + if self.admin_vrid and self.admin_interface: + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "undo vrrp vrid %s track admin-vrrp" % self.vrid) + + if self.auth_mode: + self.updates_cmd.append("interface %s" % self.interface) + self.updates_cmd.append( + "undo vrrp vrid %s authentication-mode" % self.vrid) + self.changed = True + + def get_proposed(self): + """get proposed info""" + + if self.interface: + self.proposed["interface"] = self.interface + if self.vrid: + self.proposed["vrid"] = self.vrid + if self.virtual_ip: + self.proposed["virtual_ip"] = self.virtual_ip + if self.vrrp_type: + self.proposed["vrrp_type"] = self.vrrp_type + if self.admin_vrid: + self.proposed["admin_vrid"] = self.admin_vrid + if self.admin_interface: + self.proposed["admin_interface"] = self.admin_interface + if self.admin_flowdown: + self.proposed["unflowdown"] = self.admin_flowdown + if self.admin_ignore_if_down: + self.proposed["admin_ignore_if_down"] = self.admin_ignore_if_down + if self.priority: + self.proposed["priority"] = self.priority + if self.version: + self.proposed["version"] = self.version + if self.advertise_interval: + self.proposed["advertise_interval"] = self.advertise_interval + if self.preempt_timer_delay: + self.proposed["preempt_timer_delay"] = self.preempt_timer_delay + if self.gratuitous_arp_interval: + self.proposed[ + "gratuitous_arp_interval"] = self.gratuitous_arp_interval + if self.recover_delay: + self.proposed["recover_delay"] = self.recover_delay + if self.holding_multiplier: + self.proposed["holding_multiplier"] = self.holding_multiplier + if self.auth_mode: + self.proposed["auth_mode"] = self.auth_mode + if self.is_plain: + self.proposed["is_plain"] = self.is_plain + if self.auth_key: + self.proposed["auth_key"] = self.auth_key + if self.fast_resume: + self.proposed["fast_resume"] = self.fast_resume + if self.state: + self.proposed["state"] = self.state + + def get_existing(self): + """get existing info""" + + if self.gratuitous_arp_interval: + self.existing["gratuitous_arp_interval"] = self.vrrp_global_info[ + "gratuitousArpTimeOut"] + if self.version: + self.existing["version"] = self.vrrp_global_info["version"] + if self.recover_delay: + self.existing["recover_delay"] = self.vrrp_global_info[ + "recoverDelay"] + + if self.virtual_ip: + if self.virtual_ip_info: + self.existing["interface"] = self.interface + self.existing["vrid"] = self.vrid + self.existing["virtual_ip_info"] = self.virtual_ip_info[ + "vrrpVirtualIpInfos"] + + if self.vrrp_group_info: + self.existing["interface"] = self.vrrp_group_info["ifName"] + self.existing["vrid"] = self.vrrp_group_info["vrrpId"] + self.existing["vrrp_type"] = self.vrrp_group_info["vrrpType"] + if self.vrrp_type == "admin": + self.existing["admin_ignore_if_down"] = self.vrrp_group_info[ + "authenticationMode"] + if self.admin_vrid and self.admin_interface: + self.existing["admin_vrid"] = self.vrrp_group_info[ + "adminVrrpId"] + self.existing["admin_interface"] = self.vrrp_group_info[ + "adminIfName"] + self.existing["admin_flowdown"] = self.vrrp_group_info[ + "unflowdown"] + if self.priority: + self.existing["priority"] = self.vrrp_group_info["priority"] + if self.advertise_interval: + self.existing["advertise_interval"] = self.vrrp_group_info[ + "advertiseInterval"] + if self.preempt_timer_delay: + self.existing["preempt_timer_delay"] = self.vrrp_group_info[ + "delayTime"] + if self.holding_multiplier: + self.existing["holding_multiplier"] = self.vrrp_group_info[ + "holdMultiplier"] + if self.fast_resume: + fast_resume_exist = "disable" + fast_resume = self.vrrp_group_info["fastResume"] + if fast_resume == "true": + fast_resume_exist = "enable" + self.existing["fast_resume"] = fast_resume_exist + if self.auth_mode: + self.existing["auth_mode"] = self.vrrp_group_info[ + "authenticationMode"] + self.existing["is_plain"] = self.vrrp_group_info["isPlain"] + + def get_end_state(self): + """get end state info""" + + if self.gratuitous_arp_interval or self.version or self.recover_delay: + self.vrrp_global_info = self.get_vrrp_global_info() + if self.interface and self.vrid: + if self.virtual_ip: + self.virtual_ip_info = self.get_virtual_ip_info() + if self.virtual_ip_info: + self.vrrp_group_info = self.get_vrrp_group_info() + + if self.gratuitous_arp_interval: + self.end_state["gratuitous_arp_interval"] = self.vrrp_global_info[ + "gratuitousArpTimeOut"] + if self.version: + self.end_state["version"] = self.vrrp_global_info["version"] + if self.recover_delay: + self.end_state["recover_delay"] = self.vrrp_global_info[ + "recoverDelay"] + + if self.virtual_ip: + if self.virtual_ip_info: + self.end_state["interface"] = self.interface + self.end_state["vrid"] = self.vrid + self.end_state["virtual_ip_info"] = self.virtual_ip_info[ + "vrrpVirtualIpInfos"] + + if self.vrrp_group_info: + self.end_state["interface"] = self.vrrp_group_info["ifName"] + self.end_state["vrid"] = self.vrrp_group_info["vrrpId"] + self.end_state["vrrp_type"] = self.vrrp_group_info["vrrpType"] + if self.vrrp_type == "admin": + self.end_state["admin_ignore_if_down"] = self.vrrp_group_info[ + "authenticationMode"] + if self.admin_vrid and self.admin_interface: + self.existing["admin_vrid"] = self.vrrp_group_info[ + "adminVrrpId"] + self.end_state["admin_interface"] = self.vrrp_group_info[ + "adminIfName"] + self.end_state["admin_flowdown"] = self.vrrp_group_info[ + "unflowdown"] + if self.priority: + self.end_state["priority"] = self.vrrp_group_info["priority"] + if self.advertise_interval: + self.end_state["advertise_interval"] = self.vrrp_group_info[ + "advertiseInterval"] + if self.preempt_timer_delay: + self.end_state["preempt_timer_delay"] = self.vrrp_group_info[ + "delayTime"] + if self.holding_multiplier: + self.end_state["holding_multiplier"] = self.vrrp_group_info[ + "holdMultiplier"] + if self.fast_resume: + fast_resume_end = "disable" + fast_resume = self.vrrp_group_info["fastResume"] + if fast_resume == "true": + fast_resume_end = "enable" + self.end_state["fast_resume"] = fast_resume_end + if self.auth_mode: + self.end_state["auth_mode"] = self.vrrp_group_info[ + "authenticationMode"] + self.end_state["is_plain"] = self.vrrp_group_info["isPlain"] + + def work(self): + """worker""" + + self.check_params() + if self.gratuitous_arp_interval or self.version or self.recover_delay: + self.vrrp_global_info = self.get_vrrp_global_info() + if self.interface and self.vrid: + self.virtual_ip_info = self.get_virtual_ip_info() + if self.virtual_ip_info: + self.vrrp_group_info = self.get_vrrp_group_info() + self.get_proposed() + self.get_existing() + + if self.gratuitous_arp_interval or self.version or self.recover_delay: + if self.state == "present": + self.set_vrrp_global() + else: + self.delete_vrrp_global() + else: + if not self.interface or not self.vrid: + self.module.fail_json( + msg='Error: interface, vrid must be config at the same time.') + + if self.interface and self.vrid: + if self.virtual_ip: + if self.state == "present": + self.create_virtual_ip() + else: + self.delete_virtual_ip() + else: + if not self.vrrp_group_info: + self.module.fail_json( + msg='Error: The VRRP group does not exist.') + if self.admin_ignore_if_down is True: + if self.vrrp_type != "admin": + self.module.fail_json( + msg='Error: vrrpType must be admin when admin_ignore_if_down is true.') + if self.admin_interface or self.admin_vrid: + if self.vrrp_type != "member": + self.module.fail_json( + msg='Error: it binds a VRRP group to an mVRRP group, vrrp_type must be "member".') + if not self.vrrp_type or not self.interface or not self.vrid: + self.module.fail_json( + msg='Error: admin_interface admin_vrid vrrp_type interface vrid must ' + 'be config at the same time.') + if self.auth_mode == "md5" and self.is_plain is True: + self.module.fail_json( + msg='Error: is_plain can not be True when auth_mode is md5.') + + if self.state == "present": + self.set_vrrp_group() + else: + self.delete_vrrp_group() + + self.get_end_state() + self.results['changed'] = self.changed + self.results['proposed'] = self.proposed + self.results['existing'] = self.existing + self.results['end_state'] = self.end_state + if self.changed: + self.results['updates'] = self.updates_cmd + else: + self.results['updates'] = list() + + self.module.exit_json(**self.results) + + +def main(): + """ Module main """ + + argument_spec = dict( + interface=dict(type='str'), + vrid=dict(type='str'), + virtual_ip=dict(type='str'), + vrrp_type=dict(type='str', choices=['normal', 'member', 'admin']), + admin_ignore_if_down=dict(type='bool', default=False), + admin_vrid=dict(type='str'), + admin_interface=dict(type='str'), + admin_flowdown=dict(type='bool', default=False), + priority=dict(type='str'), + version=dict(type='str', choices=['v2', 'v3']), + advertise_interval=dict(type='str'), + preempt_timer_delay=dict(type='str'), + gratuitous_arp_interval=dict(type='str'), + recover_delay=dict(type='str'), + holding_multiplier=dict(type='str'), + auth_mode=dict(type='str', choices=['simple', 'md5', 'none']), + is_plain=dict(type='bool', default=False), + auth_key=dict(type='str'), + fast_resume=dict(type='str', choices=['enable', 'disable']), + state=dict(type='str', default='present', + choices=['present', 'absent']) + ) + + argument_spec.update(ce_argument_spec) + module = Vrrp(argument_spec=argument_spec) + module.work() + + +if __name__ == '__main__': + main()