#!/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 . # from __future__ import (absolute_import, division, print_function) __metaclass__ = type ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} DOCUMENTATION = ''' --- module: ce_acl_advance short_description: Manages advanced ACL configuration on HUAWEI CloudEngine switches. description: - Manages advanced ACL configurations on HUAWEI CloudEngine switches. author: - wangdezhuang (@QijunPan) notes: - This module requires the netconf system service be enabled on the remote device being managed. - Recommended connection is C(netconf). - This module also works with C(local) connections for legacy playbooks. options: state: description: - Specify desired state of the resource. required: false default: present choices: ['present','absent','delete_acl'] acl_name: description: - ACL number or name. For a numbered rule group, the value ranging from 3000 to 3999 indicates a advance ACL. For a named rule group, the value is a string of 1 to 32 case-sensitive characters starting with a letter, spaces not supported. required: true acl_num: description: - ACL number. The value is an integer ranging from 3000 to 3999. acl_step: description: - ACL step. The value is an integer ranging from 1 to 20. The default value is 5. acl_description: description: - ACL description. The value is a string of 1 to 127 characters. rule_name: description: - Name of a basic ACL rule. The value is a string of 1 to 32 characters. rule_id: description: - ID of a basic ACL rule in configuration mode. The value is an integer ranging from 0 to 4294967294. rule_action: description: - Matching mode of basic ACL rules. choices: ['permit','deny'] protocol: description: - Protocol type. choices: ['ip', 'icmp', 'igmp', 'ipinip', 'tcp', 'udp', 'gre', 'ospf'] source_ip: description: - Source IP address. The value is a string of 0 to 255 characters.The default value is 0.0.0.0. The value is in dotted decimal notation. src_mask: description: - Source IP address mask. The value is an integer ranging from 1 to 32. src_pool_name: description: - Name of a source pool. The value is a string of 1 to 32 characters. dest_ip: description: - Destination IP address. The value is a string of 0 to 255 characters.The default value is 0.0.0.0. The value is in dotted decimal notation. dest_mask: description: - Destination IP address mask. The value is an integer ranging from 1 to 32. dest_pool_name: description: - Name of a destination pool. The value is a string of 1 to 32 characters. src_port_op: description: - Range type of the source port. choices: ['lt','eq', 'gt', 'range'] src_port_begin: description: - Start port number of the source port. The value is an integer ranging from 0 to 65535. src_port_end: description: - End port number of the source port. The value is an integer ranging from 0 to 65535. src_port_pool_name: description: - Name of a source port pool. The value is a string of 1 to 32 characters. dest_port_op: description: - Range type of the destination port. choices: ['lt','eq', 'gt', 'range'] dest_port_begin: description: - Start port number of the destination port. The value is an integer ranging from 0 to 65535. dest_port_end: description: - End port number of the destination port. The value is an integer ranging from 0 to 65535. dest_port_pool_name: description: - Name of a destination port pool. The value is a string of 1 to 32 characters. frag_type: description: - Type of packet fragmentation. choices: ['fragment', 'clear_fragment'] precedence: description: - Data packets can be filtered based on the priority field. The value is an integer ranging from 0 to 7. tos: description: - ToS value on which data packet filtering is based. The value is an integer ranging from 0 to 15. dscp: description: - Differentiated Services Code Point. The value is an integer ranging from 0 to 63. icmp_name: description: - ICMP name. choices: ['unconfiged', 'echo', 'echo-reply', 'fragmentneed-DFset', 'host-redirect', 'host-tos-redirect', 'host-unreachable', 'information-reply', 'information-request', 'net-redirect', 'net-tos-redirect', 'net-unreachable', 'parameter-problem', 'port-unreachable', 'protocol-unreachable', 'reassembly-timeout', 'source-quench', 'source-route-failed', 'timestamp-reply', 'timestamp-request', 'ttl-exceeded', 'address-mask-reply', 'address-mask-request', 'custom'] icmp_type: description: - ICMP type. This parameter is available only when the packet protocol is ICMP. The value is an integer ranging from 0 to 255. icmp_code: description: - ICMP message code. Data packets can be filtered based on the ICMP message code. The value is an integer ranging from 0 to 255. ttl_expired: description: - Whether TTL Expired is matched, with the TTL value of 1. type: bool default: 'no' vrf_name: description: - VPN instance name. The value is a string of 1 to 31 characters.The default value is _public_. syn_flag: description: - TCP flag value. The value is an integer ranging from 0 to 63. tcp_flag_mask: description: - TCP flag mask value. The value is an integer ranging from 0 to 63. established: description: - Match established connections. type: bool default: 'no' time_range: description: - Name of a time range in which an ACL rule takes effect. rule_description: description: - Description about an ACL rule. igmp_type: description: - Internet Group Management Protocol. choices: ['host-query', 'mrouter-adver', 'mrouter-solic', 'mrouter-termi', 'mtrace-resp', 'mtrace-route', 'v1host-report', 'v2host-report', 'v2leave-group', 'v3host-report'] log_flag: description: - Flag of logging matched data packets. type: bool default: 'no' ''' EXAMPLES = ''' - name: CloudEngine advance acl 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: "Config ACL" ce_acl_advance: state: present acl_name: 3200 provider: "{{ cli }}" - name: "Undo ACL" ce_acl_advance: state: delete_acl acl_name: 3200 provider: "{{ cli }}" - name: "Config ACL advance rule" ce_acl_advance: state: present acl_name: test rule_name: test_rule rule_id: 111 rule_action: permit protocol: tcp source_ip: 10.10.10.10 src_mask: 24 frag_type: fragment provider: "{{ cli }}" - name: "Undo ACL advance rule" ce_acl_advance: state: absent acl_name: test rule_name: test_rule rule_id: 111 rule_action: permit protocol: tcp source_ip: 10.10.10.10 src_mask: 24 frag_type: fragment provider: "{{ cli }}" ''' RETURN = ''' changed: description: check to see if a change was made on the device returned: always type: bool sample: true proposed: description: k/v pairs of parameters passed into module returned: always type: dict sample: {"acl_name": "test", "state": "delete_acl"} existing: description: k/v pairs of existing aaa server returned: always type: dict sample: {"aclNumOrName": "test", "aclType": "Advance"} end_state: description: k/v pairs of aaa params after module execution returned: always type: dict sample: {} updates: description: command sent to the device returned: always type: list sample: ["undo acl name test"] ''' from xml.etree import ElementTree from ansible.module_utils.basic import AnsibleModule from ansible_collections.community.general.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec, check_ip_addr # get acl CE_GET_ACL_HEADER = """ """ CE_GET_ACL_TAIL = """ """ # merge acl CE_MERGE_ACL_HEADER = """ %s """ CE_MERGE_ACL_TAIL = """ """ # delete acl CE_DELETE_ACL_HEADER = """ %s """ CE_DELETE_ACL_TAIL = """ """ # get acl advance rule CE_GET_ACL_ADVANCE_RULE_HEADER = """ %s """ CE_GET_ACL_ADVANCE_RULE_TAIL = """ """ # merge acl advance rule CE_MERGE_ACL_ADVANCE_RULE_HEADER = """ %s %s """ CE_MERGE_ACL_ADVANCE_RULE_TAIL = """ """ # delete acl advance rule CE_DELETE_ACL_ADVANCE_RULE_HEADER = """ %s %s """ CE_DELETE_ACL_ADVANCE_RULE_TAIL = """ """ PROTOCOL_NUM = {"ip": "0", "icmp": "1", "igmp": "2", "ipinip": "4", "tcp": "6", "udp": "17", "gre": "47", "ospf": "89"} IGMP_TYPE_NUM = {"host-query": "17", "mrouter-adver": "48", "mrouter-solic": "49", "mrouter-termi": "50", "mtrace-resp": "30", "mtrace-route": "31", "v1host-report": "18", "v2host-report": "22", "v2leave-group": "23", "v3host-report": "34"} def get_wildcard_mask(mask): """ convert mask length to ip address wildcard mask, i.e. 24 to 0.0.0.255 """ mask_int = ["255"] * 4 value = int(mask) if value > 32: return None if value < 8: mask_int[0] = str(int(~(0xFF << (8 - value % 8)) & 0xFF)) if value >= 8: mask_int[0] = '0' mask_int[1] = str(int(~(0xFF << (16 - (value % 16))) & 0xFF)) if value >= 16: mask_int[1] = '0' mask_int[2] = str(int(~(0xFF << (24 - (value % 24))) & 0xFF)) if value >= 24: mask_int[2] = '0' mask_int[3] = str(int(~(0xFF << (32 - (value % 32))) & 0xFF)) if value == 32: mask_int[3] = '0' return '.'.join(mask_int) class AdvanceAcl(object): """ Manages advance acl configuration """ def __init__(self, **kwargs): """ Class init """ # argument spec argument_spec = kwargs["argument_spec"] self.spec = argument_spec self.module = AnsibleModule(argument_spec=self.spec, supports_check_mode=True) # module args self.state = self.module.params['state'] self.acl_name = self.module.params['acl_name'] or None self.acl_num = self.module.params['acl_num'] or None self.acl_type = None self.acl_step = self.module.params['acl_step'] or None self.acl_description = self.module.params['acl_description'] or None self.rule_name = self.module.params['rule_name'] or None self.rule_id = self.module.params['rule_id'] or None self.rule_action = self.module.params['rule_action'] or None self.protocol = self.module.params['protocol'] or None self.protocol_num = None self.source_ip = self.module.params['source_ip'] or None self.src_mask = self.module.params['src_mask'] or None self.src_wild = None self.src_pool_name = self.module.params['src_pool_name'] or None self.dest_ip = self.module.params['dest_ip'] or None self.dest_mask = self.module.params['dest_mask'] or None self.dest_wild = None self.dest_pool_name = self.module.params['dest_pool_name'] or None self.src_port_op = self.module.params['src_port_op'] or None self.src_port_begin = self.module.params['src_port_begin'] or None self.src_port_end = self.module.params['src_port_end'] or None self.src_port_pool_name = self.module.params[ 'src_port_pool_name'] or None self.dest_port_op = self.module.params['dest_port_op'] or None self.dest_port_begin = self.module.params['dest_port_begin'] or None self.dest_port_end = self.module.params['dest_port_end'] or None self.dest_port_pool_name = self.module.params[ 'dest_port_pool_name'] or None self.frag_type = self.module.params['frag_type'] or None self.precedence = self.module.params['precedence'] or None self.tos = self.module.params['tos'] or None self.dscp = self.module.params['dscp'] or None self.icmp_name = self.module.params['icmp_name'] or None self.icmp_type = self.module.params['icmp_type'] or None self.icmp_code = self.module.params['icmp_code'] or None self.ttl_expired = self.module.params['ttl_expired'] self.vrf_name = self.module.params['vrf_name'] or None self.syn_flag = self.module.params['syn_flag'] or None self.tcp_flag_mask = self.module.params['tcp_flag_mask'] or None self.established = self.module.params['established'] self.time_range = self.module.params['time_range'] or None self.rule_description = self.module.params['rule_description'] or None self.igmp_type = self.module.params['igmp_type'] or None self.igmp_type_num = None self.log_flag = self.module.params['log_flag'] self.precedence_name = dict() self.precedence_name["0"] = "routine" self.precedence_name["1"] = "priority" self.precedence_name["2"] = "immediate" self.precedence_name["3"] = "flash" self.precedence_name["4"] = "flash-override" self.precedence_name["5"] = "critical" self.precedence_name["6"] = "internet" self.precedence_name["7"] = "network" # cur config self.cur_acl_cfg = dict() self.cur_advance_rule_cfg = dict() # state self.changed = False self.updates_cmd = list() self.results = dict() self.proposed = dict() self.existing = dict() self.end_state = dict() def netconf_get_config(self, conf_str): """ Get configure by netconf """ xml_str = get_nc_config(self.module, conf_str) return xml_str def netconf_set_config(self, conf_str): """ Set configure by netconf """ xml_str = set_nc_config(self.module, conf_str) return xml_str def get_protocol_num(self): """ Get protocol num by name """ if self.protocol: self.protocol_num = PROTOCOL_NUM.get(self.protocol) def get_igmp_type_num(self): """ Get igmp type num by type """ if self.igmp_type: self.igmp_type_num = IGMP_TYPE_NUM.get(self.igmp_type) def check_acl_args(self): """ Check acl invalid args """ need_cfg = False find_flag = False self.cur_acl_cfg["acl_info"] = [] if self.acl_name: if self.acl_name.isdigit(): if int(self.acl_name) < 3000 or int(self.acl_name) > 3999: self.module.fail_json( msg='Error: The value of acl_name is out of [3000-3999] for advance ACL.') if self.acl_num: self.module.fail_json( msg='Error: The acl_name is digit, so should not input acl_num at the same time.') else: self.acl_type = "Advance" if len(self.acl_name) < 1 or len(self.acl_name) > 32: self.module.fail_json( msg='Error: The len of acl_name is out of [1 - 32].') if self.state == "present": if not self.acl_num and not self.acl_type and not self.rule_name: self.module.fail_json( msg='Error: Please input acl_num or acl_type when config ACL.') if self.acl_num: if self.acl_num.isdigit(): if int(self.acl_num) < 3000 or int(self.acl_num) > 3999: self.module.fail_json( msg='Error: The value of acl_name is out of [3000-3999] for advance ACL.') else: self.module.fail_json( msg='Error: The acl_num is not digit.') if self.acl_step: if self.acl_step.isdigit(): if int(self.acl_step) < 1 or int(self.acl_step) > 20: self.module.fail_json( msg='Error: The value of acl_step is out of [1 - 20].') else: self.module.fail_json( msg='Error: The acl_step is not digit.') if self.acl_description: if len(self.acl_description) < 1 or len(self.acl_description) > 127: self.module.fail_json( msg='Error: The len of acl_description is out of [1 - 127].') conf_str = CE_GET_ACL_HEADER if self.acl_type: conf_str += "" if self.acl_num or self.acl_name.isdigit(): conf_str += "" if self.acl_step: conf_str += "" if self.acl_description: conf_str += "" conf_str += CE_GET_ACL_TAIL recv_xml = self.netconf_get_config(conf_str=conf_str) if "" in recv_xml: find_flag = False else: xml_str = recv_xml.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) # parse acl acl_info = root.findall( "acl/aclGroups/aclGroup") if acl_info: for tmp in acl_info: tmp_dict = dict() for site in tmp: if site.tag in ["aclNumOrName", "aclType", "aclNumber", "aclStep", "aclDescription"]: tmp_dict[site.tag] = site.text self.cur_acl_cfg["acl_info"].append(tmp_dict) if self.cur_acl_cfg["acl_info"]: find_list = list() for tmp in self.cur_acl_cfg["acl_info"]: cur_cfg_dict = dict() exist_cfg_dict = dict() if self.acl_name: if self.acl_name.isdigit() and tmp.get("aclNumber"): cur_cfg_dict["aclNumber"] = self.acl_name exist_cfg_dict["aclNumber"] = tmp.get("aclNumber") else: cur_cfg_dict["aclNumOrName"] = self.acl_name exist_cfg_dict["aclNumOrName"] = tmp.get("aclNumOrName") if self.acl_type: cur_cfg_dict["aclType"] = self.acl_type exist_cfg_dict["aclType"] = tmp.get("aclType") if self.acl_num: cur_cfg_dict["aclNumber"] = self.acl_num exist_cfg_dict["aclNumber"] = tmp.get("aclNumber") if self.acl_step: cur_cfg_dict["aclStep"] = self.acl_step exist_cfg_dict["aclStep"] = tmp.get("aclStep") if self.acl_description: cur_cfg_dict["aclDescription"] = self.acl_description exist_cfg_dict["aclDescription"] = tmp.get("aclDescription") if cur_cfg_dict == exist_cfg_dict: find_bool = True else: find_bool = False find_list.append(find_bool) for mem in find_list: if mem: find_flag = True break else: find_flag = False else: find_flag = False if self.state == "present": need_cfg = bool(not find_flag) elif self.state == "delete_acl": need_cfg = bool(find_flag) else: need_cfg = False self.cur_acl_cfg["need_cfg"] = need_cfg def check_advance_rule_args(self): """ Check advance rule invalid args """ need_cfg = False find_flag = False self.cur_advance_rule_cfg["adv_rule_info"] = [] if self.acl_name: if self.state == "absent": if not self.rule_name: self.module.fail_json( msg='Error: Please input rule_name when state is absent.') # config rule if self.rule_name: if len(self.rule_name) < 1 or len(self.rule_name) > 32: self.module.fail_json( msg='Error: The len of rule_name is out of [1 - 32].') if self.state != "delete_acl" and not self.rule_id: self.module.fail_json( msg='Error: Please input rule_id.') if self.rule_id: if self.rule_id.isdigit(): if int(self.rule_id) < 0 or int(self.rule_id) > 4294967294: self.module.fail_json( msg='Error: The value of rule_id is out of [0 - 4294967294].') else: self.module.fail_json( msg='Error: The rule_id is not digit.') if self.rule_action and not self.protocol: self.module.fail_json( msg='Error: The rule_action and the protocol must input at the same time.') if not self.rule_action and self.protocol: self.module.fail_json( msg='Error: The rule_action and the protocol must input at the same time.') if self.protocol: self.get_protocol_num() if self.source_ip: if not check_ip_addr(self.source_ip): self.module.fail_json( msg='Error: The source_ip %s is invalid.' % self.source_ip) if not self.src_mask: self.module.fail_json( msg='Error: Please input src_mask.') if self.src_mask: if self.src_mask.isdigit(): if int(self.src_mask) < 1 or int(self.src_mask) > 32: self.module.fail_json( msg='Error: The value of src_mask is out of [1 - 32].') self.src_wild = get_wildcard_mask(self.src_mask) else: self.module.fail_json( msg='Error: The src_mask is not digit.') if self.src_pool_name: if len(self.src_pool_name) < 1 or len(self.src_pool_name) > 32: self.module.fail_json( msg='Error: The len of src_pool_name is out of [1 - 32].') if self.dest_ip: if not check_ip_addr(self.dest_ip): self.module.fail_json( msg='Error: The dest_ip %s is invalid.' % self.dest_ip) if not self.dest_mask: self.module.fail_json( msg='Error: Please input dest_mask.') if self.dest_mask: if self.dest_mask.isdigit(): if int(self.dest_mask) < 1 or int(self.dest_mask) > 32: self.module.fail_json( msg='Error: The value of dest_mask is out of [1 - 32].') self.dest_wild = get_wildcard_mask(self.dest_mask) else: self.module.fail_json( msg='Error: The dest_mask is not digit.') if self.dest_pool_name: if len(self.dest_pool_name) < 1 or len(self.dest_pool_name) > 32: self.module.fail_json( msg='Error: The len of dest_pool_name is out of [1 - 32].') if self.src_port_op: if self.src_port_op == "lt": if not self.src_port_end: self.module.fail_json( msg='Error: The src_port_end must input.') if self.src_port_begin: self.module.fail_json( msg='Error: The src_port_begin should not input.') if self.src_port_op == "eq" or self.src_port_op == "gt": if not self.src_port_begin: self.module.fail_json( msg='Error: The src_port_begin must input.') if self.src_port_end: self.module.fail_json( msg='Error: The src_port_end should not input.') if self.src_port_op == "range": if not self.src_port_begin or not self.src_port_end: self.module.fail_json( msg='Error: The src_port_begin and src_port_end must input.') if self.src_port_begin: if self.src_port_begin.isdigit(): if int(self.src_port_begin) < 0 or int(self.src_port_begin) > 65535: self.module.fail_json( msg='Error: The value of src_port_begin is out of [0 - 65535].') else: self.module.fail_json( msg='Error: The src_port_begin is not digit.') if self.src_port_end: if self.src_port_end.isdigit(): if int(self.src_port_end) < 0 or int(self.src_port_end) > 65535: self.module.fail_json( msg='Error: The value of src_port_end is out of [0 - 65535].') else: self.module.fail_json( msg='Error: The src_port_end is not digit.') if self.src_port_pool_name: if len(self.src_port_pool_name) < 1 or len(self.src_port_pool_name) > 32: self.module.fail_json( msg='Error: The len of src_port_pool_name is out of [1 - 32].') if self.dest_port_op: if self.dest_port_op == "lt": if not self.dest_port_end: self.module.fail_json( msg='Error: The dest_port_end must input.') if self.dest_port_begin: self.module.fail_json( msg='Error: The dest_port_begin should not input.') if self.dest_port_op == "eq" or self.dest_port_op == "gt": if not self.dest_port_begin: self.module.fail_json( msg='Error: The dest_port_begin must input.') if self.dest_port_end: self.module.fail_json( msg='Error: The dest_port_end should not input.') if self.dest_port_op == "range": if not self.dest_port_begin or not self.dest_port_end: self.module.fail_json( msg='Error: The dest_port_begin and dest_port_end must input.') if self.dest_port_begin: if self.dest_port_begin.isdigit(): if int(self.dest_port_begin) < 0 or int(self.dest_port_begin) > 65535: self.module.fail_json( msg='Error: The value of dest_port_begin is out of [0 - 65535].') else: self.module.fail_json( msg='Error: The dest_port_begin is not digit.') if self.dest_port_end: if self.dest_port_end.isdigit(): if int(self.dest_port_end) < 0 or int(self.dest_port_end) > 65535: self.module.fail_json( msg='Error: The value of dest_port_end is out of [0 - 65535].') else: self.module.fail_json( msg='Error: The dest_port_end is not digit.') if self.dest_port_pool_name: if len(self.dest_port_pool_name) < 1 or len(self.dest_port_pool_name) > 32: self.module.fail_json( msg='Error: The len of dest_port_pool_name is out of [1 - 32].') if self.precedence: if self.precedence.isdigit(): if int(self.precedence) < 0 or int(self.precedence) > 7: self.module.fail_json( msg='Error: The value of precedence is out of [0 - 7].') else: self.module.fail_json( msg='Error: The precedence is not digit.') if self.tos: if self.tos.isdigit(): if int(self.tos) < 0 or int(self.tos) > 15: self.module.fail_json( msg='Error: The value of tos is out of [0 - 15].') else: self.module.fail_json( msg='Error: The tos is not digit.') if self.dscp: if self.dscp.isdigit(): if int(self.dscp) < 0 or int(self.dscp) > 63: self.module.fail_json( msg='Error: The value of dscp is out of [0 - 63].') else: self.module.fail_json( msg='Error: The dscp is not digit.') if self.icmp_type: if self.icmp_type.isdigit(): if int(self.icmp_type) < 0 or int(self.icmp_type) > 255: self.module.fail_json( msg='Error: The value of icmp_type is out of [0 - 255].') else: self.module.fail_json( msg='Error: The icmp_type is not digit.') if self.icmp_code: if self.icmp_code.isdigit(): if int(self.icmp_code) < 0 or int(self.icmp_code) > 255: self.module.fail_json( msg='Error: The value of icmp_code is out of [0 - 255].') else: self.module.fail_json( msg='Error: The icmp_code is not digit.') if self.vrf_name: if len(self.vrf_name) < 1 or len(self.vrf_name) > 31: self.module.fail_json( msg='Error: The len of vrf_name is out of [1 - 31].') if self.syn_flag: if self.syn_flag.isdigit(): if int(self.syn_flag) < 0 or int(self.syn_flag) > 63: self.module.fail_json( msg='Error: The value of syn_flag is out of [0 - 63].') else: self.module.fail_json( msg='Error: The syn_flag is not digit.') if self.tcp_flag_mask: if self.tcp_flag_mask.isdigit(): if int(self.tcp_flag_mask) < 0 or int(self.tcp_flag_mask) > 63: self.module.fail_json( msg='Error: The value of tcp_flag_mask is out of [0 - 63].') else: self.module.fail_json( msg='Error: The tcp_flag_mask is not digit.') if self.time_range: if len(self.time_range) < 1 or len(self.time_range) > 32: self.module.fail_json( msg='Error: The len of time_range is out of [1 - 32].') if self.rule_description: if len(self.rule_description) < 1 or len(self.rule_description) > 127: self.module.fail_json( msg='Error: The len of rule_description is out of [1 - 127].') if self.igmp_type: self.get_igmp_type_num() conf_str = CE_GET_ACL_ADVANCE_RULE_HEADER % self.acl_name if self.rule_id: conf_str += "" if self.rule_action: conf_str += "" if self.protocol: conf_str += "" if self.source_ip: conf_str += "" if self.src_wild: conf_str += "" if self.src_pool_name: conf_str += "" if self.dest_ip: conf_str += "" if self.dest_wild: conf_str += "" if self.dest_pool_name: conf_str += "" if self.src_port_op: conf_str += "" if self.src_port_begin: conf_str += "" if self.src_port_end: conf_str += "" if self.src_port_pool_name: conf_str += "" if self.dest_port_op: conf_str += "" if self.dest_port_begin: conf_str += "" if self.dest_port_end: conf_str += "" if self.dest_port_pool_name: conf_str += "" if self.frag_type: conf_str += "" if self.precedence: conf_str += "" if self.tos: conf_str += "" if self.dscp: conf_str += "" if self.icmp_name: conf_str += "" if self.icmp_type: conf_str += "" if self.icmp_code: conf_str += "" conf_str += "" if self.vrf_name: conf_str += "" if self.syn_flag: conf_str += "" if self.tcp_flag_mask: conf_str += "" conf_str += "" if self.time_range: conf_str += "" if self.rule_description: conf_str += "" if self.igmp_type: conf_str += "" conf_str += "" conf_str += CE_GET_ACL_ADVANCE_RULE_TAIL recv_xml = self.netconf_get_config(conf_str=conf_str) if "" in recv_xml: find_flag = False else: xml_str = recv_xml.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) # parse advance rule adv_rule_info = root.findall( "acl/aclGroups/aclGroup/aclRuleAdv4s/aclRuleAdv4") if adv_rule_info: for tmp in adv_rule_info: tmp_dict = dict() for site in tmp: if site.tag in ["aclRuleName", "aclRuleID", "aclAction", "aclProtocol", "aclSourceIp", "aclSrcWild", "aclSPoolName", "aclDestIp", "aclDestWild", "aclDPoolName", "aclSrcPortOp", "aclSrcPortBegin", "aclSrcPortEnd", "aclSPortPoolName", "aclDestPortOp", "aclDestPortB", "aclDestPortE", "aclDPortPoolName", "aclFragType", "aclPrecedence", "aclTos", "aclDscp", "aclIcmpName", "aclIcmpType", "aclIcmpCode", "aclTtlExpired", "vrfName", "aclSynFlag", "aclTcpFlagMask", "aclEstablished", "aclTimeName", "aclRuleDescription", "aclIgmpType", "aclLogFlag"]: tmp_dict[site.tag] = site.text self.cur_advance_rule_cfg[ "adv_rule_info"].append(tmp_dict) if self.cur_advance_rule_cfg["adv_rule_info"]: for tmp in self.cur_advance_rule_cfg["adv_rule_info"]: find_flag = True if self.rule_name and tmp.get("aclRuleName") != self.rule_name: find_flag = False if self.rule_id and tmp.get("aclRuleID") != self.rule_id: find_flag = False if self.rule_action and tmp.get("aclAction") != self.rule_action: find_flag = False if self.protocol and tmp.get("aclProtocol") != self.protocol_num: find_flag = False if self.source_ip: tmp_src_ip = self.source_ip.split(".") tmp_src_wild = self.src_wild.split(".") tmp_addr_item = [] for idx in range(4): item1 = 255 - int(tmp_src_wild[idx]) item2 = item1 & int(tmp_src_ip[idx]) tmp_addr_item.append(item2) tmp_addr = "%s.%s.%s.%s" % (tmp_addr_item[0], tmp_addr_item[1], tmp_addr_item[2], tmp_addr_item[3]) if tmp_addr != tmp.get("aclSourceIp"): find_flag = False if self.src_wild and tmp.get("aclSrcWild") != self.src_wild: find_flag = False if self.src_pool_name and tmp.get("aclSPoolName") != self.src_pool_name: find_flag = False if self.dest_ip: tmp_src_ip = self.dest_ip.split(".") tmp_src_wild = self.dest_wild.split(".") tmp_addr_item = [] for idx in range(4): item1 = 255 - int(tmp_src_wild[idx]) item2 = item1 & int(tmp_src_ip[idx]) tmp_addr_item.append(item2) tmp_addr = "%s.%s.%s.%s" % (tmp_addr_item[0], tmp_addr_item[1], tmp_addr_item[2], tmp_addr_item[3]) if tmp_addr != tmp.get("aclDestIp"): find_flag = False if self.dest_wild and tmp.get("aclDestWild") != self.dest_wild: find_flag = False if self.dest_pool_name and tmp.get("aclDPoolName") != self.dest_pool_name: find_flag = False if self.src_port_op and tmp.get("aclSrcPortOp") != self.src_port_op: find_flag = False if self.src_port_begin and tmp.get("aclSrcPortBegin") != self.src_port_begin: find_flag = False if self.src_port_end and tmp.get("aclSrcPortEnd") != self.src_port_end: find_flag = False if self.src_port_pool_name and tmp.get("aclSPortPoolName") != self.src_port_pool_name: find_flag = False if self.dest_port_op and tmp.get("aclDestPortOp") != self.dest_port_op: find_flag = False if self.dest_port_begin and tmp.get("aclDestPortB") != self.dest_port_begin: find_flag = False if self.dest_port_end and tmp.get("aclDestPortE") != self.dest_port_end: find_flag = False if self.dest_port_pool_name and tmp.get("aclDPortPoolName") != self.dest_port_pool_name: find_flag = False frag_type = "clear_fragment" if tmp.get("aclFragType") is None else tmp.get("aclFragType") if self.frag_type and frag_type != self.frag_type: find_flag = False if self.precedence and tmp.get("aclPrecedence") != self.precedence: find_flag = False if self.tos and tmp.get("aclTos") != self.tos: find_flag = False if self.dscp and tmp.get("aclDscp") != self.dscp: find_flag = False if self.icmp_name and tmp.get("aclIcmpName") != self.icmp_name: find_flag = False if self.icmp_type and tmp.get("aclIcmpType") != self.icmp_type: find_flag = False if self.icmp_code and tmp.get("aclIcmpCode") != self.icmp_code: find_flag = False if tmp.get("aclTtlExpired").lower() != str(self.ttl_expired).lower(): find_flag = False if self.vrf_name and tmp.get("vrfName") != self.vrf_name: find_flag = False if self.syn_flag and tmp.get("aclSynFlag") != self.syn_flag: find_flag = False if self.tcp_flag_mask and tmp.get("aclTcpFlagMask") != self.tcp_flag_mask: find_flag = False if self.protocol == "tcp" and \ tmp.get("aclEstablished").lower() != str(self.established).lower(): find_flag = False if self.time_range and tmp.get("aclTimeName") != self.time_range: find_flag = False if self.rule_description and tmp.get("aclRuleDescription") != self.rule_description: find_flag = False if self.igmp_type and tmp.get("aclIgmpType") != self.igmp_type_num: find_flag = False if tmp.get("aclLogFlag").lower() != str(self.log_flag).lower(): find_flag = False if find_flag: break else: find_flag = False if self.state == "present": need_cfg = bool(not find_flag) elif self.state == "absent": need_cfg = bool(find_flag) else: need_cfg = False self.cur_advance_rule_cfg["need_cfg"] = need_cfg def get_proposed(self): """ Get proposed state """ self.proposed["state"] = self.state if self.acl_name: self.proposed["acl_name"] = self.acl_name if self.acl_num: self.proposed["acl_num"] = self.acl_num if self.acl_step: self.proposed["acl_step"] = self.acl_step if self.acl_description: self.proposed["acl_description"] = self.acl_description if self.rule_name: self.proposed["rule_name"] = self.rule_name if self.rule_id: self.proposed["rule_id"] = self.rule_id if self.rule_action: self.proposed["rule_action"] = self.rule_action if self.protocol: self.proposed["protocol"] = self.protocol if self.source_ip: self.proposed["source_ip"] = self.source_ip if self.src_mask: self.proposed["src_mask"] = self.src_mask if self.src_pool_name: self.proposed["src_pool_name"] = self.src_pool_name if self.dest_ip: self.proposed["dest_ip"] = self.dest_ip if self.dest_mask: self.proposed["dest_mask"] = self.dest_mask if self.dest_pool_name: self.proposed["dest_pool_name"] = self.dest_pool_name if self.src_port_op: self.proposed["src_port_op"] = self.src_port_op if self.src_port_begin: self.proposed["src_port_begin"] = self.src_port_begin if self.src_port_end: self.proposed["src_port_end"] = self.src_port_end if self.src_port_pool_name: self.proposed["src_port_pool_name"] = self.src_port_pool_name if self.dest_port_op: self.proposed["dest_port_op"] = self.dest_port_op if self.dest_port_begin: self.proposed["dest_port_begin"] = self.dest_port_begin if self.dest_port_end: self.proposed["dest_port_end"] = self.dest_port_end if self.dest_port_pool_name: self.proposed["dest_port_pool_name"] = self.dest_port_pool_name if self.frag_type: self.proposed["frag_type"] = self.frag_type if self.precedence: self.proposed["precedence"] = self.precedence if self.tos: self.proposed["tos"] = self.tos if self.dscp: self.proposed["dscp"] = self.dscp if self.icmp_name: self.proposed["icmp_name"] = self.icmp_name if self.icmp_type: self.proposed["icmp_type"] = self.icmp_type if self.icmp_code: self.proposed["icmp_code"] = self.icmp_code if self.ttl_expired: self.proposed["ttl_expired"] = self.ttl_expired if self.vrf_name: self.proposed["vrf_name"] = self.vrf_name if self.syn_flag: self.proposed["syn_flag"] = self.syn_flag if self.tcp_flag_mask: self.proposed["tcp_flag_mask"] = self.tcp_flag_mask self.proposed["established"] = self.established if self.time_range: self.proposed["time_range"] = self.time_range if self.rule_description: self.proposed["rule_description"] = self.rule_description if self.igmp_type: self.proposed["igmp_type"] = self.igmp_type self.proposed["log_flag"] = self.log_flag def get_existing(self): """ Get existing state """ self.existing["acl_info"] = self.cur_acl_cfg["acl_info"] self.existing["adv_rule_info"] = self.cur_advance_rule_cfg[ "adv_rule_info"] def get_end_state(self): """ Get end state """ self.check_acl_args() self.end_state["acl_info"] = self.cur_acl_cfg["acl_info"] self.check_advance_rule_args() self.end_state["adv_rule_info"] = self.cur_advance_rule_cfg[ "adv_rule_info"] if self.end_state == self.existing: self.changed = False self.updates_cmd = list() def merge_acl(self): """ Merge acl operation """ conf_str = CE_MERGE_ACL_HEADER % self.acl_name if self.acl_type: conf_str += "%s" % self.acl_type if self.acl_num: conf_str += "%s" % self.acl_num if self.acl_step: conf_str += "%s" % self.acl_step if self.acl_description: conf_str += "%s" % self.acl_description conf_str += CE_MERGE_ACL_TAIL recv_xml = self.netconf_set_config(conf_str=conf_str) if "" not in recv_xml: self.module.fail_json(msg='Error: Merge acl failed.') if self.acl_name.isdigit(): cmd = "acl number %s" % self.acl_name else: if self.acl_type and not self.acl_num: cmd = "acl name %s %s" % (self.acl_name, self.acl_type.lower()) elif self.acl_type and self.acl_num: cmd = "acl name %s number %s" % (self.acl_name, self.acl_num) elif not self.acl_type and self.acl_num: cmd = "acl name %s number %s" % (self.acl_name, self.acl_num) self.updates_cmd.append(cmd) if self.acl_description: cmd = "description %s" % self.acl_description self.updates_cmd.append(cmd) if self.acl_step: cmd = "step %s" % self.acl_step self.updates_cmd.append(cmd) self.changed = True def delete_acl(self): """ Delete acl operation """ conf_str = CE_DELETE_ACL_HEADER % self.acl_name if self.acl_type: conf_str += "%s" % self.acl_type if self.acl_num: conf_str += "%s" % self.acl_num if self.acl_step: conf_str += "%s" % self.acl_step if self.acl_description: conf_str += "%s" % self.acl_description conf_str += CE_DELETE_ACL_TAIL recv_xml = self.netconf_set_config(conf_str=conf_str) if "" not in recv_xml: self.module.fail_json(msg='Error: Delete acl failed.') if self.acl_description: cmd = "undo description" self.updates_cmd.append(cmd) if self.acl_step: cmd = "undo step" self.updates_cmd.append(cmd) if self.acl_name.isdigit(): cmd = "undo acl number %s" % self.acl_name else: cmd = "undo acl name %s" % self.acl_name self.updates_cmd.append(cmd) self.changed = True def merge_adv_rule(self): """ Merge advance rule operation """ conf_str = CE_MERGE_ACL_ADVANCE_RULE_HEADER % ( self.acl_name, self.rule_name) if self.rule_id: conf_str += "%s" % self.rule_id if self.rule_action: conf_str += "%s" % self.rule_action if self.protocol: conf_str += "%s" % self.protocol_num if self.source_ip: conf_str += "%s" % self.source_ip if self.src_wild: conf_str += "%s" % self.src_wild if self.src_pool_name: conf_str += "%s" % self.src_pool_name if self.dest_ip: conf_str += "%s" % self.dest_ip if self.dest_wild: conf_str += "%s" % self.dest_wild if self.dest_pool_name: conf_str += "%s" % self.dest_pool_name if self.src_port_op: conf_str += "%s" % self.src_port_op if self.src_port_begin: conf_str += "%s" % self.src_port_begin if self.src_port_end: conf_str += "%s" % self.src_port_end if self.src_port_pool_name: conf_str += "%s" % self.src_port_pool_name if self.dest_port_op: conf_str += "%s" % self.dest_port_op if self.dest_port_begin: conf_str += "%s" % self.dest_port_begin if self.dest_port_end: conf_str += "%s" % self.dest_port_end if self.dest_port_pool_name: conf_str += "%s" % self.dest_port_pool_name if self.frag_type: conf_str += "%s" % self.frag_type if self.precedence: conf_str += "%s" % self.precedence if self.tos: conf_str += "%s" % self.tos if self.dscp: conf_str += "%s" % self.dscp if self.icmp_name: conf_str += "%s" % self.icmp_name if self.icmp_type: conf_str += "%s" % self.icmp_type if self.icmp_code: conf_str += "%s" % self.icmp_code conf_str += "%s" % str(self.ttl_expired).lower() if self.vrf_name: conf_str += "%s" % self.vrf_name if self.syn_flag: conf_str += "%s" % self.syn_flag if self.tcp_flag_mask: conf_str += "%s" % self.tcp_flag_mask if self.protocol == "tcp": conf_str += "%s" % str(self.established).lower() if self.time_range: conf_str += "%s" % self.time_range if self.rule_description: conf_str += "%s" % self.rule_description if self.igmp_type: conf_str += "%s" % self.igmp_type_num conf_str += "%s" % str(self.log_flag).lower() conf_str += CE_MERGE_ACL_ADVANCE_RULE_TAIL recv_xml = self.netconf_set_config(conf_str=conf_str) if "" not in recv_xml: self.module.fail_json(msg='Error: Merge acl base rule failed.') if self.rule_action and self.protocol: cmd = "rule" if self.rule_id: cmd += " %s" % self.rule_id cmd += " %s" % self.rule_action cmd += " %s" % self.protocol if self.dscp: cmd += " dscp %s" % self.dscp if self.tos: cmd += " tos %s" % self.tos if self.source_ip and self.src_wild: cmd += " source %s %s" % (self.source_ip, self.src_wild) if self.src_pool_name: cmd += " source-pool %s" % self.src_pool_name if self.src_port_op: cmd += " source-port" if self.src_port_op == "lt": cmd += " lt %s" % self.src_port_end elif self.src_port_op == "eq": cmd += " eq %s" % self.src_port_begin elif self.src_port_op == "gt": cmd += " gt %s" % self.src_port_begin elif self.src_port_op == "range": cmd += " range %s %s" % (self.src_port_begin, self.src_port_end) if self.src_port_pool_name: cmd += " source-port-pool %s" % self.src_port_pool_name if self.dest_ip and self.dest_wild: cmd += " destination %s %s" % (self.dest_ip, self.dest_wild) if self.dest_pool_name: cmd += " destination-pool %s" % self.dest_pool_name if self.dest_port_op: cmd += " destination-port" if self.dest_port_op == "lt": cmd += " lt %s" % self.dest_port_end elif self.dest_port_op == "eq": cmd += " eq %s" % self.dest_port_begin elif self.dest_port_op == "gt": cmd += " gt %s" % self.dest_port_begin elif self.dest_port_op == "range": cmd += " range %s %s" % (self.dest_port_begin, self.dest_port_end) if self.dest_port_pool_name: cmd += " destination-port-pool %s" % self.dest_port_pool_name if self.frag_type == "fragment": cmd += " fragment-type fragment" if self.precedence: cmd += " precedence %s" % self.precedence_name[self.precedence] if self.protocol == "icmp": if self.icmp_name: cmd += " icmp-type %s" % self.icmp_name elif self.icmp_type and self.icmp_code: cmd += " icmp-type %s %s" % (self.icmp_type, self.icmp_code) elif self.icmp_type: cmd += " icmp-type %s" % self.icmp_type if self.protocol == "tcp": if self.syn_flag: cmd += " tcp-flag %s" % self.syn_flag if self.tcp_flag_mask: cmd += " mask %s" % self.tcp_flag_mask if self.established: cmd += " established" if self.protocol == "igmp": if self.igmp_type: cmd += " igmp-type %s" % self.igmp_type if self.time_range: cmd += " time-range %s" % self.time_range if self.vrf_name: cmd += " vpn-instance %s" % self.vrf_name if self.ttl_expired: cmd += " ttl-expired" if self.log_flag: cmd += " logging" self.updates_cmd.append(cmd) if self.rule_description: cmd = "rule %s description %s" % ( self.rule_id, self.rule_description) self.updates_cmd.append(cmd) self.changed = True def delete_adv_rule(self): """ Delete advance rule operation """ conf_str = CE_DELETE_ACL_ADVANCE_RULE_HEADER % ( self.acl_name, self.rule_name) if self.rule_id: conf_str += "%s" % self.rule_id if self.rule_action: conf_str += "%s" % self.rule_action if self.protocol: conf_str += "%s" % self.protocol_num if self.source_ip: conf_str += "%s" % self.source_ip if self.src_wild: conf_str += "%s" % self.src_wild if self.src_pool_name: conf_str += "%s" % self.src_pool_name if self.dest_ip: conf_str += "%s" % self.dest_ip if self.dest_wild: conf_str += "%s" % self.dest_wild if self.dest_pool_name: conf_str += "%s" % self.dest_pool_name if self.src_port_op: conf_str += "%s" % self.src_port_op if self.src_port_begin: conf_str += "%s" % self.src_port_begin if self.src_port_end: conf_str += "%s" % self.src_port_end if self.src_port_pool_name: conf_str += "%s" % self.src_port_pool_name if self.dest_port_op: conf_str += "%s" % self.dest_port_op if self.dest_port_begin: conf_str += "%s" % self.dest_port_begin if self.dest_port_end: conf_str += "%s" % self.dest_port_end if self.dest_port_pool_name: conf_str += "%s" % self.dest_port_pool_name if self.frag_type: conf_str += "%s" % self.frag_type if self.precedence: conf_str += "%s" % self.precedence if self.tos: conf_str += "%s" % self.tos if self.dscp: conf_str += "%s" % self.dscp if self.icmp_name: conf_str += "%s" % self.icmp_name if self.icmp_type: conf_str += "%s" % self.icmp_type if self.icmp_code: conf_str += "%s" % self.icmp_code conf_str += "%s" % str(self.ttl_expired).lower() if self.vrf_name: conf_str += "%s" % self.vrf_name if self.syn_flag: conf_str += "%s" % self.syn_flag if self.tcp_flag_mask: conf_str += "%s" % self.tcp_flag_mask if self.protocol == "tcp": conf_str += "%s" % str(self.established).lower() if self.time_range: conf_str += "%s" % self.time_range if self.rule_description: conf_str += "%s" % self.rule_description if self.igmp_type: conf_str += "%s" % self.igmp_type conf_str += "%s" % str(self.log_flag).lower() conf_str += CE_DELETE_ACL_ADVANCE_RULE_TAIL recv_xml = self.netconf_set_config(conf_str=conf_str) if "" not in recv_xml: self.module.fail_json(msg='Error: Delete acl base rule failed.') if self.rule_description: if self.acl_name.isdigit(): cmd = "acl number %s" % self.acl_name else: cmd = "acl name %s" % self.acl_name self.updates_cmd.append(cmd) cmd = "undo rule %s description" % self.rule_id self.updates_cmd.append(cmd) if self.rule_id: if self.acl_name.isdigit(): cmd = "acl number %s" % self.acl_name else: cmd = "acl name %s" % self.acl_name self.updates_cmd.append(cmd) cmd = "undo rule %s" % self.rule_id self.updates_cmd.append(cmd) elif self.rule_action and self.protocol: if self.acl_name.isdigit(): cmd = "acl number %s" % self.acl_name else: cmd = "acl name %s" % self.acl_name self.updates_cmd.append(cmd) cmd = "undo rule" cmd += " %s" % self.rule_action cmd += " %s" % self.protocol if self.dscp: cmd += " dscp %s" % self.dscp if self.tos: cmd += " tos %s" % self.tos if self.source_ip and self.src_mask: cmd += " source %s %s" % (self.source_ip, self.src_mask) if self.src_pool_name: cmd += " source-pool %s" % self.src_pool_name if self.src_port_op: cmd += " source-port" if self.src_port_op == "lt": cmd += " lt %s" % self.src_port_end elif self.src_port_op == "eq": cmd += " eq %s" % self.src_port_begin elif self.src_port_op == "gt": cmd += " gt %s" % self.src_port_begin elif self.src_port_op == "range": cmd += " range %s %s" % (self.src_port_begin, self.src_port_end) if self.src_port_pool_name: cmd += " source-port-pool %s" % self.src_port_pool_name if self.dest_ip and self.dest_mask: cmd += " destination %s %s" % (self.dest_ip, self.dest_mask) if self.dest_pool_name: cmd += " destination-pool %s" % self.dest_pool_name if self.dest_port_op: cmd += " destination-port" if self.dest_port_op == "lt": cmd += " lt %s" % self.dest_port_end elif self.dest_port_op == "eq": cmd += " eq %s" % self.dest_port_begin elif self.dest_port_op == "gt": cmd += " gt %s" % self.dest_port_begin elif self.dest_port_op == "range": cmd += " range %s %s" % (self.dest_port_begin, self.dest_port_end) if self.dest_port_pool_name: cmd += " destination-port-pool %s" % self.dest_port_pool_name if self.frag_type == "fragment": cmd += " fragment-type fragment" if self.precedence: cmd += " precedence %s" % self.precedence_name[self.precedence] if self.time_range: cmd += " time-range %s" % self.time_range if self.vrf_name: cmd += " vpn-instance %s" % self.vrf_name if self.ttl_expired: cmd += " ttl-expired" if self.log_flag: cmd += " logging" self.updates_cmd.append(cmd) self.changed = True def work(self): """ Main work function """ self.check_acl_args() self.check_advance_rule_args() self.get_proposed() self.get_existing() if self.state == "present": if self.cur_acl_cfg["need_cfg"]: self.merge_acl() if self.cur_advance_rule_cfg["need_cfg"]: self.merge_adv_rule() elif self.state == "absent": if self.cur_advance_rule_cfg["need_cfg"]: self.delete_adv_rule() elif self.state == "delete_acl": if self.cur_acl_cfg["need_cfg"]: self.delete_acl() 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 self.results['updates'] = self.updates_cmd self.module.exit_json(**self.results) def main(): """ Module main """ argument_spec = dict( state=dict(choices=['present', 'absent', 'delete_acl'], default='present'), acl_name=dict(type='str', required=True), acl_num=dict(type='str'), acl_step=dict(type='str'), acl_description=dict(type='str'), rule_name=dict(type='str'), rule_id=dict(type='str'), rule_action=dict(choices=['permit', 'deny']), protocol=dict(choices=['ip', 'icmp', 'igmp', 'ipinip', 'tcp', 'udp', 'gre', 'ospf']), source_ip=dict(type='str'), src_mask=dict(type='str'), src_pool_name=dict(type='str'), dest_ip=dict(type='str'), dest_mask=dict(type='str'), dest_pool_name=dict(type='str'), src_port_op=dict(choices=['lt', 'eq', 'gt', 'range']), src_port_begin=dict(type='str'), src_port_end=dict(type='str'), src_port_pool_name=dict(type='str'), dest_port_op=dict(choices=['lt', 'eq', 'gt', 'range']), dest_port_begin=dict(type='str'), dest_port_end=dict(type='str'), dest_port_pool_name=dict(type='str'), frag_type=dict(choices=['fragment', 'clear_fragment']), precedence=dict(type='str'), tos=dict(type='str'), dscp=dict(type='str'), icmp_name=dict(choices=['unconfiged', 'echo', 'echo-reply', 'fragmentneed-DFset', 'host-redirect', 'host-tos-redirect', 'host-unreachable', 'information-reply', 'information-request', 'net-redirect', 'net-tos-redirect', 'net-unreachable', 'parameter-problem', 'port-unreachable', 'protocol-unreachable', 'reassembly-timeout', 'source-quench', 'source-route-failed', 'timestamp-reply', 'timestamp-request', 'ttl-exceeded', 'address-mask-reply', 'address-mask-request', 'custom']), icmp_type=dict(type='str'), icmp_code=dict(type='str'), ttl_expired=dict(required=False, default=False, type='bool'), vrf_name=dict(type='str'), syn_flag=dict(type='str'), tcp_flag_mask=dict(type='str'), established=dict(required=False, default=False, type='bool'), time_range=dict(type='str'), rule_description=dict(type='str'), igmp_type=dict(choices=['host-query', 'mrouter-adver', 'mrouter-solic', 'mrouter-termi', 'mtrace-resp', 'mtrace-route', 'v1host-report', 'v2host-report', 'v2leave-group', 'v3host-report']), log_flag=dict(required=False, default=False, type='bool') ) argument_spec.update(ce_argument_spec) module = AdvanceAcl(argument_spec=argument_spec) module.work() if __name__ == '__main__': main()