diff options
Diffstat (limited to 'lib/ansible/modules')
30 files changed, 0 insertions, 12809 deletions
diff --git a/lib/ansible/modules/network/ios/_ios_interface.py b/lib/ansible/modules/network/ios/_ios_interface.py deleted file mode 100644 index d6241acb16..0000000000 --- a/lib/ansible/modules/network/ios/_ios_interface.py +++ /dev/null @@ -1,495 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['deprecated'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_interface -version_added: "2.4" -author: "Ganesh Nalawade (@ganeshrn)" -short_description: Manage Interface on Cisco IOS network devices -description: - - This module provides declarative management of Interfaces - on Cisco IOS network devices. -deprecated: - removed_in: '2.13' - alternative: ios_interfaces - why: Newer and updated modules released with more functionality in Ansible 2.9 -notes: - - Tested against IOS 15.6 -options: - name: - description: - - Name of the Interface. - required: true - description: - description: - - Description of Interface. - enabled: - description: - - Interface link status. - type: bool - speed: - description: - - Interface link speed. - mtu: - description: - - Maximum size of transmit packet. - duplex: - description: - - Interface link status - default: auto - choices: ['full', 'half', 'auto'] - tx_rate: - description: - - Transmit rate in bits per second (bps). - - This is state check parameter only. - - Supports conditionals, see L(Conditionals in Networking Modules,../network/user_guide/network_working_with_command_output.html) - rx_rate: - description: - - Receiver rate in bits per second (bps). - - This is state check parameter only. - - Supports conditionals, see L(Conditionals in Networking Modules,../network/user_guide/network_working_with_command_output.html) - neighbors: - description: - - Check the operational state of given interface C(name) for CDP/LLDP neighbor. - - The following suboptions are available. - suboptions: - host: - description: - - "CDP/LLDP neighbor host for given interface C(name)." - port: - description: - - "CDP/LLDP neighbor port to which given interface C(name) is connected." - aggregate: - description: List of Interfaces definitions. - delay: - description: - - Time in seconds to wait before checking for the operational state on remote - device. This wait is applicable for operational state argument which are - I(state) with values C(up)/C(down), I(tx_rate) and I(rx_rate). - default: 10 - state: - description: - - State of the Interface configuration, C(up) means present and - operationally up and C(down) means present and operationally C(down) - default: present - choices: ['present', 'absent', 'up', 'down'] -extends_documentation_fragment: ios -""" - -EXAMPLES = """ -- name: configure interface - ios_interface: - name: GigabitEthernet0/2 - description: test-interface - speed: 100 - duplex: half - mtu: 512 - -- name: remove interface - ios_interface: - name: Loopback9 - state: absent - -- name: make interface up - ios_interface: - name: GigabitEthernet0/2 - enabled: True - -- name: make interface down - ios_interface: - name: GigabitEthernet0/2 - enabled: False - -- name: Check intent arguments - ios_interface: - name: GigabitEthernet0/2 - state: up - tx_rate: ge(0) - rx_rate: le(0) - -- name: Check neighbors intent arguments - ios_interface: - name: Gi0/0 - neighbors: - - port: eth0 - host: netdev - -- name: Config + intent - ios_interface: - name: GigabitEthernet0/2 - enabled: False - state: down - -- name: Add interface using aggregate - ios_interface: - aggregate: - - { name: GigabitEthernet0/1, mtu: 256, description: test-interface-1 } - - { name: GigabitEthernet0/2, mtu: 516, description: test-interface-2 } - duplex: full - speed: 100 - state: present - -- name: Delete interface using aggregate - ios_interface: - aggregate: - - name: Loopback9 - - name: Loopback10 - state: absent -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device. - returned: always, except for the platforms that use Netconf transport to manage the device. - type: list - sample: - - interface GigabitEthernet0/2 - - description test-interface - - duplex half - - mtu 512 -""" -import re - -from copy import deepcopy -from time import sleep - -from ansible.module_utils._text import to_text -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.connection import exec_command -from ansible.module_utils.network.ios.ios import get_config, load_config -from ansible.module_utils.network.ios.ios import ios_argument_spec -from ansible.module_utils.network.common.config import NetworkConfig -from ansible.module_utils.network.common.utils import conditional, remove_default_spec - - -def validate_mtu(value, module): - if value and not 64 <= int(value) <= 9600: - module.fail_json(msg='mtu must be between 64 and 9600') - - -def validate_param_values(module, obj, param=None): - if param is None: - param = module.params - for key in obj: - # validate the param value (if validator func exists) - validator = globals().get('validate_%s' % key) - if callable(validator): - validator(param.get(key), module) - - -def parse_shutdown(configobj, name): - cfg = configobj['interface %s' % name] - cfg = '\n'.join(cfg.children) - match = re.search(r'^shutdown', cfg, re.M) - if match: - return True - else: - return False - - -def parse_config_argument(configobj, name, arg=None): - cfg = configobj['interface %s' % name] - cfg = '\n'.join(cfg.children) - match = re.search(r'%s (.+)$' % arg, cfg, re.M) - if match: - return match.group(1) - - -def search_obj_in_list(name, lst): - for o in lst: - if o['name'] == name: - return o - - return None - - -def add_command_to_interface(interface, cmd, commands): - if interface not in commands: - commands.append(interface) - commands.append(cmd) - - -def map_config_to_obj(module): - config = get_config(module) - configobj = NetworkConfig(indent=1, contents=config) - - match = re.findall(r'^interface (\S+)', config, re.M) - if not match: - return list() - - instances = list() - - for item in set(match): - obj = { - 'name': item, - 'description': parse_config_argument(configobj, item, 'description'), - 'speed': parse_config_argument(configobj, item, 'speed'), - 'duplex': parse_config_argument(configobj, item, 'duplex'), - 'mtu': parse_config_argument(configobj, item, 'mtu'), - 'disable': True if parse_shutdown(configobj, item) else False, - 'state': 'present' - } - instances.append(obj) - return instances - - -def map_params_to_obj(module): - obj = [] - aggregate = module.params.get('aggregate') - if aggregate: - for item in aggregate: - for key in item: - if item.get(key) is None: - item[key] = module.params[key] - - validate_param_values(module, item, item) - d = item.copy() - - if d['enabled']: - d['disable'] = False - else: - d['disable'] = True - - obj.append(d) - - else: - params = { - 'name': module.params['name'], - 'description': module.params['description'], - 'speed': module.params['speed'], - 'mtu': module.params['mtu'], - 'duplex': module.params['duplex'], - 'state': module.params['state'], - 'delay': module.params['delay'], - 'tx_rate': module.params['tx_rate'], - 'rx_rate': module.params['rx_rate'], - 'neighbors': module.params['neighbors'] - } - - validate_param_values(module, params) - if module.params['enabled']: - params.update({'disable': False}) - else: - params.update({'disable': True}) - - obj.append(params) - return obj - - -def map_obj_to_commands(updates): - commands = list() - want, have = updates - - args = ('speed', 'description', 'duplex', 'mtu') - for w in want: - name = w['name'] - disable = w['disable'] - state = w['state'] - - obj_in_have = search_obj_in_list(name, have) - interface = 'interface ' + name - - if state == 'absent' and obj_in_have: - commands.append('no ' + interface) - - elif state in ('present', 'up', 'down'): - if obj_in_have: - for item in args: - candidate = w.get(item) - running = obj_in_have.get(item) - if candidate != running: - if candidate: - cmd = item + ' ' + str(candidate) - add_command_to_interface(interface, cmd, commands) - - if disable and not obj_in_have.get('disable', False): - add_command_to_interface(interface, 'shutdown', commands) - elif not disable and obj_in_have.get('disable', False): - add_command_to_interface(interface, 'no shutdown', commands) - else: - commands.append(interface) - for item in args: - value = w.get(item) - if value: - commands.append(item + ' ' + str(value)) - - if disable: - commands.append('no shutdown') - return commands - - -def check_declarative_intent_params(module, want, result): - failed_conditions = [] - have_neighbors_lldp = None - have_neighbors_cdp = None - for w in want: - want_state = w.get('state') - want_tx_rate = w.get('tx_rate') - want_rx_rate = w.get('rx_rate') - want_neighbors = w.get('neighbors') - - if want_state not in ('up', 'down') and not want_tx_rate and not want_rx_rate and not want_neighbors: - continue - - if result['changed']: - sleep(w['delay']) - - command = 'show interfaces %s' % w['name'] - rc, out, err = exec_command(module, command) - if rc != 0: - module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) - - if want_state in ('up', 'down'): - match = re.search(r'%s (\w+)' % 'line protocol is', out, re.M) - have_state = None - if match: - have_state = match.group(1) - if have_state is None or not conditional(want_state, have_state.strip()): - failed_conditions.append('state ' + 'eq(%s)' % want_state) - - if want_tx_rate: - match = re.search(r'%s (\d+)' % 'output rate', out, re.M) - have_tx_rate = None - if match: - have_tx_rate = match.group(1) - - if have_tx_rate is None or not conditional(want_tx_rate, have_tx_rate.strip(), cast=int): - failed_conditions.append('tx_rate ' + want_tx_rate) - - if want_rx_rate: - match = re.search(r'%s (\d+)' % 'input rate', out, re.M) - have_rx_rate = None - if match: - have_rx_rate = match.group(1) - - if have_rx_rate is None or not conditional(want_rx_rate, have_rx_rate.strip(), cast=int): - failed_conditions.append('rx_rate ' + want_rx_rate) - - if want_neighbors: - have_host = [] - have_port = [] - - # Process LLDP neighbors - if have_neighbors_lldp is None: - rc, have_neighbors_lldp, err = exec_command(module, 'show lldp neighbors detail') - if rc != 0: - module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) - - if have_neighbors_lldp: - lines = have_neighbors_lldp.strip().split('Local Intf: ') - for line in lines: - field = line.split('\n') - if field[0].strip() == w['name']: - for item in field: - if item.startswith('System Name:'): - have_host.append(item.split(':')[1].strip()) - if item.startswith('Port Description:'): - have_port.append(item.split(':')[1].strip()) - - # Process CDP neighbors - if have_neighbors_cdp is None: - rc, have_neighbors_cdp, err = exec_command(module, 'show cdp neighbors detail') - if rc != 0: - module.fail_json(msg=to_text(err, errors='surrogate_then_replace'), command=command, rc=rc) - - if have_neighbors_cdp: - neighbors_cdp = re.findall('Device ID: (.*?)\n.*?Interface: (.*?), Port ID .outgoing port.: (.*?)\n', have_neighbors_cdp, re.S) - for host, localif, remoteif in neighbors_cdp: - if localif == w['name']: - have_host.append(host) - have_port.append(remoteif) - - for item in want_neighbors: - host = item.get('host') - port = item.get('port') - if host and host not in have_host: - failed_conditions.append('host ' + host) - if port and port not in have_port: - failed_conditions.append('port ' + port) - return failed_conditions - - -def main(): - """ main entry point for module execution - """ - neighbors_spec = dict( - host=dict(), - port=dict() - ) - - element_spec = dict( - name=dict(), - description=dict(), - speed=dict(), - mtu=dict(), - duplex=dict(choices=['full', 'half', 'auto']), - enabled=dict(default=True, type='bool'), - tx_rate=dict(), - rx_rate=dict(), - neighbors=dict(type='list', elements='dict', options=neighbors_spec), - delay=dict(default=10, type='int'), - state=dict(default='present', - choices=['present', 'absent', 'up', 'down']) - ) - - aggregate_spec = deepcopy(element_spec) - aggregate_spec['name'] = dict(required=True) - - # remove default in aggregate spec, to handle common arguments - remove_default_spec(aggregate_spec) - - argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), - ) - - argument_spec.update(element_spec) - argument_spec.update(ios_argument_spec) - - required_one_of = [['name', 'aggregate']] - mutually_exclusive = [['name', 'aggregate']] - - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) - warnings = list() - - result = {'changed': False} - if warnings: - result['warnings'] = warnings - - want = map_params_to_obj(module) - have = map_config_to_obj(module) - - commands = map_obj_to_commands((want, have)) - result['commands'] = commands - - if commands: - if not module.check_mode: - load_config(module, commands) - result['changed'] = True - - failed_conditions = check_declarative_intent_params(module, want, result) - - if failed_conditions: - msg = 'One or more conditional statements have not been satisfied' - module.fail_json(msg=msg, failed_conditions=failed_conditions) - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/_ios_l2_interface.py b/lib/ansible/modules/network/ios/_ios_l2_interface.py deleted file mode 100644 index 710c435c4e..0000000000 --- a/lib/ansible/modules/network/ios/_ios_l2_interface.py +++ /dev/null @@ -1,499 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['deprecated'], - 'supported_by': 'network'} - -DOCUMENTATION = """ ---- -module: ios_l2_interface -extends_documentation_fragment: ios -version_added: "2.5" -short_description: Manage Layer-2 interface on Cisco IOS devices. -description: - - This module provides declarative management of Layer-2 interfaces on - Cisco IOS devices. -deprecated: - removed_in: '2.13' - alternative: ios_l2_interfaces - why: Newer and updated modules released with more functionality in Ansible 2.9 -author: - - Nathaniel Case (@Qalthos) -options: - name: - description: - - Full name of the interface excluding any logical - unit number, i.e. GigabitEthernet0/1. - required: true - aliases: ['interface'] - mode: - description: - - Mode in which interface needs to be configured. - default: access - choices: ['access', 'trunk'] - access_vlan: - description: - - Configure given VLAN in access port. - If C(mode=access), used as the access VLAN ID. - trunk_vlans: - description: - - List of VLANs to be configured in trunk port. - If C(mode=trunk), used as the VLAN range to ADD or REMOVE - from the trunk. - native_vlan: - description: - - Native VLAN to be configured in trunk port. - If C(mode=trunk), used as the trunk native VLAN ID. - trunk_allowed_vlans: - description: - - List of allowed VLANs in a given trunk port. - If C(mode=trunk), these are the only VLANs that will be - configured on the trunk, i.e. "2-10,15". - aggregate: - description: - - List of Layer-2 interface definitions. - state: - description: - - Manage the state of the Layer-2 Interface configuration. - default: present - choices: ['present','absent', 'unconfigured'] -""" - -EXAMPLES = """ -- name: Ensure GigabitEthernet0/5 is in its default l2 interface state - ios_l2_interface: - name: GigabitEthernet0/5 - state: unconfigured -- name: Ensure GigabitEthernet0/5 is configured for access vlan 20 - ios_l2_interface: - name: GigabitEthernet0/5 - mode: access - access_vlan: 20 -- name: Ensure GigabitEthernet0/5 only has vlans 5-10 as trunk vlans - ios_l2_interface: - name: GigabitEthernet0/5 - mode: trunk - native_vlan: 10 - trunk_allowed_vlans: 5-10 -- name: Ensure GigabitEthernet0/5 is a trunk port and ensure 2-50 are being tagged (doesn't mean others aren't also being tagged) - ios_l2_interface: - name: GigabitEthernet0/5 - mode: trunk - native_vlan: 10 - trunk_vlans: 2-50 -- name: Ensure these VLANs are not being tagged on the trunk - ios_l2_interface: - name: GigabitEthernet0/5 - mode: trunk - trunk_vlans: 51-4094 - state: absent -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always, except for the platforms that use Netconf transport to manage the device. - type: list - sample: - - interface GigabitEthernet0/5 - - switchport access vlan 20 -""" - -import re -from copy import deepcopy - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import remove_default_spec -from ansible.module_utils.network.ios.ios import load_config, run_commands -from ansible.module_utils.network.ios.ios import ios_argument_spec - - -def get_interface_type(interface): - intf_type = 'unknown' - if interface.upper()[:2] in ('ET', 'GI', 'FA', 'TE', 'FO', 'HU', 'TWE', 'TW'): - intf_type = 'ethernet' - elif interface.upper().startswith('VL'): - intf_type = 'svi' - elif interface.upper().startswith('LO'): - intf_type = 'loopback' - elif interface.upper()[:2] in ('MG', 'MA'): - intf_type = 'management' - elif interface.upper().startswith('PO'): - intf_type = 'portchannel' - elif interface.upper().startswith('NV'): - intf_type = 'nve' - - return intf_type - - -def is_switchport(name, module): - intf_type = get_interface_type(name) - - if intf_type in ('ethernet', 'portchannel'): - config = run_commands(module, ['show interface {0} switchport'.format(name)])[0] - match = re.search(r'Switchport: Enabled', config) - return bool(match) - return False - - -def interface_is_portchannel(name, module): - if get_interface_type(name) == 'ethernet': - config = run_commands(module, ['show run interface {0}'.format(name)])[0] - if any(c in config for c in ['channel group', 'channel-group']): - return True - return False - - -def get_switchport(name, module): - config = run_commands(module, ['show interface {0} switchport'.format(name)])[0] - mode = re.search(r'Administrative Mode: (?:.* )?(\w+)$', config, re.M) - access = re.search(r'Access Mode VLAN: (\d+)', config) - native = re.search(r'Trunking Native Mode VLAN: (\d+)', config) - trunk = re.search(r'Trunking VLANs Enabled: (.+)$', config, re.M) - if mode: - mode = mode.group(1) - if access: - access = access.group(1) - if native: - native = native.group(1) - if trunk: - trunk = trunk.group(1) - if trunk == 'ALL': - trunk = '1-4094' - - switchport_config = { - "interface": name, - "mode": mode, - "access_vlan": access, - "native_vlan": native, - "trunk_vlans": trunk, - } - - return switchport_config - - -def remove_switchport_config_commands(name, existing, proposed, module): - mode = proposed.get('mode') - commands = [] - command = None - - if mode == 'access': - av_check = existing.get('access_vlan') == proposed.get('access_vlan') - if av_check: - command = 'no switchport access vlan {0}'.format(existing.get('access_vlan')) - commands.append(command) - - elif mode == 'trunk': - # Supported Remove Scenarios for trunk_vlans_list - # 1) Existing: 1,2,3 Proposed: 1,2,3 - Remove all - # 2) Existing: 1,2,3 Proposed: 1,2 - Remove 1,2 Leave 3 - # 3) Existing: 1,2,3 Proposed: 2,3 - Remove 2,3 Leave 1 - # 4) Existing: 1,2,3 Proposed: 4,5,6 - None removed. - # 5) Existing: None Proposed: 1,2,3 - None removed. - existing_vlans = existing.get('trunk_vlans_list') - proposed_vlans = proposed.get('trunk_vlans_list') - vlans_to_remove = set(proposed_vlans).intersection(existing_vlans) - - if vlans_to_remove: - proposed_allowed_vlans = proposed.get('trunk_allowed_vlans') - remove_trunk_allowed_vlans = proposed.get('trunk_vlans', proposed_allowed_vlans) - command = 'switchport trunk allowed vlan remove {0}'.format(remove_trunk_allowed_vlans) - commands.append(command) - - native_check = existing.get('native_vlan') == proposed.get('native_vlan') - if native_check and proposed.get('native_vlan'): - command = 'no switchport trunk native vlan {0}'.format(existing.get('native_vlan')) - commands.append(command) - - if commands: - commands.insert(0, 'interface ' + name) - return commands - - -def get_switchport_config_commands(name, existing, proposed, module): - """Gets commands required to config a given switchport interface - """ - - proposed_mode = proposed.get('mode') - existing_mode = existing.get('mode') - commands = [] - command = None - - if proposed_mode != existing_mode: - if proposed_mode == 'trunk': - command = 'switchport mode trunk' - elif proposed_mode == 'access': - command = 'switchport mode access' - - if command: - commands.append(command) - - if proposed_mode == 'access': - av_check = str(existing.get('access_vlan')) == str(proposed.get('access_vlan')) - if not av_check: - command = 'switchport access vlan {0}'.format(proposed.get('access_vlan')) - commands.append(command) - - elif proposed_mode == 'trunk': - tv_check = existing.get('trunk_vlans_list') == proposed.get('trunk_vlans_list') - - if not tv_check: - if proposed.get('allowed'): - command = 'switchport trunk allowed vlan {0}'.format(proposed.get('trunk_allowed_vlans')) - commands.append(command) - - else: - existing_vlans = existing.get('trunk_vlans_list') - proposed_vlans = proposed.get('trunk_vlans_list') - vlans_to_add = set(proposed_vlans).difference(existing_vlans) - if vlans_to_add: - command = 'switchport trunk allowed vlan add {0}'.format(proposed.get('trunk_vlans')) - commands.append(command) - - native_check = str(existing.get('native_vlan')) == str(proposed.get('native_vlan')) - if not native_check and proposed.get('native_vlan'): - command = 'switchport trunk native vlan {0}'.format(proposed.get('native_vlan')) - commands.append(command) - - if commands: - commands.insert(0, 'interface ' + name) - return commands - - -def is_switchport_default(existing): - """Determines if switchport has a default config based on mode - Args: - existing (dict): existing switchport configuration from Ansible mod - Returns: - boolean: True if switchport has OOB Layer 2 config, i.e. - vlan 1 and trunk all and mode is access - """ - - c1 = str(existing['access_vlan']) == '1' - c2 = str(existing['native_vlan']) == '1' - c3 = existing['trunk_vlans'] == '1-4094' - c4 = existing['mode'] == 'access' - - default = c1 and c2 and c3 and c4 - - return default - - -def default_switchport_config(name): - commands = [] - commands.append('interface ' + name) - commands.append('switchport mode access') - commands.append('switch access vlan 1') - commands.append('switchport trunk native vlan 1') - commands.append('switchport trunk allowed vlan all') - return commands - - -def vlan_range_to_list(vlans): - result = [] - if vlans: - for part in vlans.split(','): - if part.lower() == 'none': - break - if part: - if '-' in part: - start, stop = (int(i) for i in part.split('-')) - result.extend(range(start, stop + 1)) - else: - result.append(int(part)) - return sorted(result) - - -def get_list_of_vlans(module): - config = run_commands(module, ['show vlan'])[0] - vlans = set() - - lines = config.strip().splitlines() - for line in lines: - line_parts = line.split() - if line_parts: - try: - int(line_parts[0]) - except ValueError: - continue - vlans.add(line_parts[0]) - - return list(vlans) - - -def flatten_list(commands): - flat_list = [] - for command in commands: - if isinstance(command, list): - flat_list.extend(command) - else: - flat_list.append(command) - return flat_list - - -def map_params_to_obj(module): - obj = [] - - aggregate = module.params.get('aggregate') - if aggregate: - for item in aggregate: - for key in item: - if item.get(key) is None: - item[key] = module.params[key] - - obj.append(item.copy()) - else: - obj.append({ - 'name': module.params['name'], - 'mode': module.params['mode'], - 'access_vlan': module.params['access_vlan'], - 'native_vlan': module.params['native_vlan'], - 'trunk_vlans': module.params['trunk_vlans'], - 'trunk_allowed_vlans': module.params['trunk_allowed_vlans'], - 'state': module.params['state'] - }) - - return obj - - -def main(): - """ main entry point for module execution - """ - element_spec = dict( - name=dict(type='str', aliases=['interface']), - mode=dict(choices=['access', 'trunk']), - access_vlan=dict(type='str'), - native_vlan=dict(type='str'), - trunk_vlans=dict(type='str'), - trunk_allowed_vlans=dict(type='str'), - state=dict(choices=['absent', 'present', 'unconfigured'], default='present') - ) - - aggregate_spec = deepcopy(element_spec) - - # remove default in aggregate spec, to handle common arguments - remove_default_spec(aggregate_spec) - - argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), - ) - - argument_spec.update(element_spec) - argument_spec.update(ios_argument_spec) - - module = AnsibleModule(argument_spec=argument_spec, - mutually_exclusive=[['access_vlan', 'trunk_vlans'], - ['access_vlan', 'native_vlan'], - ['access_vlan', 'trunk_allowed_vlans']], - supports_check_mode=True) - - warnings = list() - commands = [] - result = {'changed': False, 'warnings': warnings} - - want = map_params_to_obj(module) - for w in want: - name = w['name'] - mode = w['mode'] - access_vlan = w['access_vlan'] - state = w['state'] - trunk_vlans = w['trunk_vlans'] - native_vlan = w['native_vlan'] - trunk_allowed_vlans = w['trunk_allowed_vlans'] - - args = dict(name=name, mode=mode, access_vlan=access_vlan, - native_vlan=native_vlan, trunk_vlans=trunk_vlans, - trunk_allowed_vlans=trunk_allowed_vlans) - - proposed = dict((k, v) for k, v in args.items() if v is not None) - - name = name.lower() - - if mode == 'access' and state == 'present' and not access_vlan: - module.fail_json(msg='access_vlan param is required when mode=access && state=present') - - if mode == 'trunk' and access_vlan: - module.fail_json(msg='access_vlan param not supported when using mode=trunk') - - if not is_switchport(name, module): - module.fail_json(msg='Ensure interface is configured to be a L2' - '\nport first before using this module. You can use' - '\nthe ios_interface module for this.') - - if interface_is_portchannel(name, module): - module.fail_json(msg='Cannot change L2 config on physical ' - '\nport because it is in a portchannel. ' - '\nYou should update the portchannel config.') - - # existing will never be null for Eth intfs as there is always a default - existing = get_switchport(name, module) - - # Safeguard check - # If there isn't an existing, something is wrong per previous comment - if not existing: - module.fail_json(msg='Make sure you are using the FULL interface name') - - if trunk_vlans or trunk_allowed_vlans: - if trunk_vlans: - trunk_vlans_list = vlan_range_to_list(trunk_vlans) - elif trunk_allowed_vlans: - trunk_vlans_list = vlan_range_to_list(trunk_allowed_vlans) - proposed['allowed'] = True - - existing_trunks_list = vlan_range_to_list((existing['trunk_vlans'])) - - existing['trunk_vlans_list'] = existing_trunks_list - proposed['trunk_vlans_list'] = trunk_vlans_list - - current_vlans = get_list_of_vlans(module) - - if state == 'present': - if access_vlan and access_vlan not in current_vlans: - module.fail_json(msg='You are trying to configure a VLAN' - ' on an interface that\ndoes not exist on the ' - ' switch yet!', vlan=access_vlan) - elif native_vlan and native_vlan not in current_vlans: - module.fail_json(msg='You are trying to configure a VLAN' - ' on an interface that\ndoes not exist on the ' - ' switch yet!', vlan=native_vlan) - else: - command = get_switchport_config_commands(name, existing, proposed, module) - commands.append(command) - elif state == 'unconfigured': - is_default = is_switchport_default(existing) - if not is_default: - command = default_switchport_config(name) - commands.append(command) - elif state == 'absent': - command = remove_switchport_config_commands(name, existing, proposed, module) - commands.append(command) - - if trunk_vlans or trunk_allowed_vlans: - existing.pop('trunk_vlans_list') - proposed.pop('trunk_vlans_list') - - cmds = flatten_list(commands) - if cmds: - if module.check_mode: - module.exit_json(changed=True, commands=cmds) - else: - result['changed'] = True - load_config(module, cmds) - if 'configure' in cmds: - cmds.pop(0) - - result['commands'] = cmds - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/_ios_l3_interface.py b/lib/ansible/modules/network/ios/_ios_l3_interface.py deleted file mode 100644 index 8435720240..0000000000 --- a/lib/ansible/modules/network/ios/_ios_l3_interface.py +++ /dev/null @@ -1,327 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Ansible by Red Hat, inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['deprecated'], - 'supported_by': 'network'} - -DOCUMENTATION = """ ---- -module: ios_l3_interface -version_added: "2.5" -author: "Ganesh Nalawade (@ganeshrn)" -short_description: Manage Layer-3 interfaces on Cisco IOS network devices. -description: - - This module provides declarative management of Layer-3 interfaces - on IOS network devices. -deprecated: - removed_in: '2.13' - alternative: ios_l3_interfaces - why: Newer and updated modules released with more functionality in Ansible 2.9 -notes: - - Tested against IOS 15.2 -options: - name: - description: - - Name of the Layer-3 interface to be configured eg. GigabitEthernet0/2 - ipv4: - description: - - IPv4 address to be set for the Layer-3 interface mentioned in I(name) option. - The address format is <ipv4 address>/<mask>, the mask is number - in range 0-32 eg. 192.168.0.1/24 - ipv6: - description: - - IPv6 address to be set for the Layer-3 interface mentioned in I(name) option. - The address format is <ipv6 address>/<mask>, the mask is number - in range 0-128 eg. fd5d:12c9:2201:1::1/64 - aggregate: - description: - - List of Layer-3 interfaces definitions. Each of the entry in aggregate list should - define name of interface C(name) and a optional C(ipv4) or C(ipv6) address. - state: - description: - - State of the Layer-3 interface configuration. It indicates if the configuration should - be present or absent on remote device. - default: present - choices: ['present', 'absent'] -extends_documentation_fragment: ios -""" - -EXAMPLES = """ -- name: Remove GigabitEthernet0/3 IPv4 and IPv6 address - ios_l3_interface: - name: GigabitEthernet0/3 - state: absent -- name: Set GigabitEthernet0/3 IPv4 address - ios_l3_interface: - name: GigabitEthernet0/3 - ipv4: 192.168.0.1/24 -- name: Set GigabitEthernet0/3 IPv6 address - ios_l3_interface: - name: GigabitEthernet0/3 - ipv6: "fd5d:12c9:2201:1::1/64" -- name: Set GigabitEthernet0/3 in dhcp - ios_l3_interface: - name: GigabitEthernet0/3 - ipv4: dhcp - ipv6: dhcp -- name: Set interface Vlan1 (SVI) IPv4 address - ios_l3_interface: - name: Vlan1 - ipv4: 192.168.0.5/24 -- name: Set IP addresses on aggregate - ios_l3_interface: - aggregate: - - { name: GigabitEthernet0/3, ipv4: 192.168.2.10/24 } - - { name: GigabitEthernet0/3, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" } -- name: Remove IP addresses on aggregate - ios_l3_interface: - aggregate: - - { name: GigabitEthernet0/3, ipv4: 192.168.2.10/24 } - - { name: GigabitEthernet0/3, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" } - state: absent -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always, except for the platforms that use Netconf transport to manage the device. - type: list - sample: - - interface GigabitEthernet0/2 - - ip address 192.168.0.1 255.255.255.0 - - ipv6 address fd5d:12c9:2201:1::1/64 -""" -import re - -from copy import deepcopy - -from ansible.module_utils._text import to_text -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.ios import get_config, load_config -from ansible.module_utils.network.ios.ios import ios_argument_spec -from ansible.module_utils.network.common.config import NetworkConfig -from ansible.module_utils.network.common.utils import remove_default_spec -from ansible.module_utils.network.common.utils import is_netmask, is_masklen, to_netmask, to_masklen - - -def validate_ipv4(value, module): - if value: - address = value.split('/') - if len(address) != 2: - module.fail_json(msg='address format is <ipv4 address>/<mask>, got invalid format %s' % value) - - if not is_masklen(address[1]): - module.fail_json(msg='invalid value for mask: %s, mask should be in range 0-32' % address[1]) - - -def validate_ipv6(value, module): - if value: - address = value.split('/') - if len(address) != 2: - module.fail_json(msg='address format is <ipv6 address>/<mask>, got invalid format %s' % value) - else: - if not 0 <= int(address[1]) <= 128: - module.fail_json(msg='invalid value for mask: %s, mask should be in range 0-128' % address[1]) - - -def validate_param_values(module, obj, param=None): - if param is None: - param = module.params - for key in obj: - # validate the param value (if validator func exists) - validator = globals().get('validate_%s' % key) - if callable(validator): - validator(param.get(key), module) - - -def parse_config_argument(configobj, name, arg=None): - cfg = configobj['interface %s' % name] - cfg = '\n'.join(cfg.children) - - values = [] - matches = re.finditer(r'%s (.+)$' % arg, cfg, re.M) - for match in matches: - match_str = match.group(1).strip() - if arg == 'ipv6 address': - values.append(match_str) - else: - values = match_str - break - - return values or None - - -def search_obj_in_list(name, lst): - for o in lst: - if o['name'] == name: - return o - - return None - - -def map_obj_to_commands(updates, module): - commands = list() - want, have = updates - for w in want: - name = w['name'] - ipv4 = w['ipv4'] - ipv6 = w['ipv6'] - state = w['state'] - - interface = 'interface ' + name - commands.append(interface) - - obj_in_have = search_obj_in_list(name, have) - if state == 'absent' and obj_in_have: - if obj_in_have['ipv4']: - if ipv4: - address = ipv4.split('/') - if len(address) == 2: - ipv4 = '{0} {1}'.format(address[0], to_netmask(address[1])) - commands.append('no ip address {0}'.format(ipv4)) - else: - commands.append('no ip address') - if obj_in_have['ipv6']: - if ipv6: - commands.append('no ipv6 address {0}'.format(ipv6)) - else: - commands.append('no ipv6 address') - if 'dhcp' in obj_in_have['ipv6']: - commands.append('no ipv6 address dhcp') - - elif state == 'present': - if ipv4: - if obj_in_have is None or obj_in_have.get('ipv4') is None or ipv4 != obj_in_have['ipv4']: - address = ipv4.split('/') - if len(address) == 2: - ipv4 = '{0} {1}'.format(address[0], to_netmask(address[1])) - commands.append('ip address {0}'.format(ipv4)) - - if ipv6: - if obj_in_have is None or obj_in_have.get('ipv6') is None or ipv6.lower() not in [addr.lower() for addr in obj_in_have['ipv6']]: - commands.append('ipv6 address {0}'.format(ipv6)) - - if commands[-1] == interface: - commands.pop(-1) - - return commands - - -def map_config_to_obj(module): - config = get_config(module) - configobj = NetworkConfig(indent=1, contents=config) - - match = re.findall(r'^interface (\S+)', config, re.M) - if not match: - return list() - - instances = list() - - for item in set(match): - ipv4 = parse_config_argument(configobj, item, 'ip address') - if ipv4: - # eg. 192.168.2.10 255.255.255.0 -> 192.168.2.10/24 - address = ipv4.strip().split(' ') - if len(address) == 2 and is_netmask(address[1]): - ipv4 = '{0}/{1}'.format(address[0], to_text(to_masklen(address[1]))) - - obj = { - 'name': item, - 'ipv4': ipv4, - 'ipv6': parse_config_argument(configobj, item, 'ipv6 address'), - 'state': 'present' - } - instances.append(obj) - - return instances - - -def map_params_to_obj(module): - obj = [] - - aggregate = module.params.get('aggregate') - if aggregate: - for item in aggregate: - for key in item: - if item.get(key) is None: - item[key] = module.params[key] - - validate_param_values(module, item, item) - obj.append(item.copy()) - else: - obj.append({ - 'name': module.params['name'], - 'ipv4': module.params['ipv4'], - 'ipv6': module.params['ipv6'], - 'state': module.params['state'] - }) - - validate_param_values(module, obj) - - return obj - - -def main(): - """ main entry point for module execution - """ - element_spec = dict( - name=dict(), - ipv4=dict(), - ipv6=dict(), - state=dict(default='present', - choices=['present', 'absent']) - ) - - aggregate_spec = deepcopy(element_spec) - aggregate_spec['name'] = dict(required=True) - - # remove default in aggregate spec, to handle common arguments - remove_default_spec(aggregate_spec) - - argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), - ) - - argument_spec.update(element_spec) - argument_spec.update(ios_argument_spec) - - required_one_of = [['name', 'aggregate']] - mutually_exclusive = [['name', 'aggregate']] - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) - - warnings = list() - - result = {'changed': False} - - want = map_params_to_obj(module) - have = map_config_to_obj(module) - - commands = map_obj_to_commands((want, have), module) - result['commands'] = commands - - if commands: - if not module.check_mode: - resp = load_config(module, commands) - warnings.extend((out for out in resp if out)) - - result['changed'] = True - - if warnings: - result['warnings'] = warnings - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/_ios_vlan.py b/lib/ansible/modules/network/ios/_ios_vlan.py deleted file mode 100644 index d2b3dcf043..0000000000 --- a/lib/ansible/modules/network/ios/_ios_vlan.py +++ /dev/null @@ -1,350 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['deprecated'], - 'supported_by': 'network'} - -DOCUMENTATION = """ ---- -module: ios_vlan -version_added: "2.5" -author: "Trishna Guha (@trishnaguha)" -short_description: Manage VLANs on IOS network devices -description: - - This module provides declarative management of VLANs - on Cisco IOS network devices. -deprecated: - removed_in: '2.13' - alternative: ios_vlans - why: Newer and updated modules released with more functionality in Ansible 2.9 -notes: - - Tested against IOS 15.2 -options: - name: - description: - - Name of the VLAN. - vlan_id: - description: - - ID of the VLAN. Range 1-4094. - required: true - interfaces: - description: - - List of interfaces that should be associated to the VLAN. - required: true - associated_interfaces: - description: - - This is a intent option and checks the operational state of the for given vlan C(name) - for associated interfaces. If the value in the C(associated_interfaces) does not match with - the operational state of vlan interfaces on device it will result in failure. - version_added: "2.5" - delay: - description: - - Delay the play should wait to check for declarative intent params values. - default: 10 - aggregate: - description: List of VLANs definitions. - purge: - description: - - Purge VLANs not defined in the I(aggregate) parameter. - default: no - type: bool - state: - description: - - State of the VLAN configuration. - default: present - choices: ['present', 'absent', 'active', 'suspend'] -extends_documentation_fragment: ios -""" - -EXAMPLES = """ -- name: Create vlan - ios_vlan: - vlan_id: 100 - name: test-vlan - state: present - -- name: Add interfaces to VLAN - ios_vlan: - vlan_id: 100 - interfaces: - - GigabitEthernet0/0 - - GigabitEthernet0/1 - -- name: Check if interfaces is assigned to VLAN - ios_vlan: - vlan_id: 100 - associated_interfaces: - - GigabitEthernet0/0 - - GigabitEthernet0/1 - -- name: Delete vlan - ios_vlan: - vlan_id: 100 - state: absent - -- name: Add vlan using aggregate - ios_vlan: - aggregate: - - { vlan_id: 100, name: test-vlan, interfaces: [GigabitEthernet0/1, GigabitEthernet0/2], delay: 15, state: suspend } - - { vlan_id: 101, name: test-vlan, interfaces: GigabitEthernet0/3 } - -- name: Move interfaces to a different VLAN - ios_vlan: - vlan_id: 102 - interfaces: - - GigabitEthernet0/0 - - GigabitEthernet0/1 -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always - type: list - sample: - - vlan 100 - - name test-vlan -""" - -import re -import time - -from copy import deepcopy - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import remove_default_spec -from ansible.module_utils.network.ios.ios import load_config, run_commands, normalize_interface -from ansible.module_utils.network.ios.ios import ios_argument_spec - - -def search_obj_in_list(vlan_id, lst): - for o in lst: - if o['vlan_id'] == vlan_id: - return o - - -def map_obj_to_commands(updates, module): - commands = list() - want, have = updates - purge = module.params['purge'] - - for w in want: - vlan_id = w['vlan_id'] - name = w['name'] - interfaces = w['interfaces'] - state = w['state'] - - obj_in_have = search_obj_in_list(vlan_id, have) - - if state == 'absent': - if obj_in_have: - commands.append('no vlan {0}'.format(vlan_id)) - - elif state == 'present': - if not obj_in_have: - commands.append('vlan {0}'.format(vlan_id)) - if name: - commands.append('name {0}'.format(name)) - - if interfaces: - for i in interfaces: - commands.append('interface {0}'.format(i)) - commands.append('switchport mode access') - commands.append('switchport access vlan {0}'.format(vlan_id)) - - else: - if name: - if name != obj_in_have['name']: - commands.append('vlan {0}'.format(vlan_id)) - commands.append('name {0}'.format(name)) - - if interfaces: - if not obj_in_have['interfaces']: - for i in interfaces: - commands.append('vlan {0}'.format(vlan_id)) - commands.append('interface {0}'.format(i)) - commands.append('switchport mode access') - commands.append('switchport access vlan {0}'.format(vlan_id)) - - elif set(interfaces) != set(obj_in_have['interfaces']): - missing_interfaces = list(set(interfaces) - set(obj_in_have['interfaces'])) - for i in missing_interfaces: - commands.append('vlan {0}'.format(vlan_id)) - commands.append('interface {0}'.format(i)) - commands.append('switchport mode access') - commands.append('switchport access vlan {0}'.format(vlan_id)) - - superfluous_interfaces = list(set(obj_in_have['interfaces']) - set(interfaces)) - for i in superfluous_interfaces: - commands.append('vlan {0}'.format(vlan_id)) - commands.append('interface {0}'.format(i)) - commands.append('switchport mode access') - commands.append('no switchport access vlan {0}'.format(vlan_id)) - else: - commands.append('vlan {0}'.format(vlan_id)) - if name: - commands.append('name {0}'.format(name)) - commands.append('state {0}'.format(state)) - - if purge: - for h in have: - obj_in_want = search_obj_in_list(h['vlan_id'], want) - if not obj_in_want and h['vlan_id'] != '1': - commands.append('no vlan {0}'.format(h['vlan_id'])) - - return commands - - -def map_params_to_obj(module): - obj = [] - aggregate = module.params.get('aggregate') - if aggregate: - for item in aggregate: - for key in item: - if item.get(key) is None: - item[key] = module.params[key] - - d = item.copy() - d['vlan_id'] = str(d['vlan_id']) - - obj.append(d) - else: - obj.append({ - 'vlan_id': str(module.params['vlan_id']), - 'name': module.params['name'], - 'interfaces': module.params['interfaces'], - 'associated_interfaces': module.params['associated_interfaces'], - 'state': module.params['state'] - }) - - return obj - - -def parse_to_logical_rows(out): - started_yielding = False - cur_row = [] - for l in out.splitlines()[2:]: - if not l: - """Skip empty lines.""" - continue - if '0' < l[0] <= '9': - """Line starting with a number.""" - if started_yielding: - yield cur_row - cur_row = [] # Reset it to hold a next chunk - started_yielding = True - cur_row.append(l) - - # Return the rest of it: - yield cur_row - - -def map_ports_str_to_list(ports_str): - return list(filter(bool, (normalize_interface(p.strip()) for p in ports_str.split(', ')))) - - -def parse_to_obj(logical_rows): - first_row = logical_rows[0] - rest_rows = logical_rows[1:] - obj = re.match(r'(?P<vlan_id>\d+)\s+(?P<name>[^\s]+)\s+(?P<state>[^\s]+)\s*(?P<interfaces>.*)', first_row).groupdict() - if obj['state'] == 'suspended': - obj['state'] = 'suspend' - obj['interfaces'] = map_ports_str_to_list(obj['interfaces']) - obj['interfaces'].extend(prts_r for prts in rest_rows for prts_r in map_ports_str_to_list(prts)) - return obj - - -def parse_vlan_brief(vlan_out): - return [parse_to_obj(r) for r in parse_to_logical_rows(vlan_out)] - - -def map_config_to_obj(module): - return parse_vlan_brief(run_commands(module, ['show vlan brief'])[0]) - - -def check_declarative_intent_params(want, module, result): - - have = None - is_delay = False - - for w in want: - if w.get('associated_interfaces') is None: - continue - - if result['changed'] and not is_delay: - time.sleep(module.params['delay']) - is_delay = True - - if have is None: - have = map_config_to_obj(module) - - for i in w['associated_interfaces']: - obj_in_have = search_obj_in_list(w['vlan_id'], have) - if obj_in_have and 'interfaces' in obj_in_have and i not in obj_in_have['interfaces']: - module.fail_json(msg="Interface %s not configured on vlan %s" % (i, w['vlan_id'])) - - -def main(): - """ main entry point for module execution - """ - element_spec = dict( - vlan_id=dict(type='int'), - name=dict(), - interfaces=dict(type='list'), - associated_interfaces=dict(type='list'), - delay=dict(default=10, type='int'), - state=dict(default='present', - choices=['present', 'absent', 'active', 'suspend']) - ) - - aggregate_spec = deepcopy(element_spec) - aggregate_spec['vlan_id'] = dict(required=True) - - # remove default in aggregate spec, to handle common arguments - remove_default_spec(aggregate_spec) - - argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), - purge=dict(default=False, type='bool') - ) - - argument_spec.update(element_spec) - argument_spec.update(ios_argument_spec) - - required_one_of = [['vlan_id', 'aggregate']] - mutually_exclusive = [['vlan_id', 'aggregate']] - - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) - warnings = list() - result = {'changed': False} - if warnings: - result['warnings'] = warnings - - want = map_params_to_obj(module) - have = map_config_to_obj(module) - commands = map_obj_to_commands((want, have), module) - result['commands'] = commands - - if commands: - if not module.check_mode: - load_config(module, commands) - result['changed'] = True - - check_declarative_intent_params(want, module, result) - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_acl_interfaces.py b/lib/ansible/modules/network/ios/ios_acl_interfaces.py deleted file mode 100644 index 7286ac45a8..0000000000 --- a/lib/ansible/modules/network/ios/ios_acl_interfaces.py +++ /dev/null @@ -1,633 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The module file for ios_acl_interfaces -""" - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - -DOCUMENTATION = """ ---- -module: ios_acl_interfaces -version_added: '2.10' -short_description: Configure and manage access-control (ACL) attributes of interfaces on IOS devices. -description: This module configures and manages the access-control (ACL) attributes of interfaces on IOS platforms. -author: Sumit Jaiswal (@justjais) -notes: - - Tested against Cisco IOSv Version 15.2 on VIRL - - This module works with connection C(network_cli). - See L(IOS Platform Options,../network/user_guide/platform_ios.html). -options: - config: - description: A dictionary of ACL interfaces options - type: list - elements: dict - suboptions: - name: - description: Full name of the interface excluding any logical unit number, i.e. GigabitEthernet0/1. - type: str - required: True - access_groups: - description: Specify access-group for IP access list (standard or extended). - type: list - elements: dict - suboptions: - afi: - description: Specifies the AFI for the ACLs to be configured on this interface. - type: str - required: True - choices: - - ipv4 - - ipv6 - acls: - description: Specifies the ACLs for the provided AFI. - type: list - elements: dict - suboptions: - name: - description: Specifies the name of the IPv4/IPv4 ACL for the interface. - type: str - required: True - direction: - description: - - Specifies the direction of packets that the ACL will be applied on. - - With one direction already assigned, other acl direction cannot be same. - type: str - required: True - choices: - - in - - out - running_config: - description: - - The module, by default, will connect to the remote device and retrieve the current - running-config to use as a base for comparing against the contents of source. - There are times when it is not desirable to have the task get the current running-config - for every task in a playbook. The I(running_config) argument allows the implementer to - pass in the configuration to use as the base config for comparison. This value of this - option should be the output received from device by executing command. - type: str - state: - description: - - The state the configuration should be left in - type: str - choices: - - merged - - replaced - - overridden - - deleted - - gathered - - parsed - - rendered - default: merged -""" - -EXAMPLES = """ ---- - -# Using Merged - -# Before state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# interface GigabitEthernet0/2 -# ip access-group 123 out - -- name: "Merge module attributes of given access-groups" - ios_acl_interfaces: - config: - - name: GigabitEthernet0/1 - access_groups: - - afi: ipv4 - acls: - - name: 110 - direction: in - - name: 123 - direction: out - - afi: ipv6 - acls: - - name: test_v6 - direction: out - - name: temp_v6 - direction: in - - name: GigabitEthernet0/2 - access_groups: - - afi: ipv4 - acls: - - name: 100 - direction: in - state: merged - -# Commands Fired: -# --------------- -# -# interface GigabitEthernet0/1 -# ip access-group 110 in -# ip access-group 123 out -# ipv6 traffic-filter test_v6 out -# ipv6 traffic-filter temp_v6 in -# interface GigabitEthernet0/2 -# ip access-group 100 in -# ip access-group 123 out - - -# After state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# ip access-group 110 in -# ip access-group 123 out -# ipv6 traffic-filter test_v6 out -# ipv6 traffic-filter temp_v6 in -# interface GigabitEthernet0/2 -# ip access-group 110 in -# ip access-group 123 out - -# Using Replaced - -# Before state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# ip access-group 110 in -# ip access-group 123 out -# ipv6 traffic-filter test_v6 out -# ipv6 traffic-filter temp_v6 in -# interface GigabitEthernet0/2 -# ip access-group 110 in -# ip access-group 123 out - -- name: "Replace module attributes of given access-groups" - ios_acl_interfaces: - config: - - name: GigabitEthernet0/1 - access_groups: - - afi: ipv4 - acls: - - name: 100 - direction: out - - name: 110 - direction: in - state: replaced - -# Commands Fired: -# --------------- -# -# interface GigabitEthernet0/1 -# no ip access-group 123 out -# no ipv6 traffic-filter temp_v6 in -# no ipv6 traffic-filter test_v6 out -# ip access-group 100 out - -# After state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# ip access-group 100 out -# ip access-group 110 in -# interface GigabitEthernet0/2 -# ip access-group 110 in -# ip access-group 123 out - -# Using Overridden - -# Before state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# ip access-group 110 in -# ip access-group 123 out -# ipv6 traffic-filter test_v6 out -# ipv6 traffic-filter temp_v6 in -# interface GigabitEthernet0/2 -# ip access-group 110 in -# ip access-group 123 out - -- name: "Overridden module attributes of given access-groups" - ios_acl_interfaces: - config: - - name: GigabitEthernet0/1 - access_groups: - - afi: ipv4 - acls: - - name: 100 - direction: out - - name: 110 - direction: in - state: overridden - -# Commands Fired: -# --------------- -# -# interface GigabitEthernet0/1 -# no ip access-group 123 out -# no ipv6 traffic-filter test_v6 out -# no ipv6 traffic-filter temp_v6 in -# ip access-group 100 out -# interface GigabitEthernet0/2 -# no ip access-group 110 in -# no ip access-group 123 out - -# After state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# ip access-group 100 out -# ip access-group 110 in -# interface GigabitEthernet0/2 - -# Using Deleted - -# Before state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# ip access-group 110 in -# ip access-group 123 out -# ipv6 traffic-filter test_v6 out -# ipv6 traffic-filter temp_v6 in -# interface GigabitEthernet0/2 -# ip access-group 110 in -# ip access-group 123 out - -- name: "Delete module attributes of given Interface" - ios_acl_interfaces: - config: - - name: GigabitEthernet0/1 - state: deleted - -# Commands Fired: -# --------------- -# -# interface GigabitEthernet0/1 -# no ip access-group 110 in -# no ip access-group 123 out -# no ipv6 traffic-filter test_v6 out -# no ipv6 traffic-filter temp_v6 in - -# After state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# interface GigabitEthernet0/2 -# ip access-group 110 in -# ip access-group 123 out - -# Before state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# ip access-group 110 in -# ip access-group 123 out -# ipv6 traffic-filter test_v6 out -# ipv6 traffic-filter temp_v6 in -# interface GigabitEthernet0/2 -# ip access-group 110 in -# ip access-group 123 out - -- name: "Delete module attributes of given Interface based on AFI" - ios_acl_interfaces: - config: - - name: GigabitEthernet0/1 - access_groups: - - afi: ipv4 - state: deleted - -# Commands Fired: -# --------------- -# -# interface GigabitEthernet0/1 -# no ip access-group 110 in -# no ip access-group 123 out - -# After state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# ipv6 traffic-filter test_v6 out -# ipv6 traffic-filter temp_v6 in -# interface GigabitEthernet0/2 -# ip access-group 110 in -# ip access-group 123 out - -# Using DELETED without any config passed -#"(NOTE: This will delete all of configured resource module attributes from each configured interface)" - -# Before state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# ip access-group 110 in -# ip access-group 123 out -# ipv6 traffic-filter test_v6 out -# ipv6 traffic-filter temp_v6 in -# interface GigabitEthernet0/2 -# ip access-group 110 in -# ip access-group 123 out - -- name: "Delete module attributes of given access-groups from ALL Interfaces" - ios_acl_interfaces: - config: - state: deleted - -# Commands Fired: -# --------------- -# -# interface GigabitEthernet0/1 -# no ip access-group 110 in -# no ip access-group 123 out -# no ipv6 traffic-filter test_v6 out -# no ipv6 traffic-filter temp_v6 in -# interface GigabitEthernet0/2 -# no ip access-group 110 out -# no ip access-group 123 out - -# After state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# interface GigabitEthernet0/2 - -# Using Gathered - -# Before state: -# ------------- -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# ip access-group 110 in -# ip access-group 123 out -# ipv6 traffic-filter test_v6 out -# ipv6 traffic-filter temp_v6 in -# interface GigabitEthernet0/2 -# ip access-group 110 in -# ip access-group 123 out - -- name: Gather listed acl interfaces with provided configurations - ios_acl_interfaces: - config: - state: gathered - -# Module Execution Result: -# ------------------------ -# -# "gathered": [ -# { -# "name": "Loopback888" -# }, -# { -# "name": "GigabitEthernet0/0" -# }, -# { -# "access_groups": [ -# { -# "acls": [ -# { -# "direction": "in", -# "name": "110" -# }, -# { -# "direction": "out", -# "name": "123" -# } -# ], -# "afi": "ipv4" -# }, -# { -# "acls": [ -# { -# "direction": "in", -# "name": "temp_v6" -# }, -# { -# "direction": "out", -# "name": "test_v6" -# } -# ], -# "afi": "ipv6" -# } -# ], -# "name": "GigabitEthernet0/1" -# }, -# { -# "access_groups": [ -# { -# "acls": [ -# { -# "direction": "in", -# "name": "100" -# }, -# { -# "direction": "out", -# "name": "123" -# } -# ], -# "afi": "ipv4" -# } -# ], -# "name": "GigabitEthernet0/2" -# } -# ] - -# After state: -# ------------ -# -# vios#sh running-config | include interface|ip access-group|ipv6 traffic-filter -# interface Loopback888 -# interface GigabitEthernet0/0 -# interface GigabitEthernet0/1 -# ip access-group 110 in -# ip access-group 123 out -# ipv6 traffic-filter test_v6 out -# ipv6 traffic-filter temp_v6 in -# interface GigabitEthernet0/2 -# ip access-group 110 in -# ip access-group 123 out - -# Using Rendered - -- name: Render the commands for provided configuration - ios_acl_interfaces: - config: - - name: GigabitEthernet0/1 - access_groups: - - afi: ipv4 - acls: - - name: 110 - direction: in - - name: 123 - direction: out - - afi: ipv6 - acls: - - name: test_v6 - direction: out - - name: temp_v6 - direction: in - state: rendered - -# Module Execution Result: -# ------------------------ -# -# "rendered": [ -# "interface GigabitEthernet0/1", -# "ip access-group 110 in", -# "ip access-group 123 out", -# "ipv6 traffic-filter temp_v6 in", -# "ipv6 traffic-filter test_v6 out" -# ] - -# Using Parsed - -- name: Parse the commands for provided configuration - ios_acl_interfaces: - running_config: - "interface GigabitEthernet0/1 - ip access-group 110 in - ip access-group 123 out - ipv6 traffic-filter temp_v6 in - ipv6 traffic-filter test_v6 out" - state: parsed - -# Module Execution Result: -# ------------------------ -# -# "parsed": [ -# { -# "access_groups": [ -# { -# "acls": [ -# { -# "direction": "in", -# "name": "110" -# } -# ], -# "afi": "ipv4" -# }, -# { -# "acls": [ -# { -# "direction": "in", -# "name": "temp_v6" -# } -# ], -# "afi": "ipv6" -# } -# ], -# "name": "GigabitEthernet0/1" -# } -# ] - -""" - -RETURN = """ -before: - description: The configuration as structured data prior to module invocation. - returned: always - type: list - sample: The configuration returned will always be in the same format of the parameters above. -after: - description: The configuration as structured data after module completion. - returned: when changed - type: list - sample: The configuration returned will always be in the same format of the parameters above. -commands: - description: The set of commands pushed to the remote device - returned: always - type: list - sample: ['interface GigabitEthernet0/1', 'ip access-group 110 in', 'ipv6 traffic-filter test_v6 out'] -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.acl_interfaces.acl_interfaces import Acl_InterfacesArgs -from ansible.module_utils.network.ios.config.acl_interfaces.acl_interfaces import Acl_Interfaces - - -def main(): - """ - Main entry point for module execution - :returns: the result form module invocation - """ - required_if = [('state', 'merged', ('config',)), - ('state', 'replaced', ('config',)), - ('state', 'overridden', ('config',)), - ('state', 'rendered', ('config',)), - ('state', 'parsed', ('running_config',))] - - mutually_exclusive = [('config', 'running_config')] - - module = AnsibleModule(argument_spec=Acl_InterfacesArgs.argument_spec, - required_if=required_if, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) - - result = Acl_Interfaces(module).execute_module() - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_acls.py b/lib/ansible/modules/network/ios/ios_acls.py deleted file mode 100644 index a05214d8e1..0000000000 --- a/lib/ansible/modules/network/ios/ios_acls.py +++ /dev/null @@ -1,1417 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The module file for ios_acls -""" - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_acls -version_added: '2.10' -short_description: Manages named or numbered ACLs on IOS devices. -description: This module configures and manages the named or numbered ACLs on IOS platforms. -author: Sumit Jaiswal (@justjais) -notes: -- Tested against Cisco IOSv Version 15.2 on VIRL -- This module works with connection C(network_cli). - See L(IOS Platform Options,../network/user_guide/platform_ios.html). -options: - config: - description: A dictionary of ACL options. - type: list - elements: dict - suboptions: - afi: - description: - - The Address Family Indicator (AFI) for the Access Control Lists (ACL). - required: true - type: str - choices: - - ipv4 - - ipv6 - acls: - description: - - A list of Access Control Lists (ACL). - type: list - elements: dict - suboptions: - name: - description: The name or the number of the ACL. - required: true - type: str - acl_type: - description: - - ACL type - - Note, it's mandatory and required for Named ACL, but for - Numbered ACL it's not mandatory. - type: str - choices: - - extended - - standard - aces: - description: The entries within the ACL. - elements: dict - type: list - suboptions: - grant: - description: Specify the action. - type: str - choices: - - permit - - deny - sequence: - description: - - Sequence Number for the Access Control Entry(ACE). - - Refer to vendor documentation for valid values. - type: int - protocol: - description: - - Specify the protocol to match. - - Refer to vendor documentation for valid values. - type: str - protocol_options: - description: protocol type. - type: dict - suboptions: - protocol_number: - description: An IP protocol number - type: int - ahp: - description: Authentication Header Protocol. - type: bool - eigrp: - description: Cisco's EIGRP routing protocol. - type: bool - esp: - description: Encapsulation Security Payload. - type: bool - gre: - description: Cisco's GRE tunneling. - type: bool - hbh: - description: Hop by Hop options header. Valid for IPV6 - type: bool - icmp: - description: Internet Control Message Protocol. - type: dict - suboptions: - administratively_prohibited: - description: Administratively prohibited - type: bool - alternate_address: - description: Alternate address - type: bool - conversion_error: - description: Datagram conversion - type: bool - dod_host_prohibited: - description: Host prohibited - type: bool - dod_net_prohibited: - description: Net prohibited - type: bool - echo: - description: Echo (ping) - type: bool - echo_reply: - description: Echo reply - type: bool - general_parameter_problem: - description: Parameter problem - type: bool - host_isolated: - description: Host isolated - type: bool - host_precedence_unreachable: - description: Host unreachable for precedence - type: bool - host_redirect: - description: Host redirect - type: bool - host_tos_redirect: - description: Host redirect for TOS - type: bool - host_tos_unreachable: - description: Host unreachable for TOS - type: bool - host_unknown: - description: Host unknown - type: bool - host_unreachable: - description: Host unreachable - type: bool - information_reply: - description: Information replies - type: bool - information_request: - description: Information requests - type: bool - mask_reply: - description: Mask replies - type: bool - mask_request: - description: mask_request - type: bool - mobile_redirect: - description: Mobile host redirect - type: bool - net_redirect: - description: Network redirect - type: bool - net_tos_redirect: - description: Net redirect for TOS - type: bool - net_tos_unreachable: - description: Network unreachable for TOS - type: bool - net_unreachable: - description: Net unreachable - type: bool - network_unknown: - description: Network unknown - type: bool - no_room_for_option: - description: Parameter required but no room - type: bool - option_missing: - description: Parameter required but not present - type: bool - packet_too_big: - description: Fragmentation needed and DF set - type: bool - parameter_problem: - description: All parameter problems - type: bool - port_unreachable: - description: Port unreachable - type: bool - precedence_unreachable: - description: Precedence cutoff - type: bool - protocol_unreachable: - description: Protocol unreachable - type: bool - reassembly_timeout: - description: Reassembly timeout - type: bool - redirect: - description: All redirects - type: bool - router_advertisement: - description: Router discovery advertisements - type: bool - router_solicitation: - description: Router discovery solicitations - type: bool - source_quench: - description: Source quenches - type: bool - source_route_failed: - description: Source route failed - type: bool - time_exceeded: - description: All time exceededs - type: bool - timestamp_reply: - description: Timestamp replies - type: bool - timestamp_request: - description: Timestamp requests - type: bool - traceroute: - description: Traceroute - type: bool - ttl_exceeded: - description: TTL exceeded - type: bool - unreachable: - description: All unreachables - type: bool - igmp: - description: Internet Gateway Message Protocol. - type: dict - suboptions: - dvmrp: - description: Distance Vector Multicast Routing Protocol(2) - type: bool - host_query: - description: IGMP Membership Query(0) - type: bool - mtrace_resp: - description: Multicast Traceroute Response(7) - type: bool - mtrace_route: - description: Multicast Traceroute(8) - type: bool - pim: - description: Protocol Independent Multicast(3) - type: bool - trace: - description: Multicast trace(4) - type: bool - v1host_report: - description: IGMPv1 Membership Report(1) - type: bool - v2host_report: - description: IGMPv2 Membership Report(5) - type: bool - v2leave_group: - description: IGMPv2 Leave Group(6) - type: bool - v3host_report: - description: IGMPv3 Membership Report(9) - type: bool - ip: - description: Any Internet Protocol. - type: bool - ipv6: - description: Any IPv6. - type: bool - ipinip: - description: IP in IP tunneling. - type: bool - nos: - description: KA9Q NOS compatible IP over IP tunneling. - type: bool - ospf: - description: OSPF routing protocol. - type: bool - pcp: - description: Payload Compression Protocol. - type: bool - pim: - description: Protocol Independent Multicast. - type: bool - sctp: - description: Stream Control Transmission Protocol. - type: bool - udp: - description: User Datagram Protocol. - type: bool - tcp: - description: Match TCP packet flags - type: dict - suboptions: - ack: - description: Match on the ACK bit - type: bool - established: - description: Match established connections - type: bool - fin: - description: Match on the FIN bit - type: bool - psh: - description: Match on the PSH bit - type: bool - rst: - description: Match on the RST bit - type: bool - syn: - description: Match on the SYN bit - type: bool - urg: - description: Match on the URG bit - type: bool - source: - description: Specify the packet source. - type: dict - suboptions: - address: - description: Source network address. - type: str - wildcard_bits: - description: Destination wildcard bits, valid with IPV4 address. - type: str - any: - description: Match any source address. - type: bool - host: - description: A single source host - type: str - port_protocol: - description: - - Specify the destination port along with protocol. - - Note, Valid with TCP/UDP protocol_options - type: dict - suboptions: - eq: - description: Match only packets on a given port number. - type: str - gt: - description: Match only packets with a greater port number. - type: str - lt: - description: Match only packets with a lower port number. - type: str - neq: - description: Match only packets not on a given port number. - type: str - range: - description: Port group. - type: dict - suboptions: - start: - description: Specify the start of the port range. - type: int - end: - description: Specify the end of the port range. - type: int - destination: - description: Specify the packet destination. - type: dict - suboptions: - address: - description: Host address to match, or any single host address. - type: str - wildcard_bits: - description: Destination wildcard bits, valid with IPV4 address. - type: str - any: - description: Match any source address. - type: bool - host: - description: A single destination host - type: str - port_protocol: - description: - - Specify the destination port along with protocol. - - Note, Valid with TCP/UDP protocol_options - type: dict - suboptions: - eq: - description: Match only packets on a given port number. - type: str - gt: - description: Match only packets with a greater port number. - type: str - lt: - description: Match only packets with a lower port number. - type: str - neq: - description: Match only packets not on a given port number. - type: str - range: - description: Port group. - type: dict - suboptions: - start: - description: Specify the start of the port range. - type: int - end: - description: Specify the end of the port range. - type: int - dscp: - description: Match packets with given dscp value. - type: str - fragments: - description: Check non-initial fragments. - type: str - log: - description: Log matches against this entry. - type: str - log_input: - description: Log matches against this entry, including input interface. - type: str - option: - description: - - Match packets with given IP Options value. - - Valid only for named acls. - type: dict - suboptions: - add_ext: - description: Match packets with Address Extension Option (147). - type: bool - any_options: - description: Match packets with ANY Option. - type: bool - com_security: - description: Match packets with Commercial Security Option (134). - type: bool - dps: - description: Match packets with Dynamic Packet State Option (151). - type: bool - encode: - description: Match packets with Encode Option (15). - type: bool - eool: - description: Match packets with End of Options (0). - type: bool - ext_ip: - description: Match packets with Extended IP Option (145). - type: bool - ext_security: - description: Match packets with Extended Security Option (133). - type: bool - finn: - description: Match packets with Experimental Flow Control Option (205). - type: bool - imitd: - description: Match packets with IMI Traffic Desriptor Option (144). - type: bool - lsr: - description: Match packets with Loose Source Route Option (131). - type: bool - mtup: - description: Match packets with MTU Probe Option (11). - type: bool - mtur: - description: Match packets with MTU Reply Option (12). - type: bool - no_op: - description: Match packets with No Operation Option (1). - type: bool - nsapa: - description: Match packets with NSAP Addresses Option (150). - type: bool - record_route: - description: Match packets with Record Route Option (7). - type: bool - router_alert: - description: Match packets with Router Alert Option (148). - type: bool - sdb: - description: Match packets with Selective Directed Broadcast Option (149). - type: bool - security: - description: Match packets with Basic Security Option (130). - type: bool - ssr: - description: Match packets with Strict Source Routing Option (137). - type: bool - stream_id: - description: Match packets with Stream ID Option (136). - type: bool - timestamp: - description: Match packets with Time Stamp Option (68). - type: bool - traceroute: - description: Match packets with Trace Route Option (82). - type: bool - ump: - description: Match packets with Upstream Multicast Packet Option (152). - type: bool - visa: - description: Match packets with Experimental Access Control Option (142). - type: bool - zsu: - description: Match packets with Experimental Measurement Option (10). - type: bool - precedence: - description: Match packets with given precedence value. - type: int - time_range: - description: Specify a time-range. - type: str - tos: - description: - - Match packets with given TOS value. - - Note, DSCP and TOS are mutually exclusive - type: dict - suboptions: - service_value: - description: Type of service value - type: int - max_reliability: - description: Match packets with max reliable TOS (2). - type: bool - max_throughput: - description: Match packets with max throughput TOS (4). - type: bool - min_delay : - description: Match packets with min delay TOS (8). - type: bool - min_monetary_cost: - description: Match packets with min monetary cost TOS (1). - type: bool - normal: - description: Match packets with normal TOS (0). - type: bool - ttl: - description: Match packets with given TTL value. - type: dict - suboptions: - eq: - description: Match only packets on a given TTL number. - type: int - gt: - description: Match only packets with a greater TTL number. - type: int - lt: - description: Match only packets with a lower TTL number. - type: int - neq: - description: Match only packets not on a given TTL number. - type: int - range: - description: Match only packets in the range of TTLs. - type: dict - suboptions: - start: - description: Specify the start of the port range. - type: int - end: - description: Specify the end of the port range. - type: int - running_config: - description: - - The module, by default, will connect to the remote device and - retrieve the current running-config to use as a base for comparing - against the contents of source. There are times when it is not - desirable to have the task get the current running-config for - every task in a playbook. The I(running_config) argument allows the - implementer to pass in the configuration to use as the base - config for comparison. - type: str - state: - choices: - - merged - - replaced - - overridden - - deleted - - gathered - - rendered - - parsed - default: merged - description: - - The state of the configuration after module completion - type: str -""" - -EXAMPLES = """ ---- - -# Using merged - -# Before state: -# ------------- -# -# vios#sh access-lists -# Extended IP access list 110 -# 10 deny icmp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 echo dscp ef ttl eq 10 - -- name: Merge provided configuration with device configuration - ios_acl: - config: - - afi: ipv4 - acls: - - name: std_acl - acl_type: standard - aces: - - grant: deny - source: - address: 192.168.1.200 - - grant: deny - source: - address: 192.168.2.0 - wildcard_bits: 0.0.0.255 - - name: 110 - aces: - - grant: deny - sequence: 10 - protocol_options: - icmp: - traceroute: true - source: - address: 192.0.2.0 - wildcard_bits: 0.0.0.255 - destination: - address: 192.0.3.0 - wildcard_bits: 0.0.0.255 - dscp: ef - ttl: - eq: 10 - - grant: deny - protocol_options: - tcp: - ack: true - source: - host: 198.51.100.0 - destination: - host: 198.51.110.0 - port_protocol: - eq: telnet - - name: test - acl_type: extended - aces: - - grant: deny - protocol_options: - tcp: - fin: true - source: - address: 192.0.2.0 - wildcard_bits: 0.0.0.255 - destination: - address: 192.0.3.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: www - option: - traceroute: true - ttl: - eq: 10 - - name: 123 - aces: - - grant: deny - protocol_options: - tcp: - ack: true - source: - address: 198.51.100.0 - wildcard_bits: 0.0.0.255 - destination: - address: 198.51.101.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: telnet - tos: - service_value: 12 - - grant: deny - protocol_options: - tcp: - ack: true - source: - address: 192.0.3.0 - wildcard_bits: 0.0.0.255 - destination: - address: 192.0.4.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: www - dscp: ef - ttl: - lt: 20 - - afi: ipv6 - acls: - - name: R1_TRAFFIC - aces: - - grant: deny - protocol_options: - tcp: - ack: true - source: - any: true - port_protocol: - eq: www - destination: - any: true - port_protocol: - eq: telnet - dscp: af11 - state: merged - -# Commands fired: -# --------------- -# -# - ip access-list standard std_acl -# - deny 192.168.1.200 -# - deny 192.168.2.0 0.0.0.255 -# - ip access-list extended 110 -# - no 10 -# - 10 deny icmp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 traceroute dscp ef ttl eq 10 -# - deny tcp host 198.51.100.0 host 198.51.110.0 eq telnet ack -# - ip access-list extended test -# - deny tcp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 eq www fin option traceroute ttl eq 10 -# - ip access-list extended 123 -# - deny tcp 198.51.100.0 0.0.0.255 198.51.101.0 0.0.0.255 eq telnet ack tos 12 -# - deny tcp 192.0.3.0 0.0.0.255 192.0.4.0 0.0.0.255 eq www ack dscp ef ttl lt 20 -# - ipv6 access-list R1_TRAFFIC -# - deny tcp any eq www any eq telnet ack dscp af11 - -# After state: -# ------------ -# -# vios#sh access-lists -# Standard IP access list std_acl -# 10 deny 192.168.1.200 -# 20 deny 192.168.2.0, wildcard bits 0.0.0.255 -# Extended IP access list 110 -# 10 deny icmp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 traceroute dscp ef ttl eq 10 -# 20 deny tcp host 198.51.100.0 host 198.51.110.0 eq telnet ack -# Extended IP access list 123 -# 10 deny tcp 198.51.100.0 0.0.0.255 198.51.101.0 0.0.0.255 eq telnet ack tos 12 -# 20 deny tcp 192.0.3.0 0.0.0.255 192.0.4.0 0.0.0.255 eq www ack dscp ef ttl lt 20 -# Extended IP access list test -# 10 deny tcp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 eq www fin option traceroute ttl eq 10 -# IPv6 access list R1_TRAFFIC -# deny tcp any eq www any eq telnet ack dscp af11 sequence 10 - - -# Using replaced - -# Before state: -# ------------- -# -# vios#sh access-lists -# Standard IP access list std_acl -# 10 deny 192.168.1.200 -# 20 deny 192.168.2.0, wildcard bits 0.0.0.255 -# Extended IP access list 110 -# 10 deny icmp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 traceroute dscp ef ttl eq 10 -# 20 deny tcp host 198.51.100.0 host 198.51.110.0 eq telnet ack -# Extended IP access list 123 -# 10 deny tcp 198.51.100.0 0.0.0.255 198.51.101.0 0.0.0.255 eq telnet ack tos 12 -# 20 deny tcp 192.0.3.0 0.0.0.255 192.0.4.0 0.0.0.255 eq www ack dscp ef ttl lt 20 -# Extended IP access list test -# 10 deny tcp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 eq www fin option traceroute ttl eq 10 -# IPv6 access list R1_TRAFFIC -# deny tcp any eq www any eq telnet ack dscp af11 sequence 10 - - -- name: Replaces device configuration of listed acls with provided configuration - ios_acl: - config: - - afi: ipv4 - acls: - - name: 110 - aces: - - grant: deny - protocol_options: - tcp: - syn: true - source: - address: 192.0.2.0 - wildcard_bits: 0.0.0.255 - destination: - address: 192.0.3.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: www - dscp: ef - ttl: - eq: 10 - - name: 150 - aces: - - grant: deny - sequence: 20 - protocol_options: - tcp: - syn: true - source: - address: 198.51.100.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: telnet - destination: - address: 198.51.110.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: telnet - dscp: ef - ttl: - eq: 10 - state: replaced - -# Commands fired: -# --------------- -# -# - no ip access-list extended 110 -# - ip access-list extended 110 -# - deny tcp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 eq www syn dscp ef ttl eq 10 -# - ip access-list extended 150 -# - 20 deny tcp 198.51.100.0 0.0.0.255 eq telnet 198.51.110.0 0.0.0.255 eq telnet syn dscp ef ttl eq 10 - -# After state: -# ------------- -# -# vios#sh access-lists -# Standard IP access list std_acl -# 10 deny 192.168.1.200 -# 20 deny 192.168.2.0, wildcard bits 0.0.0.255 -# Extended IP access list 110 -# 10 deny tcp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 eq www syn dscp ef ttl eq 10 -# Extended IP access list 123 -# 10 deny tcp 198.51.100.0 0.0.0.255 198.51.101.0 0.0.0.255 eq telnet ack tos 12 -# 20 deny tcp 192.0.3.0 0.0.0.255 192.0.4.0 0.0.0.255 eq www ack dscp ef ttl lt 20 -# Extended IP access list 150 -# 20 deny tcp 198.51.100.0 0.0.0.255 eq telnet 198.51.110.0 0.0.0.255 eq telnet syn dscp ef ttl eq 10 -# Extended IP access list test -# 10 deny tcp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 eq www fin option traceroute ttl eq 10 -# IPv6 access list R1_TRAFFIC -# deny tcp any eq www any eq telnet ack dscp af11 sequence 10 - -# Using overridden - -# Before state: -# ------------- -# -# vios#sh access-lists -# Standard IP access list std_acl -# 10 deny 192.168.1.200 -# 20 deny 192.168.2.0, wildcard bits 0.0.0.255 -# Extended IP access list 110 -# 10 deny icmp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 traceroute dscp ef ttl eq 10 -# 20 deny tcp host 198.51.100.0 host 198.51.110.0 eq telnet ack -# Extended IP access list 123 -# 10 deny tcp 198.51.100.0 0.0.0.255 198.51.101.0 0.0.0.255 eq telnet ack tos 12 -# 20 deny tcp 192.0.3.0 0.0.0.255 192.0.4.0 0.0.0.255 eq www ack dscp ef ttl lt 20 -# Extended IP access list test -# 10 deny tcp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 eq www fin option traceroute ttl eq 10 -# IPv6 access list R1_TRAFFIC -# deny tcp any eq www any eq telnet ack dscp af11 sequence 10 - -- name: Override device configuration of all acls with provided configuration - ios_acl: - config: - - afi: ipv4 - acls: - - name: 110 - aces: - - grant: deny - sequence: 20 - protocol_options: - tcp: - ack: true - source: - address: 198.51.100.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: telnet - destination: - address: 198.51.110.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: www - dscp: ef - ttl: - eq: 10 - - name: 150 - aces: - - grant: deny - sequence: 10 - protocol_options: - tcp: - syn: true - source: - address: 198.51.100.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: telnet - destination: - address: 198.51.110.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: telnet - dscp: ef - ttl: - eq: 10 - state: overridden - -# Commands fired: -# --------------- -# -# - no ip access-list standard std_acl -# - no ip access-list extended 110 -# - no ip access-list extended 123 -# - no ip access-list extended 150 -# - no ip access-list extended test -# - no ipv6 access-list R1_TRAFFIC -# - ip access-list extended 150 -# - 10 deny tcp 198.51.100.0 0.0.0.255 eq telnet 198.51.110.0 0.0.0.255 eq telnet syn dscp ef ttl eq 10 -# - ip access-list extended 110 -# - 20 deny tcp 198.51.100.0 0.0.0.255 eq telnet 198.51.110.0 0.0.0.255 eq www ack dscp ef ttl eq 10 - -# After state: -# ------------- -# -# vios#sh access-lists -# Extended IP access list 110 -# 20 deny tcp 198.51.100.0 0.0.0.255 eq telnet 198.51.110.0 0.0.0.255 eq www ack dscp ef ttl eq 10 -# Extended IP access list 150 -# 10 deny tcp 198.51.100.0 0.0.0.255 eq telnet 198.51.110.0 0.0.0.255 eq telnet syn dscp ef ttl eq 10 - -# Using Deleted - -# Before state: -# ------------- -# -# vios#sh access-lists -# Standard IP access list std_acl -# 10 deny 192.168.1.200 -# 20 deny 192.168.2.0, wildcard bits 0.0.0.255 -# Extended IP access list 110 -# 10 deny icmp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 traceroute dscp ef ttl eq 10 -# 20 deny tcp host 198.51.100.0 host 198.51.110.0 eq telnet ack -# Extended IP access list 123 -# 10 deny tcp 198.51.100.0 0.0.0.255 198.51.101.0 0.0.0.255 eq telnet ack tos 12 -# 20 deny tcp 192.0.3.0 0.0.0.255 192.0.4.0 0.0.0.255 eq www ack dscp ef ttl lt 20 -# Extended IP access list test -# 10 deny tcp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 eq www fin option traceroute ttl eq 10 -# IPv6 access list R1_TRAFFIC -# deny tcp any eq www any eq telnet ack dscp af11 sequence 10 - -- name: "Delete module attributes of given acls (Note: This won't delete the interface itself)" - ios_acl: - config: - - afi: ipv4 - acls: - - name: test - acl_type: extended - - name: 110 - - name: 123 - aces: - - sequence: 10 - - afi: ipv6 - acls: - - name: R1_TRAFFIC - state: deleted - -# Commands fired: -# --------------- -# -# - no ip access-list extended test -# - no ip access-list extended 110 -# - ip access-list extended 123 -# - no 10 -# - no ipv6 access-list R1_TRAFFIC - -# After state: -# ------------- -# -# vios#sh access-lists -# Standard IP access list std_acl -# 10 deny 192.168.1.200 -# 20 deny 192.168.2.0, wildcard bits 0.0.0.255 -# Extended IP access list 123 -# 20 deny tcp 192.0.3.0 0.0.0.255 192.0.4.0 0.0.0.255 eq www ack dscp ef ttl lt 20 - -# Before state: -# ------------- -# -# vios#sh access-lists -# Standard IP access list std_acl -# 10 deny 192.168.1.200 -# 20 deny 192.168.2.0, wildcard bits 0.0.0.255 -# Extended IP access list 110 -# 10 deny icmp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 traceroute dscp ef ttl eq 10 -# 20 deny tcp host 198.51.100.0 host 198.51.110.0 eq telnet ack -# Extended IP access list 123 -# 10 deny tcp 198.51.100.0 0.0.0.255 198.51.101.0 0.0.0.255 eq telnet ack tos 12 -# 20 deny tcp 192.0.3.0 0.0.0.255 192.0.4.0 0.0.0.255 eq www ack dscp ef ttl lt 20 -# Extended IP access list test -# 10 deny tcp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 eq www fin option traceroute ttl eq 10 -# IPv6 access list R1_TRAFFIC -# deny tcp any eq www any eq telnet ack dscp af11 sequence 10 - -- name: "Delete module attributes of given ACL based on AFI (Note: This won't delete the interface itself)" - ios_acl: - config: - - afi: ipv4 - state: deleted - -# Commands fired: -# --------------- -# -# - no ip access-list standard std_acl -# - no ip access-list extended test -# - no ip access-list extended 110 -# - no ip access-list extended 123 - -# After state: -# ------------- -# -# vios#sh access-lists -# IPv6 access list R1_TRAFFIC -# deny tcp any eq www any eq telnet ack dscp af11 sequence 10 - -# Using Deleted without any config passed -#"(NOTE: This will delete all of configured resource module attributes from each configured interface)" - -# Before state: -# ------------- -# -# vios#sh access-lists -# Standard IP access list std_acl -# 10 deny 192.168.1.200 -# 20 deny 192.168.2.0, wildcard bits 0.0.0.255 -# Extended IP access list 110 -# 10 deny icmp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 traceroute dscp ef ttl eq 10 -# 20 deny tcp host 198.51.100.0 host 198.51.110.0 eq telnet ack -# Extended IP access list 123 -# 10 deny tcp 198.51.100.0 0.0.0.255 198.51.101.0 0.0.0.255 eq telnet ack tos 12 -# 20 deny tcp 192.0.3.0 0.0.0.255 192.0.4.0 0.0.0.255 eq www ack dscp ef ttl lt 20 -# Extended IP access list test -# 10 deny tcp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 eq www fin option traceroute ttl eq 10 -# IPv6 access list R1_TRAFFIC -# deny tcp any eq www any eq telnet ack dscp af11 sequence 10 - -- name: "Delete module attributes of all acls (Note: This won't delete the interface itself)" - ios_acl: - state: deleted - -# Commands fired: -# --------------- -# -# - no ip access-list extended test -# - no ip access-list extended 110 -# - no ip access-list extended 123 -# - no ip access-list extended test -# - no ipv6 access-list R1_TRAFFIC - -# After state: -# ------------- -# -# vios#sh access-lists - -# Using Gathered - -# Before state: -# ------------- -# -# vios#sh access-lists -# Standard IP access list std_acl -# 10 deny 192.168.1.200 -# 20 deny 192.168.2.0, wildcard bits 0.0.0.255 -# Extended IP access list 110 -# 10 deny icmp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 traceroute dscp ef ttl eq 10 -# 20 deny tcp host 198.51.100.0 host 198.51.110.0 eq telnet ack -# Extended IP access list 123 -# 10 deny tcp 198.51.100.0 0.0.0.255 198.51.101.0 0.0.0.255 eq telnet ack tos 12 -# 20 deny tcp 192.0.3.0 0.0.0.255 192.0.4.0 0.0.0.255 eq www ack dscp ef ttl lt 20 -# Extended IP access list test -# 10 deny tcp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 eq www fin option traceroute ttl eq 10 -# IPv6 access list R1_TRAFFIC -# deny tcp any eq www any eq telnet ack dscp af11 sequence 10 - -- name: Gather listed acls interfaces with provided configurations - ios_acl_interfaces: - config: - state: gathered - -# Module Execution Result: -# ------------------------ -# -# "gathered": [ -# { -# "acls": [ -# { -# "aces": [ -# { -# "destination": { -# "address": "192.0.3.0", -# "wildcard_bits": "0.0.0.255" -# }, -# "dscp": "ef", -# "grant": "deny", -# "protocol_options": { -# "icmp": { -# "echo": true -# } -# }, -# "sequence": 10, -# "source": { -# "address": "192.0.2.0", -# "wildcard_bits": "0.0.0.255" -# }, -# "ttl": { -# "eq": 10 -# } -# } -# ], -# "acl_type": "extended", -# "name": "110" -# }, -# { -# "aces": [ -# { -# "destination": { -# "address": "198.51.101.0", -# "port_protocol": { -# "eq": "telnet" -# }, -# "wildcard_bits": "0.0.0.255" -# }, -# "grant": "deny", -# "protocol_options": { -# "tcp": { -# "ack": true -# } -# }, -# "sequence": 10, -# "source": { -# "address": "198.51.100.0", -# "wildcard_bits": "0.0.0.255" -# }, -# "tos": { -# "service_value": 12 -# } -# }, -# { -# "destination": { -# "address": "192.0.4.0", -# "port_protocol": { -# "eq": "www" -# }, -# "wildcard_bits": "0.0.0.255" -# }, -# "dscp": "ef", -# "grant": "deny", -# "protocol_options": { -# "tcp": { -# "ack": true -# } -# }, -# "sequence": 20, -# "source": { -# "address": "192.0.3.0", -# "wildcard_bits": "0.0.0.255" -# }, -# "ttl": { -# "lt": 20 -# } -# } -# ], -# "acl_type": "extended", -# "name": "123" -# }, -# { -# "aces": [ -# { -# "destination": { -# "address": "192.0.3.0", -# "port_protocol": { -# "eq": "www" -# }, -# "wildcard_bits": "0.0.0.255" -# }, -# "grant": "deny", -# "option": { -# "traceroute": true -# }, -# "protocol_options": { -# "tcp": { -# "fin": true -# } -# }, -# "sequence": 10, -# "source": { -# "address": "192.0.2.0", -# "wildcard_bits": "0.0.0.255" -# }, -# "ttl": { -# "eq": 10 -# } -# } -# ], -# "acl_type": "extended", -# "name": "test_acl" -# } -# ], -# "afi": "ipv4" -# }, -# { -# "acls": [ -# { -# "aces": [ -# { -# "destination": { -# "any": true, -# "port_protocol": { -# "eq": "telnet" -# } -# }, -# "dscp": "af11", -# "grant": "deny", -# "protocol_options": { -# "tcp": { -# "ack": true -# } -# }, -# "sequence": 10, -# "source": { -# "any": true, -# "port_protocol": { -# "eq": "www" -# } -# } -# } -# ], -# "name": "R1_TRAFFIC" -# } -# ], -# "afi": "ipv6" -# } -# ] - -# Using Rendered - -- name: Rendered the provided configuration with the exisiting running configuration - ios_acl: - config: - - afi: ipv4 - acls: - - name: 110 - aces: - - grant: deny - sequence: 10 - protocol_options: - tcp: - syn: true - source: - address: 192.0.2.0 - wildcard_bits: 0.0.0.255 - destination: - address: 192.0.3.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: www - dscp: ef - ttl: - eq: 10 - - name: 150 - aces: - - grant: deny - protocol_options: - tcp: - syn: true - source: - address: 198.51.100.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: telnet - destination: - address: 198.51.110.0 - wildcard_bits: 0.0.0.255 - port_protocol: - eq: telnet - dscp: ef - ttl: - eq: 10 - state: rendered - -# Module Execution Result: -# ------------------------ -# -# "rendered": [ -# "ip access-list extended 110", -# "10 deny tcp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 eq www syn dscp ef ttl eq 10", -# "ip access-list extended 150", -# "deny tcp 198.51.100.0 0.0.0.255 eq telnet 198.51.110.0 0.0.0.255 eq telnet syn dscp ef ttl eq 10" -# ] - -# Using Parsed - -- name: Parse the commands for provided configuration - ios_acl: - running_config: - "ipv6 access-list R1_TRAFFIC - deny tcp any eq www any eq telnet ack dscp af11" - state: parsed - -# Module Execution Result: -# ------------------------ -# -# "parsed": [ -# { -# "acls": [ -# { -# "aces": [ -# { -# "destination": { -# "any": true, -# "port_protocol": { -# "eq": "telnet" -# } -# }, -# "dscp": "af11", -# "grant": "deny", -# "protocol_options": { -# "tcp": { -# "ack": true -# } -# }, -# "source": { -# "any": true, -# "port_protocol": { -# "eq": "www" -# } -# } -# } -# ], -# "name": "R1_TRAFFIC" -# } -# ], -# "afi": "ipv6" -# } -# ] - -""" - -RETURN = """ -before: - description: The configuration as structured data prior to module invocation. - returned: always - type: list - sample: The configuration returned will always be in the same format of the parameters above. -after: - description: The configuration as structured data after module completion. - returned: when changed - type: list - sample: The configuration returned will always be in the same format of the parameters above. -commands: - description: The set of commands pushed to the remote device - returned: always - type: list - sample: ['ip access-list extended 110', 'deny icmp 192.0.2.0 0.0.0.255 192.0.3.0 0.0.0.255 echo dscp ef ttl eq 10'] -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.acls.acls import AclsArgs -from ansible.module_utils.network.ios.config.acls.acls import Acls - - -def main(): - """ - Main entry point for module execution - - :returns: the result form module invocation - """ - required_if = [('state', 'merged', ('config',)), - ('state', 'replaced', ('config',)), - ('state', 'overridden', ('config',)), - ('state', 'rendered', ('config',)), - ('state', 'parsed', ('running_config',))] - - mutually_exclusive = [('config', 'running_config')] - - module = AnsibleModule(argument_spec=AclsArgs.argument_spec, - required_if=required_if, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) - - result = Acls(module).execute_module() - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_banner.py b/lib/ansible/modules/network/ios/ios_banner.py deleted file mode 100644 index c28838407c..0000000000 --- a/lib/ansible/modules/network/ios/ios_banner.py +++ /dev/null @@ -1,186 +0,0 @@ -#!/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 <http://www.gnu.org/licenses/>. -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_banner -version_added: "2.3" -author: "Ricardo Carrillo Cruz (@rcarrillocruz)" -short_description: Manage multiline banners on Cisco IOS devices -description: - - This will configure both login and motd banners on remote devices - running Cisco IOS. It allows playbooks to add or remote - banner text from the active running configuration. -extends_documentation_fragment: ios -notes: - - Tested against IOS 15.6 -options: - banner: - description: - - Specifies which banner should be configured on the remote device. - In Ansible 2.4 and earlier only I(login) and I(motd) were supported. - required: true - choices: ['login', 'motd', 'exec', 'incoming', 'slip-ppp'] - text: - description: - - The banner text that should be - present in the remote device running configuration. This argument - accepts a multiline string, with no empty lines. Requires I(state=present). - state: - description: - - Specifies whether or not the configuration is - present in the current devices active running configuration. - default: present - choices: ['present', 'absent'] -""" - -EXAMPLES = """ -- name: configure the login banner - ios_banner: - banner: login - text: | - this is my login banner - that contains a multiline - string - state: present - -- name: remove the motd banner - ios_banner: - banner: motd - state: absent - -- name: Configure banner from file - ios_banner: - banner: motd - text: "{{ lookup('file', './config_partial/raw_banner.cfg') }}" - state: present - -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always - type: list - sample: - - banner login - - this is my login banner - - that contains a multiline - - string -""" -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.ios import get_config, load_config -from ansible.module_utils.network.ios.ios import ios_argument_spec -from re import search, M - - -def map_obj_to_commands(updates, module): - commands = list() - want, have = updates - state = module.params['state'] - - if state == 'absent' and 'text' in have.keys() and have['text']: - commands.append('no banner %s' % module.params['banner']) - - elif state == 'present': - if want['text'] and (want['text'] != have.get('text')): - banner_cmd = 'banner %s' % module.params['banner'] - banner_cmd += ' @\n' - banner_cmd += want['text'].strip('\n') - banner_cmd += '\n@' - commands.append(banner_cmd) - - return commands - - -def map_config_to_obj(module): - """ - This function gets the banner config without stripping any whitespaces, - and then fetches the required banner from it. - :param module: - :return: banner config dict object. - """ - out = get_config(module, flags='| begin banner %s' % module.params['banner']) - if out: - regex = 'banner ' + module.params['banner'] + ' ^C\n' - if search('banner ' + module.params['banner'], out, M): - output = str((out.split(regex))[1].split("^C\n")[0]) - else: - output = None - else: - output = None - obj = {'banner': module.params['banner'], 'state': 'absent'} - if output: - obj['text'] = output - obj['state'] = 'present' - return obj - - -def map_params_to_obj(module): - text = module.params['text'] - return { - 'banner': module.params['banner'], - 'text': text, - 'state': module.params['state'] - } - - -def main(): - """ main entry point for module execution - """ - argument_spec = dict( - banner=dict(required=True, choices=['login', 'motd', 'exec', 'incoming', 'slip-ppp']), - text=dict(), - state=dict(default='present', choices=['present', 'absent']) - ) - - argument_spec.update(ios_argument_spec) - - required_if = [('state', 'present', ('text',))] - - module = AnsibleModule(argument_spec=argument_spec, - required_if=required_if, - supports_check_mode=True) - - warnings = list() - - result = {'changed': False} - if warnings: - result['warnings'] = warnings - want = map_params_to_obj(module) - have = map_config_to_obj(module) - - commands = map_obj_to_commands((want, have), module) - result['commands'] = commands - - if commands: - if not module.check_mode: - load_config(module, commands) - - result['changed'] = True - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_bgp.py b/lib/ansible/modules/network/ios/ios_bgp.py deleted file mode 100644 index 88fe29a12c..0000000000 --- a/lib/ansible/modules/network/ios/ios_bgp.py +++ /dev/null @@ -1,438 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# (c) 2019, Ansible by Red Hat, inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -# - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_bgp -version_added: "2.8" -author: "Nilashish Chakraborty (@NilashishC)" -short_description: Configure global BGP protocol settings on Cisco IOS. -description: - - This module provides configuration management of global BGP parameters - on devices running Cisco IOS -notes: - - Tested against Cisco IOS Version 15.6(3)M2 -options: - config: - description: - - Specifies the BGP related configuration. - suboptions: - bgp_as: - description: - - Specifies the BGP Autonomous System (AS) number to configure on the device. - type: int - required: true - router_id: - description: - - Configures the BGP routing process router-id value. - default: null - log_neighbor_changes: - description: - - Enable/disable logging neighbor up/down and reset reason. - type: bool - neighbors: - description: - - Specifies BGP neighbor related configurations. - suboptions: - neighbor: - description: - - Neighbor router address. - required: True - remote_as: - description: - - Remote AS of the BGP neighbor to configure. - type: int - required: True - update_source: - description: - - Source of the routing updates. - password: - description: - - Password to authenticate the BGP peer connection. - enabled: - description: - - Administratively shutdown or enable a neighbor. - type: bool - description: - description: - - Neighbor specific description. - ebgp_multihop: - description: - - Specifies the maximum hop count for EBGP neighbors not on directly connected networks. - - The range is from 1 to 255. - type: int - peer_group: - description: - - Name of the peer group that the neighbor is a member of. - timers: - description: - - Specifies BGP neighbor timer related configurations. - suboptions: - keepalive: - description: - - Frequency (in seconds) with which the device sends keepalive messages to its peer. - - The range is from 0 to 65535. - type: int - required: True - holdtime: - description: - - Interval (in seconds) after not receiving a keepalive message that IOS declares a peer dead. - - The range is from 0 to 65535. - type: int - required: True - min_neighbor_holdtime: - description: - - Interval (in seconds) specifying the minimum acceptable hold-time from a BGP neighbor. - - The minimum acceptable hold-time must be less than, or equal to, the interval specified in the holdtime argument. - - The range is from 0 to 65535. - type: int - local_as: - description: - - The local AS number for the neighbor. - type: int - networks: - description: - - Specify Networks to announce via BGP. - - For operation replace, this option is mutually exclusive with networks option under address_family. - - For operation replace, if the device already has an address family activated, this option is not allowed. - suboptions: - prefix: - description: - - Network ID to announce via BGP. - required: True - masklen: - description: - - Subnet mask length for the Network to announce(e.g, 8, 16, 24, etc.). - route_map: - description: - - Route map to modify the attributes. - address_family: - description: - - Specifies BGP address family related configurations. - suboptions: - afi: - description: - - Type of address family to configure. - choices: - - ipv4 - - ipv6 - required: True - safi: - description: - - Specifies the type of cast for the address family. - choices: - - flowspec - - unicast - - multicast - - labeled-unicast - default: unicast - synchronization: - description: - - Enable/disable IGP synchronization. - type: bool - auto_summary: - description: - - Enable/disable automatic network number summarization. - type: bool - redistribute: - description: - - Specifies the redistribute information from another routing protocol. - suboptions: - protocol: - description: - - Specifies the protocol for configuring redistribute information. - choices: ['ospf', 'ospfv3', 'eigrp', 'isis', 'static', 'connected', 'odr', 'lisp', 'mobile', 'rip'] - required: True - id: - description: - - Identifier for the routing protocol for configuring redistribute information. - - Valid for protocols 'ospf', 'ospfv3' and 'eigrp'. - metric: - description: - - Specifies the metric for redistributed routes. - route_map: - description: - - Specifies the route map reference. - networks: - description: - - Specify Networks to announce via BGP. - - For operation replace, this option is mutually exclusive with root level networks option. - suboptions: - prefix: - description: - - Network ID to announce via BGP. - required: True - masklen: - description: - - Subnet mask length for the Network to announce(e.g, 8, 16, 24, etc.). - route_map: - description: - - Route map to modify the attributes. - neighbors: - description: - - Specifies BGP neighbor related configurations in Address Family configuration mode. - suboptions: - neighbor: - description: - - Neighbor router address. - required: True - advertisement_interval: - description: - - Minimum interval between sending BGP routing updates for this neighbor. - type: int - route_reflector_client: - description: - - Specify a neighbor as a route reflector client. - type: bool - route_server_client: - description: - - Specify a neighbor as a route server client. - type: bool - activate: - description: - - Enable the Address Family for this Neighbor. - type: bool - remove_private_as: - description: - - Remove the private AS number from outbound updates. - type: bool - next_hop_self: - description: - - Enable/disable the next hop calculation for this neighbor. - type: bool - next_hop_unchanged: - description: - - Propagate next hop unchanged for iBGP paths to this neighbor. - type: bool - maximum_prefix: - description: - - Maximum number of prefixes to accept from this peer. - - The range is from 1 to 2147483647. - type: int - prefix_list_in: - description: - - Name of ip prefix-list to apply to incoming prefixes. - prefix_list_out: - description: - - Name of ip prefix-list to apply to outgoing prefixes. - operation: - description: - - Specifies the operation to be performed on the BGP process configured on the device. - - In case of merge, the input configuration will be merged with the existing BGP configuration on the device. - - In case of replace, if there is a diff between the existing configuration and the input configuration, the - existing configuration will be replaced by the input configuration for every option that has the diff. - - In case of override, all the existing BGP configuration will be removed from the device and replaced with - the input configuration. - - In case of delete the existing BGP configuration will be removed from the device. - default: merge - choices: ['merge', 'replace', 'override', 'delete'] -""" - -EXAMPLES = """ -- name: configure global bgp as 64496 - ios_bgp: - config: - bgp_as: 64496 - router_id: 192.0.2.1 - log_neighbor_changes: True - neighbors: - - neighbor: 203.0.113.5 - remote_as: 64511 - timers: - keepalive: 300 - holdtime: 360 - min_neighbor_holdtime: 360 - - neighbor: 198.51.100.2 - remote_as: 64498 - networks: - - prefix: 198.51.100.0 - route_map: RMAP_1 - - prefix: 192.0.2.0 - masklen: 23 - address_family: - - afi: ipv4 - safi: unicast - redistribute: - - protocol: ospf - id: 223 - metric: 10 - operation: merge - -- name: Configure BGP neighbors - ios_bgp: - config: - bgp_as: 64496 - neighbors: - - neighbor: 192.0.2.10 - remote_as: 64496 - password: ansible - description: IBGP_NBR_1 - ebgp_multihop: 100 - timers: - keepalive: 300 - holdtime: 360 - min_neighbor_holdtime: 360 - - neighbor: 192.0.2.15 - remote_as: 64496 - description: IBGP_NBR_2 - ebgp_multihop: 150 - operation: merge - -- name: Configure root-level networks for BGP - ios_bgp: - config: - bgp_as: 64496 - networks: - - prefix: 203.0.113.0 - masklen: 27 - route_map: RMAP_1 - - prefix: 203.0.113.32 - masklen: 27 - route_map: RMAP_2 - operation: merge - -- name: Configure BGP neighbors under address family mode - ios_bgp: - config: - bgp_as: 64496 - address_family: - - afi: ipv4 - safi: unicast - neighbors: - - neighbor: 203.0.113.10 - activate: yes - maximum_prefix: 250 - advertisement_interval: 120 - - neighbor: 192.0.2.15 - activate: yes - route_reflector_client: True - operation: merge - -- name: remove bgp as 64496 from config - ios_bgp: - config: - bgp_as: 64496 - operation: delete -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always - type: list - sample: - - router bgp 64496 - - bgp router-id 192.0.2.1 - - bgp log-neighbor-changes - - neighbor 203.0.113.5 remote-as 64511 - - neighbor 203.0.113.5 timers 300 360 360 - - neighbor 198.51.100.2 remote-as 64498 - - network 198.51.100.0 route-map RMAP_1 - - network 192.0.2.0 mask 255.255.254.0 - - address-family ipv4 - - redistribute ospf 223 metric 70 - - exit-address-family -""" -from ansible.module_utils._text import to_text -from ansible.module_utils.network.ios.providers.module import NetworkModule -from ansible.module_utils.network.ios.providers.cli.config.bgp.process import REDISTRIBUTE_PROTOCOLS - - -def main(): - """ main entry point for module execution - """ - network_spec = { - 'prefix': dict(required=True), - 'masklen': dict(type='int'), - 'route_map': dict(), - } - - redistribute_spec = { - 'protocol': dict(choices=REDISTRIBUTE_PROTOCOLS, required=True), - 'id': dict(), - 'metric': dict(type='int'), - 'route_map': dict(), - } - - timer_spec = { - 'keepalive': dict(type='int', required=True), - 'holdtime': dict(type='int', required=True), - 'min_neighbor_holdtime': dict(type='int'), - } - - neighbor_spec = { - 'neighbor': dict(required=True), - 'remote_as': dict(type='int', required=True), - 'local_as': dict(type='int'), - 'update_source': dict(), - 'password': dict(no_log=True), - 'enabled': dict(type='bool'), - 'description': dict(), - 'ebgp_multihop': dict(type='int'), - 'timers': dict(type='dict', options=timer_spec), - 'peer_group': dict(), - } - - af_neighbor_spec = { - 'neighbor': dict(required=True), - 'activate': dict(type='bool'), - 'advertisement_interval': dict(type='int'), - 'remove_private_as': dict(type='bool'), - 'next_hop_self': dict(type='bool'), - 'route_reflector_client': dict(type='bool'), - 'route_server_client': dict(type='bool'), - 'maximum_prefix': dict(type='int'), - 'prefix_list_in': dict(), - 'prefix_list_out': dict() - } - - address_family_spec = { - 'afi': dict(choices=['ipv4', 'ipv6'], required=True), - 'safi': dict(choices=['flowspec', 'labeled-unicast', 'multicast', 'unicast'], default='unicast'), - 'auto_summary': dict(type='bool'), - 'synchronization': dict(type='bool'), - 'networks': dict(type='list', elements='dict', options=network_spec), - 'redistribute': dict(type='list', elements='dict', options=redistribute_spec), - 'neighbors': dict(type='list', elements='dict', options=af_neighbor_spec), - } - - config_spec = { - 'bgp_as': dict(type='int', required=True), - 'router_id': dict(), - 'log_neighbor_changes': dict(type='bool'), - 'neighbors': dict(type='list', elements='dict', options=neighbor_spec), - 'address_family': dict(type='list', elements='dict', options=address_family_spec), - 'networks': dict(type='list', elements='dict', options=network_spec) - } - - argument_spec = { - 'config': dict(type='dict', options=config_spec), - 'operation': dict(default='merge', choices=['merge', 'replace', 'override', 'delete']) - } - - module = NetworkModule(argument_spec=argument_spec, - supports_check_mode=True) - - try: - result = module.edit_config(config_filter='| section ^router bgp') - except Exception as exc: - module.fail_json(msg=to_text(exc)) - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_command.py b/lib/ansible/modules/network/ios/ios_command.py deleted file mode 100644 index 59ea254b2d..0000000000 --- a/lib/ansible/modules/network/ios/ios_command.py +++ /dev/null @@ -1,230 +0,0 @@ -#!/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 <http://www.gnu.org/licenses/>. -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_command -version_added: "2.1" -author: "Peter Sprygada (@privateip)" -short_description: Run commands on remote devices running Cisco IOS -description: - - Sends arbitrary commands to an ios node and returns the results - read from the device. This module includes an - argument that will cause the module to wait for a specific condition - before returning or timing out if the condition is not met. - - This module does not support running commands in configuration mode. - Please use M(ios_config) to configure IOS devices. -extends_documentation_fragment: ios -notes: - - Tested against IOS 15.6 -options: - commands: - description: - - List of commands to send to the remote ios device over the - configured provider. The resulting output from the command - is returned. If the I(wait_for) argument is provided, the - module is not returned until the condition is satisfied or - the number of retries has expired. If a command sent to the - device requires answering a prompt, it is possible to pass - a dict containing I(command), I(answer) and I(prompt). - Common answers are 'y' or "\\r" (carriage return, must be - double quotes). See examples. - required: true - wait_for: - description: - - List of conditions to evaluate against the output of the - command. The task will wait for each condition to be true - before moving forward. If the conditional is not true - within the configured number of retries, the task fails. - See examples. - aliases: ['waitfor'] - version_added: "2.2" - match: - description: - - The I(match) argument is used in conjunction with the - I(wait_for) argument to specify the match policy. Valid - values are C(all) or C(any). If the value is set to C(all) - then all conditionals in the wait_for must be satisfied. If - the value is set to C(any) then only one of the values must be - satisfied. - default: all - choices: ['any', 'all'] - version_added: "2.2" - retries: - description: - - Specifies the number of retries a command should by tried - before it is considered failed. The command is run on the - target device every retry and evaluated against the - I(wait_for) conditions. - default: 10 - interval: - description: - - Configures the interval in seconds to wait between retries - of the command. If the command does not pass the specified - conditions, the interval indicates how long to wait before - trying the command again. - default: 1 -""" - -EXAMPLES = r""" -tasks: - - name: run show version on remote devices - ios_command: - commands: show version - - - name: run show version and check to see if output contains IOS - ios_command: - commands: show version - wait_for: result[0] contains IOS - - - name: run multiple commands on remote nodes - ios_command: - commands: - - show version - - show interfaces - - - name: run multiple commands and evaluate the output - ios_command: - commands: - - show version - - show interfaces - wait_for: - - result[0] contains IOS - - result[1] contains Loopback0 - - - name: run commands that require answering a prompt - ios_command: - commands: - - command: 'clear counters GigabitEthernet0/1' - prompt: 'Clear "show interface" counters on this interface \[confirm\]' - answer: 'y' - - command: 'clear counters GigabitEthernet0/2' - prompt: '[confirm]' - answer: "\r" -""" - -RETURN = """ -stdout: - description: The set of responses from the commands - returned: always apart from low level errors (such as action plugin) - type: list - sample: ['...', '...'] -stdout_lines: - description: The value of stdout split into a list - returned: always apart from low level errors (such as action plugin) - type: list - sample: [['...', '...'], ['...'], ['...']] -failed_conditions: - description: The list of conditionals that have failed - returned: failed - type: list - sample: ['...', '...'] -""" -import time - -from ansible.module_utils._text import to_text -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.parsing import Conditional -from ansible.module_utils.network.common.utils import transform_commands, to_lines -from ansible.module_utils.network.ios.ios import run_commands -from ansible.module_utils.network.ios.ios import ios_argument_spec - - -def parse_commands(module, warnings): - commands = transform_commands(module) - - if module.check_mode: - for item in list(commands): - if not item['command'].startswith('show'): - warnings.append( - 'Only show commands are supported when using check mode, not ' - 'executing %s' % item['command'] - ) - commands.remove(item) - - return commands - - -def main(): - """main entry point for module execution - """ - argument_spec = dict( - commands=dict(type='list', required=True), - - wait_for=dict(type='list', aliases=['waitfor']), - match=dict(default='all', choices=['all', 'any']), - - retries=dict(default=10, type='int'), - interval=dict(default=1, type='int') - ) - - argument_spec.update(ios_argument_spec) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - warnings = list() - result = {'changed': False, 'warnings': warnings} - commands = parse_commands(module, warnings) - wait_for = module.params['wait_for'] or list() - - try: - conditionals = [Conditional(c) for c in wait_for] - except AttributeError as exc: - module.fail_json(msg=to_text(exc)) - - retries = module.params['retries'] - interval = module.params['interval'] - match = module.params['match'] - - while retries > 0: - responses = run_commands(module, commands) - - for item in list(conditionals): - if item(responses): - if match == 'any': - conditionals = list() - break - conditionals.remove(item) - - if not conditionals: - break - - time.sleep(interval) - retries -= 1 - - if conditionals: - failed_conditions = [item.raw for item in conditionals] - msg = 'One or more conditional statements have not been satisfied' - module.fail_json(msg=msg, failed_conditions=failed_conditions) - - result.update({ - 'stdout': responses, - 'stdout_lines': list(to_lines(responses)), - }) - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_config.py b/lib/ansible/modules/network/ios/ios_config.py deleted file mode 100644 index b359c9cc78..0000000000 --- a/lib/ansible/modules/network/ios/ios_config.py +++ /dev/null @@ -1,567 +0,0 @@ -#!/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 <http://www.gnu.org/licenses/>. -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_config -version_added: "2.1" -author: "Peter Sprygada (@privateip)" -short_description: Manage Cisco IOS configuration sections -description: - - Cisco IOS configurations use a simple block indent file syntax - for segmenting configuration into sections. This module provides - an implementation for working with IOS configuration sections in - a deterministic way. -extends_documentation_fragment: ios -notes: - - Tested against IOS 15.6 - - Abbreviated commands are NOT idempotent, see - L(Network FAQ,../network/user_guide/faq.html#why-do-the-config-modules-always-return-changed-true-with-abbreviated-commands). -options: - lines: - description: - - The ordered set of commands that should be configured in the - section. The commands must be the exact same commands as found - in the device running-config. Be sure to note the configuration - command syntax as some commands are automatically modified by the - device config parser. - aliases: ['commands'] - parents: - description: - - The ordered set of parents that uniquely identify the section or hierarchy - the commands should be checked against. If the parents argument - is omitted, the commands are checked against the set of top - level or global commands. - src: - description: - - Specifies the source path to the file that contains the configuration - or configuration template to load. The path to the source file can - either be the full path on the Ansible control host or a relative - path from the playbook or role root directory. This argument is mutually - exclusive with I(lines), I(parents). - version_added: "2.2" - before: - description: - - The ordered set of commands to push on to the command stack if - a change needs to be made. This allows the playbook designer - the opportunity to perform configuration commands prior to pushing - any changes without affecting how the set of commands are matched - against the system. - after: - description: - - The ordered set of commands to append to the end of the command - stack if a change needs to be made. Just like with I(before) this - allows the playbook designer to append a set of commands to be - executed after the command set. - match: - description: - - Instructs the module on the way to perform the matching of - the set of commands against the current device config. If - match is set to I(line), commands are matched line by line. If - match is set to I(strict), command lines are matched with respect - to position. If match is set to I(exact), command lines - must be an equal match. Finally, if match is set to I(none), the - module will not attempt to compare the source configuration with - the running configuration on the remote device. - choices: ['line', 'strict', 'exact', 'none'] - default: line - replace: - description: - - Instructs the module on the way to perform the configuration - on the device. If the replace argument is set to I(line) then - the modified lines are pushed to the device in configuration - mode. If the replace argument is set to I(block) then the entire - command block is pushed to the device in configuration mode if any - line is not correct. - default: line - choices: ['line', 'block'] - multiline_delimiter: - description: - - This argument is used when pushing a multiline configuration - element to the IOS device. It specifies the character to use - as the delimiting character. This only applies to the - configuration action. - default: "@" - version_added: "2.3" - backup: - description: - - This argument will cause the module to create a full backup of - the current C(running-config) from the remote device before any - changes are made. If the C(backup_options) value is not given, - the backup file is written to the C(backup) folder in the playbook - root directory or role root directory, if playbook is part of an - ansible role. If the directory does not exist, it is created. - type: bool - default: 'no' - version_added: "2.2" - running_config: - description: - - The module, by default, will connect to the remote device and - retrieve the current running-config to use as a base for comparing - against the contents of source. There are times when it is not - desirable to have the task get the current running-config for - every task in a playbook. The I(running_config) argument allows the - implementer to pass in the configuration to use as the base - config for comparison. - aliases: ['config'] - version_added: "2.4" - defaults: - description: - - This argument specifies whether or not to collect all defaults - when getting the remote device running config. When enabled, - the module will get the current config by issuing the command - C(show running-config all). - type: bool - default: 'no' - version_added: "2.2" - save_when: - description: - - When changes are made to the device running-configuration, the - changes are not copied to non-volatile storage by default. Using - this argument will change that before. If the argument is set to - I(always), then the running-config will always be copied to the - startup-config and the I(modified) flag will always be set to - True. If the argument is set to I(modified), then the running-config - will only be copied to the startup-config if it has changed since - the last save to startup-config. If the argument is set to - I(never), the running-config will never be copied to the - startup-config. If the argument is set to I(changed), then the running-config - will only be copied to the startup-config if the task has made a change. - I(changed) was added in Ansible 2.5. - default: never - choices: ['always', 'never', 'modified', 'changed'] - version_added: "2.4" - diff_against: - description: - - When using the C(ansible-playbook --diff) command line argument - the module can generate diffs against different sources. - - When this option is configure as I(startup), the module will return - the diff of the running-config against the startup-config. - - When this option is configured as I(intended), the module will - return the diff of the running-config against the configuration - provided in the C(intended_config) argument. - - When this option is configured as I(running), the module will - return the before and after diff of the running-config with respect - to any changes made to the device configuration. - choices: ['running', 'startup', 'intended'] - version_added: "2.4" - diff_ignore_lines: - description: - - Use this argument to specify one or more lines that should be - ignored during the diff. This is used for lines in the configuration - that are automatically updated by the system. This argument takes - a list of regular expressions or exact line matches. - version_added: "2.4" - intended_config: - description: - - The C(intended_config) provides the master configuration that - the node should conform to and is used to check the final - running-config against. This argument will not modify any settings - on the remote device and is strictly used to check the compliance - of the current device's configuration against. When specifying this - argument, the task should also modify the C(diff_against) value and - set it to I(intended). - version_added: "2.4" - backup_options: - description: - - This is a dict object containing configurable options related to backup file path. - The value of this option is read only when C(backup) is set to I(yes), if C(backup) is set - to I(no) this option will be silently ignored. - suboptions: - filename: - description: - - The filename to be used to store the backup configuration. If the filename - is not given it will be generated based on the hostname, current time and date - in format defined by <hostname>_config.<current-date>@<current-time> - dir_path: - description: - - This option provides the path ending with directory name in which the backup - configuration file will be stored. If the directory does not exist it will be first - created and the filename is either the value of C(filename) or default filename - as described in C(filename) options description. If the path value is not given - in that case a I(backup) directory will be created in the current working directory - and backup configuration will be copied in C(filename) within I(backup) directory. - type: path - type: dict - version_added: "2.8" -""" - -EXAMPLES = """ -- name: configure top level configuration - ios_config: - lines: hostname {{ inventory_hostname }} - -- name: configure interface settings - ios_config: - lines: - - description test interface - - ip address 172.31.1.1 255.255.255.0 - parents: interface Ethernet1 - -- name: configure ip helpers on multiple interfaces - ios_config: - lines: - - ip helper-address 172.26.1.10 - - ip helper-address 172.26.3.8 - parents: "{{ item }}" - with_items: - - interface Ethernet1 - - interface Ethernet2 - - interface GigabitEthernet1 - -- name: configure policer in Scavenger class - ios_config: - lines: - - conform-action transmit - - exceed-action drop - parents: - - policy-map Foo - - class Scavenger - - police cir 64000 - -- name: load new acl into device - ios_config: - lines: - - 10 permit ip host 192.0.2.1 any log - - 20 permit ip host 192.0.2.2 any log - - 30 permit ip host 192.0.2.3 any log - - 40 permit ip host 192.0.2.4 any log - - 50 permit ip host 192.0.2.5 any log - parents: ip access-list extended test - before: no ip access-list extended test - match: exact - -- name: check the running-config against master config - ios_config: - diff_against: intended - intended_config: "{{ lookup('file', 'master.cfg') }}" - -- name: check the startup-config against the running-config - ios_config: - diff_against: startup - diff_ignore_lines: - - ntp clock .* - -- name: save running to startup when modified - ios_config: - save_when: modified - -- name: for idempotency, use full-form commands - ios_config: - lines: - # - shut - - shutdown - # parents: int gig1/0/11 - parents: interface GigabitEthernet1/0/11 - -# Set boot image based on comparison to a group_var (version) and the version -# that is returned from the `ios_facts` module -- name: SETTING BOOT IMAGE - ios_config: - lines: - - no boot system - - boot system flash bootflash:{{new_image}} - host: "{{ inventory_hostname }}" - when: ansible_net_version != version - -- name: render a Jinja2 template onto an IOS device - ios_config: - backup: yes - src: ios_template.j2 - -- name: configurable backup path - ios_config: - src: ios_template.j2 - backup: yes - backup_options: - filename: backup.cfg - dir_path: /home/user -""" - -RETURN = """ -updates: - description: The set of commands that will be pushed to the remote device - returned: always - type: list - sample: ['hostname foo', 'router ospf 1', 'router-id 192.0.2.1'] -commands: - description: The set of commands that will be pushed to the remote device - returned: always - type: list - sample: ['hostname foo', 'router ospf 1', 'router-id 192.0.2.1'] -backup_path: - description: The full path to the backup file - returned: when backup is yes - type: str - sample: /playbooks/ansible/backup/ios_config.2016-07-16@22:28:34 -filename: - description: The name of the backup file - returned: when backup is yes and filename is not specified in backup options - type: str - sample: ios_config.2016-07-16@22:28:34 -shortname: - description: The full path to the backup file excluding the timestamp - returned: when backup is yes and filename is not specified in backup options - type: str - sample: /playbooks/ansible/backup/ios_config -date: - description: The date extracted from the backup file name - returned: when backup is yes - type: str - sample: "2016-07-16" -time: - description: The time extracted from the backup file name - returned: when backup is yes - type: str - sample: "22:28:34" -""" -import json - -from ansible.module_utils._text import to_text -from ansible.module_utils.connection import ConnectionError -from ansible.module_utils.network.ios.ios import run_commands, get_config -from ansible.module_utils.network.ios.ios import get_defaults_flag, get_connection -from ansible.module_utils.network.ios.ios import ios_argument_spec -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.config import NetworkConfig, dumps - - -def check_args(module, warnings): - if module.params['multiline_delimiter']: - if len(module.params['multiline_delimiter']) != 1: - module.fail_json(msg='multiline_delimiter value can only be a ' - 'single character') - - -def edit_config_or_macro(connection, commands): - # only catch the macro configuration command, - # not negated 'no' variation. - if commands[0].startswith("macro name"): - connection.edit_macro(candidate=commands) - else: - connection.edit_config(candidate=commands) - - -def get_candidate_config(module): - candidate = '' - if module.params['src']: - candidate = module.params['src'] - - elif module.params['lines']: - candidate_obj = NetworkConfig(indent=1) - parents = module.params['parents'] or list() - candidate_obj.add(module.params['lines'], parents=parents) - candidate = dumps(candidate_obj, 'raw') - - return candidate - - -def get_running_config(module, current_config=None, flags=None): - running = module.params['running_config'] - if not running: - if not module.params['defaults'] and current_config: - running = current_config - else: - running = get_config(module, flags=flags) - - return running - - -def save_config(module, result): - result['changed'] = True - if not module.check_mode: - run_commands(module, 'copy running-config startup-config\r') - else: - module.warn('Skipping command `copy running-config startup-config` ' - 'due to check_mode. Configuration not copied to ' - 'non-volatile storage') - - -def main(): - """ main entry point for module execution - """ - backup_spec = dict( - filename=dict(), - dir_path=dict(type='path') - ) - argument_spec = dict( - src=dict(type='path'), - - lines=dict(aliases=['commands'], type='list'), - parents=dict(type='list'), - - before=dict(type='list'), - after=dict(type='list'), - - match=dict(default='line', choices=['line', 'strict', 'exact', 'none']), - replace=dict(default='line', choices=['line', 'block']), - multiline_delimiter=dict(default='@'), - - running_config=dict(aliases=['config']), - intended_config=dict(), - - defaults=dict(type='bool', default=False), - backup=dict(type='bool', default=False), - backup_options=dict(type='dict', options=backup_spec), - save_when=dict(choices=['always', 'never', 'modified', 'changed'], default='never'), - - diff_against=dict(choices=['startup', 'intended', 'running']), - diff_ignore_lines=dict(type='list'), - ) - - argument_spec.update(ios_argument_spec) - - mutually_exclusive = [('lines', 'src'), - ('parents', 'src')] - - required_if = [('match', 'strict', ['lines']), - ('match', 'exact', ['lines']), - ('replace', 'block', ['lines']), - ('diff_against', 'intended', ['intended_config'])] - - module = AnsibleModule(argument_spec=argument_spec, - mutually_exclusive=mutually_exclusive, - required_if=required_if, - supports_check_mode=True) - - result = {'changed': False} - - warnings = list() - check_args(module, warnings) - result['warnings'] = warnings - - diff_ignore_lines = module.params['diff_ignore_lines'] - config = None - contents = None - flags = get_defaults_flag(module) if module.params['defaults'] else [] - connection = get_connection(module) - - if module.params['backup'] or (module._diff and module.params['diff_against'] == 'running'): - contents = get_config(module, flags=flags) - config = NetworkConfig(indent=1, contents=contents) - if module.params['backup']: - result['__backup__'] = contents - - if any((module.params['lines'], module.params['src'])): - match = module.params['match'] - replace = module.params['replace'] - path = module.params['parents'] - - candidate = get_candidate_config(module) - running = get_running_config(module, contents, flags=flags) - try: - response = connection.get_diff(candidate=candidate, running=running, diff_match=match, diff_ignore_lines=diff_ignore_lines, path=path, - diff_replace=replace) - except ConnectionError as exc: - module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) - - config_diff = response['config_diff'] - banner_diff = response['banner_diff'] - - if config_diff or banner_diff: - commands = config_diff.split('\n') - - if module.params['before']: - commands[:0] = module.params['before'] - - if module.params['after']: - commands.extend(module.params['after']) - - result['commands'] = commands - result['updates'] = commands - result['banners'] = banner_diff - - # send the configuration commands to the device and merge - # them with the current running config - if not module.check_mode: - if commands: - edit_config_or_macro(connection, commands) - if banner_diff: - connection.edit_banner(candidate=json.dumps(banner_diff), multiline_delimiter=module.params['multiline_delimiter']) - - result['changed'] = True - - running_config = module.params['running_config'] - startup_config = None - - if module.params['save_when'] == 'always': - save_config(module, result) - elif module.params['save_when'] == 'modified': - output = run_commands(module, ['show running-config', 'show startup-config']) - - running_config = NetworkConfig(indent=1, contents=output[0], ignore_lines=diff_ignore_lines) - startup_config = NetworkConfig(indent=1, contents=output[1], ignore_lines=diff_ignore_lines) - - if running_config.sha1 != startup_config.sha1: - save_config(module, result) - elif module.params['save_when'] == 'changed' and result['changed']: - save_config(module, result) - - if module._diff: - if not running_config: - output = run_commands(module, 'show running-config') - contents = output[0] - else: - contents = running_config - - # recreate the object in order to process diff_ignore_lines - running_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines) - - if module.params['diff_against'] == 'running': - if module.check_mode: - module.warn("unable to perform diff against running-config due to check mode") - contents = None - else: - contents = config.config_text - - elif module.params['diff_against'] == 'startup': - if not startup_config: - output = run_commands(module, 'show startup-config') - contents = output[0] - else: - contents = startup_config.config_text - - elif module.params['diff_against'] == 'intended': - contents = module.params['intended_config'] - - if contents is not None: - base_config = NetworkConfig(indent=1, contents=contents, ignore_lines=diff_ignore_lines) - - if running_config.sha1 != base_config.sha1: - if module.params['diff_against'] == 'intended': - before = running_config - after = base_config - elif module.params['diff_against'] in ('startup', 'running'): - before = base_config - after = running_config - - result.update({ - 'changed': True, - 'diff': {'before': str(before), 'after': str(after)} - }) - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_facts.py b/lib/ansible/modules/network/ios/ios_facts.py deleted file mode 100644 index e2f147e669..0000000000 --- a/lib/ansible/modules/network/ios/ios_facts.py +++ /dev/null @@ -1,239 +0,0 @@ -#!/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 <http://www.gnu.org/licenses/>. -# -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_facts -version_added: "2.2" -author: - - "Peter Sprygada (@privateip)" - - "Sumit Jaiswal (@justjais)" -short_description: Collect facts from remote devices running Cisco IOS -description: - - Collects a base set of device facts from a remote device that - is running IOS. This module prepends all of the - base network fact keys with C(ansible_net_<fact>). The facts - module will always collect a base set of facts from the device - and can enable or disable collection of additional facts. -extends_documentation_fragment: ios -notes: - - Tested against IOS 15.6 -options: - gather_subset: - description: - - When supplied, this argument restricts the facts collected - to a given subset. - - Possible values for this argument include - C(all), C(min), C(hardware), C(config), and C(interfaces). - - Specify a list of values to include a larger subset. - - Use a value with an initial C(!) to collect all facts except that subset. - required: false - default: '!config' - gather_network_resources: - description: - - When supplied, this argument will restrict the facts collected - to a given subset. Possible values for this argument include - all and the resources like interfaces, vlans etc. - Can specify a list of values to include a larger subset. - Values can also be used with an initial C(M(!)) to specify that - a specific subset should not be collected. - Valid subsets are 'all', 'interfaces', 'l2_interfaces', 'vlans', - 'lag_interfaces', 'lacp', 'lacp_interfaces', 'lldp_global', - 'lldp_interfaces', 'l3_interfaces', 'acl_interfaces', 'static_routes', 'acls'. - version_added: "2.9" -""" - -EXAMPLES = """ -- name: Gather all legacy facts - ios_facts: - gather_subset: all - -- name: Gather only the config and default facts - ios_facts: - gather_subset: - - config - -- name: Do not gather hardware facts - ios_facts: - gather_subset: - - "!hardware" - -- name: Gather legacy and resource facts - ios_facts: - gather_subset: all - gather_network_resources: all - -- name: Gather only the interfaces resource facts and no legacy facts - ios_facts: - gather_subset: - - '!all' - - '!min' - gather_network_resources: - - interfaces - -- name: Gather interfaces resource and minimal legacy facts - ios_facts: - gather_subset: min - gather_network_resources: interfaces - -- name: Gather L2 interfaces resource and minimal legacy facts - ios_facts: - gather_subset: min - gather_network_resources: l2_interfaces - -- name: Gather L3 interfaces resource and minimal legacy facts - ios_facts: - gather_subset: min - gather_network_resources: l3_interfaces - -""" - -RETURN = """ -ansible_net_gather_subset: - description: The list of fact subsets collected from the device - returned: always - type: list - -ansible_net_gather_network_resources: - description: The list of fact for network resource subsets collected from the device - returned: when the resource is configured - type: list - -# default -ansible_net_model: - description: The model name returned from the device - returned: always - type: str -ansible_net_serialnum: - description: The serial number of the remote device - returned: always - type: str -ansible_net_version: - description: The operating system version running on the remote device - returned: always - type: str -ansible_net_iostype: - description: The operating system type (IOS or IOS-XE) running on the remote device - returned: always - type: str -ansible_net_hostname: - description: The configured hostname of the device - returned: always - type: str -ansible_net_image: - description: The image file the device is running - returned: always - type: str -ansible_net_stacked_models: - description: The model names of each device in the stack - returned: when multiple devices are configured in a stack - type: list -ansible_net_stacked_serialnums: - description: The serial numbers of each device in the stack - returned: when multiple devices are configured in a stack - type: list -ansible_net_api: - description: The name of the transport - returned: always - type: str -ansible_net_python_version: - description: The Python version Ansible controller is using - returned: always - type: str - -# hardware -ansible_net_filesystems: - description: All file system names available on the device - returned: when hardware is configured - type: list -ansible_net_filesystems_info: - description: A hash of all file systems containing info about each file system (e.g. free and total space) - returned: when hardware is configured - type: dict -ansible_net_memfree_mb: - description: The available free memory on the remote device in Mb - returned: when hardware is configured - type: int -ansible_net_memtotal_mb: - description: The total memory on the remote device in Mb - returned: when hardware is configured - type: int - -# config -ansible_net_config: - description: The current active config from the device - returned: when config is configured - type: str - -# interfaces -ansible_net_all_ipv4_addresses: - description: All IPv4 addresses configured on the device - returned: when interfaces is configured - type: list -ansible_net_all_ipv6_addresses: - description: All IPv6 addresses configured on the device - returned: when interfaces is configured - type: list -ansible_net_interfaces: - description: A hash of all interfaces running on the system - returned: when interfaces is configured - type: dict -ansible_net_neighbors: - description: - - The list of CDP and LLDP neighbors from the remote device. If both, - CDP and LLDP neighbor data is present on one port, CDP is preferred. - returned: when interfaces is configured - type: dict -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.facts.facts import FactsArgs -from ansible.module_utils.network.ios.facts.facts import Facts -from ansible.module_utils.network.ios.ios import ios_argument_spec - - -def main(): - """ - Main entry point for module execution - - :returns: ansible_facts - """ - argument_spec = FactsArgs.argument_spec - argument_spec.update(ios_argument_spec) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - warnings = [] - if module.params["gather_subset"] == "!config": - warnings.append('default value for `gather_subset` will be changed to `min` from `!config` v2.11 onwards') - - result = Facts(module).get_facts() - - ansible_facts, additional_warnings = result - warnings.extend(additional_warnings) - - module.exit_json(ansible_facts=ansible_facts, warnings=warnings) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_interfaces.py b/lib/ansible/modules/network/ios/ios_interfaces.py deleted file mode 100644 index 4988f029be..0000000000 --- a/lib/ansible/modules/network/ios/ios_interfaces.py +++ /dev/null @@ -1,405 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The module file for ios_interfaces -""" - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_interfaces -version_added: 2.9 -short_description: Manages interface attributes of Cisco IOS network devices -description: This module manages the interface attributes of Cisco IOS network devices. -author: Sumit Jaiswal (@justjais) -notes: -- Tested against Cisco IOSv Version 15.2 on VIRL -- This module works with connection C(network_cli). - See L(IOS Platform Options,../network/user_guide/platform_ios.html). -options: - config: - description: A dictionary of interface options - type: list - suboptions: - name: - description: - - Full name of interface, e.g. GigabitEthernet0/2, loopback999. - type: str - required: True - description: - description: - - Interface description. - type: str - enabled: - description: - - Administrative state of the interface. - - Set the value to C(true) to administratively enable the interface or C(false) to disable it. - type: bool - default: True - speed: - description: - - Interface link speed. Applicable for Ethernet interfaces only. - type: str - mtu: - description: - - MTU for a specific interface. Applicable for Ethernet interfaces only. - - Refer to vendor documentation for valid values. - type: int - duplex: - description: - - Interface link status. Applicable for Ethernet interfaces only, either in half duplex, - full duplex or in automatic state which negotiates the duplex automatically. - type: str - choices: ['full', 'half', 'auto'] - state: - choices: - - merged - - replaced - - overridden - - deleted - default: merged - description: - - The state of the configuration after module completion - type: str -""" - -EXAMPLES = """ ---- - -# Using merged - -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description This is test -# no ip address -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# no ip address -# duplex auto -# speed auto - -- name: Merge provided configuration with device configuration - ios_interfaces: - config: - - name: GigabitEthernet0/2 - description: 'Configured and Merged by Ansible Network' - enabled: True - - name: GigabitEthernet0/3 - description: 'Configured and Merged by Ansible Network' - mtu: 2800 - enabled: False - speed: 100 - duplex: full - state: merged - -# After state: -# ------------ -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description Configured and Merged by Ansible Network -# no ip address -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# description Configured and Merged by Ansible Network -# mtu 2800 -# no ip address -# shutdown -# duplex full -# speed 100 - -# Using replaced - -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description Configured by Ansible Network -# no ip address -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# mtu 2000 -# no ip address -# shutdown -# duplex full -# speed 100 - -- name: Replaces device configuration of listed interfaces with provided configuration - ios_interfaces: - config: - - name: GigabitEthernet0/3 - description: 'Configured and Replaced by Ansible Network' - enabled: False - duplex: auto - mtu: 2500 - speed: 1000 - state: replaced - -# After state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description Configured by Ansible Network -# no ip address -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# description Configured and Replaced by Ansible Network -# mtu 2500 -# no ip address -# shutdown -# duplex full -# speed 1000 - -# Using overridden - -# Before state: -# ------------- -# -# vios#show running-config | section ^interface# -# interface GigabitEthernet0/1 -# description Configured by Ansible -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description This is test -# no ip address -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# description Configured by Ansible -# mtu 2800 -# no ip address -# shutdown -# duplex full -# speed 100 - -- name: Override device configuration of all interfaces with provided configuration - ios_interfaces: - config: - - name: GigabitEthernet0/2 - description: 'Configured and Overridden by Ansible Network' - speed: 1000 - - name: GigabitEthernet0/3 - description: 'Configured and Overridden by Ansible Network' - enabled: False - duplex: full - mtu: 2000 - state: overridden - -# After state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description Configured and Overridden by Ansible Network -# no ip address -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# description Configured and Overridden by Ansible Network -# mtu 2000 -# no ip address -# shutdown -# duplex full -# speed 100 - -# Using Deleted - -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description Configured by Ansible Network -# no ip address -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# mtu 2500 -# no ip address -# shutdown -# duplex full -# speed 1000 - -- name: "Delete module attributes of given interfaces (Note: This won't delete the interface itself)" - ios_interfaces: - config: - - name: GigabitEthernet0/2 - state: deleted - -# After state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# mtu 2500 -# no ip address -# shutdown -# duplex full -# speed 1000 - -# Using Deleted without any config passed -#"(NOTE: This will delete all of configured resource module attributes from each configured interface)" - -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description Configured by Ansible Network -# no ip address -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# mtu 2500 -# no ip address -# shutdown -# duplex full -# speed 1000 - -- name: "Delete module attributes of all interfaces (Note: This won't delete the interface itself)" - ios_interfaces: - state: deleted - -# After state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/3 -# no ip address -# duplex auto -# speed auto - -""" - -RETURN = """ -before: - description: The configuration as structured data prior to module invocation. - returned: always - type: list - sample: The configuration returned will always be in the same format of the parameters above. -after: - description: The configuration as structured data after module completion. - returned: when changed - type: list - sample: The configuration returned will always be in the same format of the parameters above. -commands: - description: The set of commands pushed to the remote device - returned: always - type: list - sample: ['interface GigabitEthernet 0/1', 'description This is test', 'speed 100'] -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.interfaces.interfaces import InterfacesArgs -from ansible.module_utils.network.ios.config.interfaces.interfaces import Interfaces - - -def main(): - """ - Main entry point for module execution - - :returns: the result form module invocation - """ - required_if = [('state', 'merged', ('config',)), - ('state', 'replaced', ('config',)), - ('state', 'overridden', ('config',))] - - module = AnsibleModule(argument_spec=InterfacesArgs.argument_spec, - required_if=required_if, - supports_check_mode=True) - - result = Interfaces(module).execute_module() - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_l2_interfaces.py b/lib/ansible/modules/network/ios/ios_l2_interfaces.py deleted file mode 100644 index 19eadb8426..0000000000 --- a/lib/ansible/modules/network/ios/ios_l2_interfaces.py +++ /dev/null @@ -1,390 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The module file for ios_l2_interfaces -""" - - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - -DOCUMENTATION = """ ---- -module: ios_l2_interfaces -version_added: 2.9 -short_description: Manage Layer-2 interface on Cisco IOS devices. -description: This module provides declarative management of Layer-2 interface on Cisco IOS devices. -author: Sumit Jaiswal (@justjais) -notes: - - Tested against Cisco IOSv Version 15.2 on VIRL - - This module works with connection C(network_cli). - See L(IOS Platform Options,../network/user_guide/platform_ios.html). -options: - config: - description: A dictionary of Layer-2 interface options - type: list - elements: dict - suboptions: - name: - description: - - Full name of the interface excluding any logical unit number, i.e. GigabitEthernet0/1. - type: str - required: True - access: - description: - - Switchport mode access command to configure the interface as a layer 2 access. - type: dict - suboptions: - vlan: - description: - - Configure given VLAN in access port. It's used as the access VLAN ID. - type: int - voice: - description: - - Switchport mode voice command to configure the interface with a voice vlan. - type: dict - suboptions: - vlan: - description: - - Configure given voice VLAN on access port. It's used as the voice VLAN ID. - type: int - trunk: - description: - - Switchport mode trunk command to configure the interface as a Layer 2 trunk. - Note The encapsulation is always set to dot1q. - type: dict - suboptions: - allowed_vlans: - description: - - List of allowed VLANs in a given trunk port. These are the only VLANs that will be - configured on the trunk. - type: list - native_vlan: - description: - - Native VLAN to be configured in trunk port. It's used as the trunk native VLAN ID. - type: int - encapsulation: - description: - - Trunking encapsulation when interface is in trunking mode. - choices: ['dot1q','isl','negotiate'] - type: str - pruning_vlans: - description: - - Pruning VLAN to be configured in trunk port. It's used as the trunk pruning VLAN ID. - type: list - mode: - description: - - Mode in which interface needs to be configured. - - An interface whose trunk encapsulation is "Auto" can not be configured to "trunk" mode. - version_added: '2.10' - type: str - choices: ['access', 'trunk'] - state: - choices: - - merged - - replaced - - overridden - - deleted - default: merged - description: - - The state of the configuration after module completion - type: str -""" - -EXAMPLES = """ ---- - -# Using merged - -# Before state: -# ------------- -# -# viosl2#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# negotiation auto -# interface GigabitEthernet0/2 -# description This is test -# switchport access vlan 20 -# media-type rj45 -# negotiation auto - -- name: Merge provided configuration with device configuration - ios_l2_interfaces: - config: - - name: GigabitEthernet0/1 - mode: access - access: - vlan: 10 - voice: - vlan: 40 - - name: GigabitEthernet0/2 - mode: trunk - trunk: - allowed_vlans: 10-20,40 - native_vlan: 20 - pruning_vlans: 10,20 - encapsulation: dot1q - state: merged - -# After state: -# ------------ -# -# viosl2#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# switchport access vlan 10 -# switchport access vlan 40 -# switchport mode access -# negotiation auto -# interface GigabitEthernet0/2 -# description This is test -# switchport trunk allowed vlan 10-20,40 -# switchport trunk encapsulation dot1q -# switchport trunk native vlan 20 -# switchport trunk pruning vlan 10,20 -# switchport mode trunk -# media-type rj45 -# negotiation auto - -# Using replaced - -# Before state: -# ------------- -# -# viosl2#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# switchport access vlan 20 -# negotiation auto -# interface GigabitEthernet0/2 -# description This is test -# switchport access vlan 20 -# media-type rj45 -# negotiation auto - -- name: Replaces device configuration of listed l2 interfaces with provided configuration - ios_l2_interfaces: - config: - - name: GigabitEthernet0/2 - trunk: - - allowed_vlans: 20-25,40 - native_vlan: 20 - pruning_vlans: 10 - encapsulation: isl - state: replaced - -# After state: -# ------------- -# -# viosl2#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# switchport access vlan 20 -# negotiation auto -# interface GigabitEthernet0/2 -# description This is test -# switchport trunk allowed vlan 20-25,40 -# switchport trunk encapsulation isl -# switchport trunk native vlan 20 -# switchport trunk pruning vlan 10 -# media-type rj45 -# negotiation auto - -# Using overridden - -# Before state: -# ------------- -# -# viosl2#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# switchport trunk encapsulation dot1q -# switchport trunk native vlan 20 -# negotiation auto -# interface GigabitEthernet0/2 -# description This is test -# switchport access vlan 20 -# switchport trunk encapsulation dot1q -# switchport trunk native vlan 20 -# media-type rj45 -# negotiation auto - -- name: Override device configuration of all l2 interfaces with provided configuration - ios_l2_interfaces: - config: - - name: GigabitEthernet0/2 - access: - vlan: 20 - voice: - vlan: 40 - state: overridden - -# After state: -# ------------- -# -# viosl2#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# negotiation auto -# interface GigabitEthernet0/2 -# description This is test -# switchport access vlan 20 -# switchport voice vlan 40 -# media-type rj45 -# negotiation auto - -# Using Deleted - -# Before state: -# ------------- -# -# viosl2#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# switchport access vlan 20 -# negotiation auto -# interface GigabitEthernet0/2 -# description This is test -# switchport access vlan 20 -# switchport trunk allowed vlan 20-40,60,80 -# switchport trunk encapsulation dot1q -# switchport trunk native vlan 10 -# switchport trunk pruning vlan 10 -# media-type rj45 -# negotiation auto - -- name: Delete IOS L2 interfaces as in given arguments - ios_l2_interfaces: - config: - - name: GigabitEthernet0/1 - state: deleted - -# After state: -# ------------- -# -# viosl2#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# negotiation auto -# interface GigabitEthernet0/2 -# description This is test -# switchport access vlan 20 -# switchport trunk allowed vlan 20-40,60,80 -# switchport trunk encapsulation dot1q -# switchport trunk native vlan 10 -# switchport trunk pruning vlan 10 -# media-type rj45 -# negotiation auto - - -# Using Deleted without any config passed -#"(NOTE: This will delete all of configured resource module attributes from each configured interface)" - -# Before state: -# ------------- -# -# viosl2#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# switchport access vlan 20 -# negotiation auto -# interface GigabitEthernet0/2 -# description This is test -# switchport access vlan 20 -# switchport trunk allowed vlan 20-40,60,80 -# switchport trunk encapsulation dot1q -# switchport trunk native vlan 10 -# switchport trunk pruning vlan 10 -# media-type rj45 -# negotiation auto - -- name: Delete IOS L2 interfaces as in given arguments - ios_l2_interfaces: - state: deleted - -# After state: -# ------------- -# -# viosl2#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# negotiation auto -# interface GigabitEthernet0/2 -# description This is test -# media-type rj45 -# negotiation auto - -""" - -RETURN = """ -before: - description: The configuration as structured data prior to module invocation. - returned: always - type: list - sample: The configuration returned will always be in the same format of the parameters above. -after: - description: The configuration as structured data after module completion. - returned: when changed - type: list - sample: The configuration returned will always be in the same format of the parameters above. -commands: - description: The set of commands pushed to the remote device - returned: always - type: list - sample: ['interface GigabitEthernet0/1', 'switchport access vlan 20'] -""" - - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.l2_interfaces.l2_interfaces import L2_InterfacesArgs -from ansible.module_utils.network.ios.config.l2_interfaces.l2_interfaces import L2_Interfaces - - -def main(): - """ - Main entry point for module execution - - :returns: the result form module invocation - """ - required_if = [('state', 'merged', ('config',)), - ('state', 'replaced', ('config',)), - ('state', 'overridden', ('config',))] - - module = AnsibleModule(argument_spec=L2_InterfacesArgs.argument_spec, - required_if=required_if, - supports_check_mode=True) - - result = L2_Interfaces(module).execute_module() - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_l3_interfaces.py b/lib/ansible/modules/network/ios/ios_l3_interfaces.py deleted file mode 100644 index 9fd054ef75..0000000000 --- a/lib/ansible/modules/network/ios/ios_l3_interfaces.py +++ /dev/null @@ -1,442 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat Inc. -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################## -# WARNING -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -# -############################################## - -""" -The module file for ios_l3_interfaces -""" - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_l3_interfaces -version_added: 2.9 -short_description: Manage Layer-3 interface on Cisco IOS devices. -description: -- This module provides declarative management of Layer-3 interface - on Cisco IOS devices. -author: Sumit Jaiswal (@justjais) -options: - config: - description: A dictionary of Layer-3 interface options - type: list - elements: dict - suboptions: - name: - description: - - Full name of the interface excluding any logical unit number, - i.e. GigabitEthernet0/1. - type: str - required: True - ipv4: - description: - - IPv4 address to be set for the Layer-3 interface mentioned in - I(name) option. The address format is <ipv4 address>/<mask>, - the mask is number in range 0-32 eg. 192.168.0.1/24. - type: list - elements: dict - suboptions: - address: - description: - - Configures the IPv4 address for Interface. - type: str - secondary: - description: - - Configures the IP address as a secondary address. - type: bool - dhcp_client: - description: - - Configures and specifies client-id to use over DHCP ip. - Note, This option shall work only when dhcp is configured - as IP. - - GigabitEthernet interface number - type: int - dhcp_hostname: - description: - - Configures and specifies value for hostname option over - DHCP ip. Note, This option shall work only when dhcp is - configured as IP. - type: str - ipv6: - description: - - IPv6 address to be set for the Layer-3 interface mentioned in - I(name) option. - - The address format is <ipv6 address>/<mask>, the mask is number - in range 0-128 eg. fd5d:12c9:2201:1::1/64 - type: list - elements: dict - suboptions: - address: - description: - - Configures the IPv6 address for Interface. - type: str - state: - choices: - - merged - - replaced - - overridden - - deleted - default: merged - description: - - The state of the configuration after module completion - type: str -""" - -EXAMPLES = """ ---- -# Using merged -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# ip address 10.1.1.1 255.255.255.0 -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description This is test -# no ip address -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# no ip address -# interface GigabitEthernet0/3.100 -# encapsulation dot1Q 20 - -- name: Merge provided configuration with device configuration - ios_l3_interfaces: - config: - - name: GigabitEthernet0/1 - ipv4: - - address: 192.168.0.1/24 - secondary: True - - name: GigabitEthernet0/2 - ipv4: - - address: 192.168.0.2/24 - - name: GigabitEthernet0/3 - ipv6: - - address: fd5d:12c9:2201:1::1/64 - - name: GigabitEthernet0/3.100 - ipv4: - - address: 192.168.0.3/24 - state: merged - -# After state: -# ------------ -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# ip address 10.1.1.1 255.255.255.0 -# ip address 192.168.0.1 255.255.255.0 secondary -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description This is test -# ip address 192.168.0.2 255.255.255.0 -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# ipv6 address FD5D:12C9:2201:1::1/64 -# interface GigabitEthernet0/3.100 -# encapsulation dot1Q 20 -# ip address 192.168.0.3 255.255.255.0 - -# Using replaced -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# ip address 10.1.1.1 255.255.255.0 -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description This is test -# no ip address -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# ip address 192.168.2.0 255.255.255.0 -# interface GigabitEthernet0/3.100 -# encapsulation dot1Q 20 -# ip address 192.168.0.2 255.255.255.0 - -- name: Replaces device configuration of listed interfaces with provided configuration - ios_l3_interfaces: - config: - - name: GigabitEthernet0/2 - ipv4: - - address: 192.168.2.0/24 - - name: GigabitEthernet0/3 - ipv4: - - address: dhcp - dhcp_client: 2 - dhcp_hostname: test.com - - name: GigabitEthernet0/3.100 - ipv4: - - address: 192.168.0.3/24 - secondary: True - state: replaced - -# After state: -# ------------ -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# ip address 10.1.1.1 255.255.255.0 -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description This is test -# ip address 192.168.2.1 255.255.255.0 -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# ip address dhcp client-id GigabitEthernet0/2 hostname test.com -# interface GigabitEthernet0/3.100 -# encapsulation dot1Q 20 -# ip address 192.168.0.2 255.255.255.0 -# ip address 192.168.0.3 255.255.255.0 secondary - -# Using overridden -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# ip address 10.1.1.1 255.255.255.0 -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description This is test -# ip address 192.168.2.1 255.255.255.0 -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# ipv6 address FD5D:12C9:2201:1::1/64 -# interface GigabitEthernet0/3.100 -# encapsulation dot1Q 20 -# ip address 192.168.0.2 255.255.255.0 - -- name: Override device configuration of all interfaces with provided configuration - ios_l3_interfaces: - config: - - name: GigabitEthernet0/2 - ipv4: - - address: 192.168.0.1/24 - - name: GigabitEthernet0/3.100 - ipv6: - - address: autoconfig - state: overridden - -# After state: -# ------------ -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# description Configured by Ansible -# no ip address -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description This is test -# ip address 192.168.0.1 255.255.255.0 -# duplex auto -# speed 1000 -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# interface GigabitEthernet0/3.100 -# encapsulation dot1Q 20 -# ipv6 address autoconfig - -# Using Deleted -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# ip address 192.0.2.10 255.255.255.0 -# shutdown -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description Configured by Ansible Network -# ip address 192.168.1.0 255.255.255.0 -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# ip address 192.168.0.1 255.255.255.0 -# shutdown -# duplex full -# speed 10 -# ipv6 address FD5D:12C9:2201:1::1/64 -# interface GigabitEthernet0/3.100 -# encapsulation dot1Q 20 -# ip address 192.168.0.2 255.255.255.0 - -- name: "Delete attributes of given interfaces (NOTE: This won't delete the interface itself)" - ios_l3_interfaces: - config: - - name: GigabitEthernet0/2 - - name: GigabitEthernet0/3.100 - state: deleted - -# After state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# no ip address -# shutdown -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description Configured by Ansible Network -# no ip address -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# ip address 192.168.0.1 255.255.255.0 -# shutdown -# duplex full -# speed 10 -# ipv6 address FD5D:12C9:2201:1::1/64 -# interface GigabitEthernet0/3.100 -# encapsulation dot1Q 20 - -# Using Deleted without any config passed -#"(NOTE: This will delete all of configured L3 resource module attributes from each configured interface)" - -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# ip address 192.0.2.10 255.255.255.0 -# shutdown -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description Configured by Ansible Network -# ip address 192.168.1.0 255.255.255.0 -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# ip address 192.168.0.1 255.255.255.0 -# shutdown -# duplex full -# speed 10 -# ipv6 address FD5D:12C9:2201:1::1/64 -# interface GigabitEthernet0/3.100 -# encapsulation dot1Q 20 -# ip address 192.168.0.2 255.255.255.0 - -- name: "Delete L3 attributes of ALL interfaces together (NOTE: This won't delete the interface itself)" - ios_l3_interfaces: - state: deleted - -# After state: -# ------------- -# -# vios#show running-config | section ^interface -# interface GigabitEthernet0/1 -# no ip address -# shutdown -# duplex auto -# speed auto -# interface GigabitEthernet0/2 -# description Configured by Ansible Network -# no ip address -# interface GigabitEthernet0/3 -# description Configured by Ansible Network -# shutdown -# duplex full -# speed 10 -# interface GigabitEthernet0/3.100 -# encapsulation dot1Q 20 - -""" - -RETURN = """ -before: - description: The configuration as structured data prior to module invocation. - returned: always - type: list - sample: The configuration returned will always be in the same format of the parameters above. -after: - description: The configuration as structured data after module completion. - returned: when changed - type: list - sample: The configuration returned will always be in the same format of the parameters above. -commands: - description: The set of commands pushed to the remote device - returned: always - type: list - sample: ['interface GigabitEthernet0/1', 'ip address 192.168.0.2 255.255.255.0'] -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.l3_interfaces.l3_interfaces import L3_InterfacesArgs -from ansible.module_utils.network.ios.config.l3_interfaces.l3_interfaces import L3_Interfaces - - -def main(): - """ - Main entry point for module execution - :returns: the result form module invocation - """ - required_if = [('state', 'merged', ('config',)), - ('state', 'replaced', ('config',)), - ('state', 'overridden', ('config',))] - - module = AnsibleModule(argument_spec=L3_InterfacesArgs.argument_spec, - required_if=required_if, - supports_check_mode=True) - - result = L3_Interfaces(module).execute_module() - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_lacp.py b/lib/ansible/modules/network/ios/ios_lacp.py deleted file mode 100644 index 1ebe3b3cef..0000000000 --- a/lib/ansible/modules/network/ios/ios_lacp.py +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The module file for ios_lacp -""" - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network' -} - -DOCUMENTATION = """ ---- -module: ios_lacp -version_added: 2.9 -short_description: Manage Global Link Aggregation Control Protocol (LACP) on Cisco IOS devices. -description: This module provides declarative management of Global LACP on Cisco IOS network devices. -author: Sumit Jaiswal (@justjais) -notes: - - Tested against Cisco IOSv Version 15.2 on VIRL - - This module works with connection C(network_cli), - See L(IOS Platform Options,../network/user_guide/platform_ios.html). -options: - config: - description: The provided configurations. - type: dict - suboptions: - system: - description: This option sets the default system parameters for LACP. - type: dict - suboptions: - priority: - description: - - LACP priority for the system. - - Refer to vendor documentation for valid values. - type: int - required: True - state: - description: - - The state of the configuration after module completion - type: str - choices: - - merged - - replaced - - deleted - default: merged -""" - -EXAMPLES = """ - -# Using merged -# -# Before state: -# ------------- -# -# vios#show lacp sys-id -# 32768, 5e00.0000.8000 - -- name: Merge provided configuration with device configuration - ios_lacp: - config: - system: - priority: 123 - state: merged - -# After state: -# ------------ -# -# vios#show lacp sys-id -# 123, 5e00.0000.8000 - -# Using replaced -# -# Before state: -# ------------- -# -# vios#show lacp sys-id -# 500, 5e00.0000.8000 - -- name: Replaces Global LACP configuration - ios_lacp: - config: - system: - priority: 123 - state: replaced - -# After state: -# ------------ -# -# vios#show lacp sys-id -# 123, 5e00.0000.8000 - -# Using Deleted -# -# Before state: -# ------------- -# -# vios#show lacp sys-id -# 500, 5e00.0000.8000 - -- name: Delete Global LACP attribute - ios_lacp: - state: deleted - -# After state: -# ------------- -# -# vios#show lacp sys-id -# 32768, 5e00.0000.8000 - -""" - -RETURN = """ -before: - description: The configuration as structured data prior to module invocation. - returned: always - type: list - sample: > - The configuration returned will always be in the same format - of the parameters above. -after: - description: The configuration as structured data after module completion. - returned: when changed - type: list - sample: > - The configuration returned will always be in the same format - of the parameters above. -commands: - description: The set of commands pushed to the remote device. - returned: always - type: list - sample: ['lacp system-priority 10'] -""" - - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.lacp.lacp import LacpArgs -from ansible.module_utils.network.ios.config.lacp.lacp import Lacp - - -def main(): - """ - Main entry point for module execution - - :returns: the result form module invocation - """ - required_if = [('state', 'merged', ('config',)), - ('state', 'replaced', ('config',))] - - module = AnsibleModule(argument_spec=LacpArgs.argument_spec, - required_if=required_if, - supports_check_mode=True) - - result = Lacp(module).execute_module() - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_lacp_interfaces.py b/lib/ansible/modules/network/ios/ios_lacp_interfaces.py deleted file mode 100644 index d9e52e39cf..0000000000 --- a/lib/ansible/modules/network/ios/ios_lacp_interfaces.py +++ /dev/null @@ -1,363 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The module file for ios_lacp_interfaces -""" - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network' -} - - -DOCUMENTATION = """ ---- -module: ios_lacp_interfaces -version_added: 2.9 -short_description: Manage Link Aggregation Control Protocol (LACP) on Cisco IOS devices interface. -description: This module provides declarative management of LACP on Cisco IOS network devices lacp_interfaces. -author: Sumit Jaiswal (@justjais) -notes: - - Tested against Cisco IOSv Version 15.2 on VIRL. - - This module works with connection C(network_cli), - See L(IOS Platform Options,../network/user_guide/platform_ios.html). -options: - config: - description: A dictionary of LACP lacp_interfaces option - type: list - elements: dict - suboptions: - name: - description: - - Name of the Interface for configuring LACP. - type: str - required: True - port_priority: - description: - - LACP priority on this interface. - - Refer to vendor documentation for valid port values. - type: int - fast_switchover: - description: - - LACP fast switchover supported on this port channel. - type: bool - max_bundle: - description: - - LACP maximum number of ports to bundle in this port channel. - - Refer to vendor documentation for valid port values. - type: int - state: - description: - - The state of the configuration after module completion - type: str - choices: - - merged - - replaced - - overridden - - deleted - default: merged -""" - -EXAMPLES = """ - -# Using merged -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# interface GigabitEthernet0/2 -# shutdown -# interface GigabitEthernet0/3 -# shutdown - -- name: Merge provided configuration with device configuration - ios_lacp_interfaces: - config: - - name: GigabitEthernet0/1 - port_priority: 10 - - name: GigabitEthernet0/2 - port_priority: 20 - - name: GigabitEthernet0/3 - port_priority: 30 - - name: Port-channel10 - fast_switchover: True - max_bundle: 5 - state: merged - -# After state: -# ------------ -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# lacp fast-switchover -# lacp max-bundle 5 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# lacp port-priority 10 -# interface GigabitEthernet0/2 -# shutdown -# lacp port-priority 20 -# interface GigabitEthernet0/3 -# shutdown -# lacp port-priority 30 - -# Using overridden -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# lacp fast-switchover -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# lacp port-priority 10 -# interface GigabitEthernet0/2 -# shutdown -# lacp port-priority 20 -# interface GigabitEthernet0/3 -# shutdown -# lacp port-priority 30 - -- name: Override device configuration of all lacp_interfaces with provided configuration - ios_lacp_interfaces: - config: - - name: GigabitEthernet0/1 - port_priority: 20 - - name: Port-channel10 - max_bundle: 2 - state: overridden - -# After state: -# ------------ -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# lacp max-bundle 2 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# lacp port-priority 20 -# interface GigabitEthernet0/2 -# shutdown -# interface GigabitEthernet0/3 -# shutdown - -# Using replaced -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# lacp max-bundle 5 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# lacp port-priority 10 -# interface GigabitEthernet0/2 -# shutdown -# lacp port-priority 20 -# interface GigabitEthernet0/3 -# shutdown -# lacp port-priority 30 - -- name: Replaces device configuration of listed lacp_interfaces with provided configuration - ios_lacp_interfaces: - config: - - name: GigabitEthernet0/3 - port_priority: 40 - - name: Port-channel10 - fast_switchover: True - max_bundle: 2 - state: replaced - -# After state: -# ------------ -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# lacp fast-switchover -# lacp max-bundle 2 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# lacp port-priority 10 -# interface GigabitEthernet0/2 -# shutdown -# lacp port-priority 20 -# interface GigabitEthernet0/3 -# shutdown -# lacp port-priority 40 - -# Using Deleted -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# flowcontrol receive on -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# lacp port-priority 10 -# interface GigabitEthernet0/2 -# shutdown -# lacp port-priority 20 -# interface GigabitEthernet0/3 -# shutdown -# lacp port-priority 30 - -- name: "Delete LACP attributes of given interfaces (Note: This won't delete the interface itself)" - ios_lacp_interfaces: - config: - - name: GigabitEthernet0/1 - state: deleted - -# After state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# interface GigabitEthernet0/2 -# shutdown -# lacp port-priority 20 -# interface GigabitEthernet0/3 -# shutdown -# lacp port-priority 30 - -# Using Deleted without any config passed -# "(NOTE: This will delete all of configured LLDP module attributes)" -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# lacp fast-switchover -# interface Port-channel20 -# lacp max-bundle 2 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# lacp port-priority 10 -# interface GigabitEthernet0/2 -# shutdown -# lacp port-priority 20 -# interface GigabitEthernet0/3 -# shutdown -# lacp port-priority 30 - -- name: "Delete LACP attributes for all configured interfaces (Note: This won't delete the interface itself)" - ios_lacp_interfaces: - state: deleted - -# After state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# interface GigabitEthernet0/2 -# shutdown -# interface GigabitEthernet0/3 -# shutdown - -""" - -RETURN = """ -before: - description: The configuration as structured data prior to module invocation. - returned: always - type: list - sample: > - The configuration returned will always be in the same format - of the parameters above. -after: - description: The configuration as structured data after module completion. - returned: when changed - type: list - sample: > - The configuration returned will always be in the same format - of the parameters above. -commands: - description: The set of commands pushed to the remote device. - returned: always - type: list - sample: ['interface GigabitEthernet 0/1', 'lacp port-priority 30'] -""" - - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.lacp_interfaces.lacp_interfaces import Lacp_InterfacesArgs -from ansible.module_utils.network.ios.config.lacp_interfaces.lacp_interfaces import Lacp_Interfaces - - -def main(): - """ - Main entry point for module execution - - :returns: the result form module invocation - """ - required_if = [('state', 'merged', ('config',)), - ('state', 'replaced', ('config',)), - ('state', 'overridden', ('config',))] - - module = AnsibleModule(argument_spec=Lacp_InterfacesArgs.argument_spec, - required_if=required_if, - supports_check_mode=True) - - result = Lacp_Interfaces(module).execute_module() - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_lag_interfaces.py b/lib/ansible/modules/network/ios/ios_lag_interfaces.py deleted file mode 100644 index b5351c6dd8..0000000000 --- a/lib/ansible/modules/network/ios/ios_lag_interfaces.py +++ /dev/null @@ -1,390 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat Inc. -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################## -# WARNING -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -# -############################################## - -""" -The module file for ios_l3_interfaces -""" - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_lag_interfaces -version_added: 2.9 -short_description: Manage Link Aggregation on Cisco IOS devices. -description: This module manages properties of Link Aggregation Group on Cisco IOS devices. -author: Sumit Jaiswal (@justjais) -notes: - - Tested against Cisco IOSv Version 15.2 on VIRL - - This module works with connection C(network_cli). - See L(IOS Platform Options,../network/user_guide/platform_ios.html). -options: - config: - description: A list of link aggregation group configurations. - type: list - elements: dict - suboptions: - name: - description: - - ID of Ethernet Channel of interfaces. - - Refer to vendor documentation for valid port values. - type: str - required: True - members: - description: - - Interface options for the link aggregation group. - type: list - suboptions: - member: - description: - - Interface member of the link aggregation group. - type: str - mode: - description: - - Etherchannel Mode of the interface for link aggregation. - type: str - choices: - - 'auto' - - 'on' - - 'desirable' - - 'active' - - 'passive' - link: - description: - - Assign a link identifier used for load-balancing. - - Refer to vendor documentation for valid values. - - NOTE, parameter only supported on Cisco IOS XE platform. - type: int - state: - description: - - The state of the configuration after module completion - type: str - choices: - - merged - - replaced - - overridden - - deleted - default: merged -""" - -EXAMPLES = """ ---- -# Using merged -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface GigabitEthernet0/1 -# shutdown -# interface GigabitEthernet0/2 -# shutdown -# interface GigabitEthernet0/3 -# shutdown -# interface GigabitEthernet0/4 -# shutdown - -- name: Merge provided configuration with device configuration - ios_lag_interfaces: - config: - - name: 10 - members: - - member: GigabitEthernet0/1 - mode: auto - - member: GigabitEthernet0/2 - mode: auto - - name: 20 - members: - - member: GigabitEthernet0/3 - mode: on - - name: 30 - members: - - member: GigabitEthernet0/4 - mode: active - state: merged - -# After state: -# ------------ -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# channel-group 10 mode auto -# interface GigabitEthernet0/2 -# shutdown -# channel-group 10 mode auto -# interface GigabitEthernet0/3 -# shutdown -# channel-group 20 mode on -# interface GigabitEthernet0/4 -# shutdown -# channel-group 30 mode active - -# Using overridden -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# channel-group 10 mode auto -# interface GigabitEthernet0/2 -# shutdown -# channel-group 10 mode auto -# interface GigabitEthernet0/3 -# shutdown -# channel-group 20 mode on -# interface GigabitEthernet0/4 -# shutdown -# channel-group 30 mode active - -- name: Override device configuration of all interfaces with provided configuration - ios_lag_interfaces: - config: - - name: 20 - members: - - member: GigabitEthernet0/2 - mode: auto - - member: GigabitEthernet0/3 - mode: auto - state: overridden - -# After state: -# ------------ -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# interface GigabitEthernet0/2 -# shutdown -# channel-group 20 mode auto -# interface GigabitEthernet0/3 -# shutdown -# channel-group 20 mode auto -# interface GigabitEthernet0/4 -# shutdown - -# Using replaced -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# channel-group 10 mode auto -# interface GigabitEthernet0/2 -# shutdown -# channel-group 10 mode auto -# interface GigabitEthernet0/3 -# shutdown -# channel-group 20 mode on -# interface GigabitEthernet0/4 -# shutdown -# channel-group 30 mode active - -- name: Replaces device configuration of listed interfaces with provided configuration - ios_lag_interfaces: - config: - - name: 40 - members: - - member: GigabitEthernet0/3 - mode: auto - state: replaced - -# After state: -# ------------ -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface Port-channel20 -# interface Port-channel30 -# interface Port-channel40 -# interface GigabitEthernet0/1 -# shutdown -# channel-group 10 mode auto -# interface GigabitEthernet0/2 -# shutdown -# channel-group 10 mode auto -# interface GigabitEthernet0/3 -# shutdown -# channel-group 40 mode on -# interface GigabitEthernet0/4 -# shutdown -# channel-group 30 mode active - -# Using Deleted -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# channel-group 10 mode auto -# interface GigabitEthernet0/2 -# shutdown -# channel-group 10 mode auto -# interface GigabitEthernet0/3 -# shutdown -# channel-group 20 mode on -# interface GigabitEthernet0/4 -# shutdown -# channel-group 30 mode active - -- name: "Delete LAG attributes of given interfaces (Note: This won't delete the interface itself)" - ios_lag_interfaces: - config: - - name: 10 - - name: 20 - state: deleted - -# After state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# interface GigabitEthernet0/2 -# shutdown -# interface GigabitEthernet0/3 -# shutdown -# interface GigabitEthernet0/4 -# shutdown -# channel-group 30 mode active - -# Using Deleted without any config passed -#"(NOTE: This will delete all of configured LLDP module attributes)" - -# -# Before state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# channel-group 10 mode auto -# interface GigabitEthernet0/2 -# shutdown -# channel-group 10 mode auto -# interface GigabitEthernet0/3 -# shutdown -# channel-group 20 mode on -# interface GigabitEthernet0/4 -# shutdown -# channel-group 30 mode active - -- name: "Delete all configured LAG attributes for interfaces (Note: This won't delete the interface itself)" - ios_lag_interfaces: - state: deleted - -# After state: -# ------------- -# -# vios#show running-config | section ^interface -# interface Port-channel10 -# interface Port-channel20 -# interface Port-channel30 -# interface GigabitEthernet0/1 -# shutdown -# interface GigabitEthernet0/2 -# shutdown -# interface GigabitEthernet0/3 -# shutdown -# interface GigabitEthernet0/4 -# shutdown -""" - -RETURN = """ -before: - description: The configuration as structured data prior to module invocation. - returned: always - type: list - sample: The configuration returned will always be in the same format of the parameters above. -after: - description: The configuration as structured data after module completion. - returned: when changed - type: list - sample: The configuration returned will always be in the same format of the parameters above. -commands: - description: The set of commands pushed to the remote device - returned: always - type: list - sample: ['interface GigabitEthernet0/1', 'channel-group 1 mode active'] -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.lag_interfaces.lag_interfaces import Lag_interfacesArgs -from ansible.module_utils.network.ios.config.lag_interfaces.lag_interfaces import Lag_interfaces - - -def main(): - """ - Main entry point for module execution - :returns: the result form module invocation - """ - required_if = [('state', 'merged', ('config',)), - ('state', 'replaced', ('config',)), - ('state', 'overridden', ('config',))] - - module = AnsibleModule(argument_spec=Lag_interfacesArgs.argument_spec, - required_if=required_if, - supports_check_mode=True) - - result = Lag_interfaces(module).execute_module() - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_linkagg.py b/lib/ansible/modules/network/ios/ios_linkagg.py deleted file mode 100644 index 61620e6b57..0000000000 --- a/lib/ansible/modules/network/ios/ios_linkagg.py +++ /dev/null @@ -1,318 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - -DOCUMENTATION = """ ---- -module: ios_linkagg -version_added: "2.5" -author: "Trishna Guha (@trishnaguha)" -short_description: Manage link aggregation groups on Cisco IOS network devices -description: - - This module provides declarative management of link aggregation groups - on Cisco IOS network devices. -notes: - - Tested against IOS 15.2 -options: - group: - description: - - Channel-group number for the port-channel - Link aggregation group. Range 1-255. - mode: - description: - - Mode of the link aggregation group. - choices: ['active', 'on', 'passive', 'auto', 'desirable'] - members: - description: - - List of members of the link aggregation group. - aggregate: - description: List of link aggregation definitions. - state: - description: - - State of the link aggregation group. - default: present - choices: ['present', 'absent'] - purge: - description: - - Purge links not defined in the I(aggregate) parameter. - default: no - type: bool -extends_documentation_fragment: ios -""" - -EXAMPLES = """ -- name: create link aggregation group - ios_linkagg: - group: 10 - state: present - -- name: delete link aggregation group - ios_linkagg: - group: 10 - state: absent - -- name: set link aggregation group to members - ios_linkagg: - group: 200 - mode: active - members: - - GigabitEthernet0/0 - - GigabitEthernet0/1 - -- name: remove link aggregation group from GigabitEthernet0/0 - ios_linkagg: - group: 200 - mode: active - members: - - GigabitEthernet0/1 - -- name: Create aggregate of linkagg definitions - ios_linkagg: - aggregate: - - { group: 3, mode: on, members: [GigabitEthernet0/1] } - - { group: 100, mode: passive, members: [GigabitEthernet0/2] } -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always, except for the platforms that use Netconf transport to manage the device. - type: list - sample: - - interface port-channel 30 - - interface GigabitEthernet0/3 - - channel-group 30 mode on - - no interface port-channel 30 -""" - -import re -from copy import deepcopy - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.config import CustomNetworkConfig -from ansible.module_utils.network.common.utils import remove_default_spec -from ansible.module_utils.network.ios.ios import get_config, load_config -from ansible.module_utils.network.ios.ios import ios_argument_spec - - -def search_obj_in_list(group, lst): - for o in lst: - if o['group'] == group: - return o - - -def map_obj_to_commands(updates, module): - commands = list() - want, have = updates - purge = module.params['purge'] - - for w in want: - group = w['group'] - mode = w['mode'] - members = w.get('members') or [] - state = w['state'] - del w['state'] - - obj_in_have = search_obj_in_list(group, have) - - if state == 'absent': - if obj_in_have: - commands.append('no interface port-channel {0}'.format(group)) - - elif state == 'present': - cmd = ['interface port-channel {0}'.format(group), - 'end'] - if not obj_in_have: - if not group: - module.fail_json(msg='group is a required option') - commands.extend(cmd) - - if members: - for m in members: - commands.append('interface {0}'.format(m)) - commands.append('channel-group {0} mode {1}'.format(group, mode)) - - else: - if members: - if 'members' not in obj_in_have.keys(): - for m in members: - commands.extend(cmd) - commands.append('interface {0}'.format(m)) - commands.append('channel-group {0} mode {1}'.format(group, mode)) - - elif set(members) != set(obj_in_have['members']): - missing_members = list(set(members) - set(obj_in_have['members'])) - for m in missing_members: - commands.extend(cmd) - commands.append('interface {0}'.format(m)) - commands.append('channel-group {0} mode {1}'.format(group, mode)) - - superfluous_members = list(set(obj_in_have['members']) - set(members)) - for m in superfluous_members: - commands.extend(cmd) - commands.append('interface {0}'.format(m)) - commands.append('no channel-group {0} mode {1}'.format(group, mode)) - - if purge: - for h in have: - obj_in_want = search_obj_in_list(h['group'], want) - if not obj_in_want: - commands.append('no interface port-channel {0}'.format(h['group'])) - - return commands - - -def map_params_to_obj(module): - obj = [] - - aggregate = module.params.get('aggregate') - if aggregate: - for item in aggregate: - for key in item: - if item.get(key) is None: - item[key] = module.params[key] - - d = item.copy() - d['group'] = str(d['group']) - - obj.append(d) - else: - obj.append({ - 'group': str(module.params['group']), - 'mode': module.params['mode'], - 'members': module.params['members'], - 'state': module.params['state'] - }) - - return obj - - -def parse_mode(module, config, group, member): - mode = None - netcfg = CustomNetworkConfig(indent=1, contents=config) - parents = ['interface {0}'.format(member)] - body = netcfg.get_section(parents) - - match_int = re.findall(r'interface {0}\n'.format(member), body, re.M) - if match_int: - match = re.search(r'channel-group {0} mode (\S+)'.format(group), body, re.M) - if match: - mode = match.group(1) - - return mode - - -def parse_members(module, config, group): - members = [] - - for line in config.strip().split('!'): - l = line.strip() - if l.startswith('interface'): - match_group = re.findall(r'channel-group {0} mode'.format(group), l, re.M) - if match_group: - match = re.search(r'interface (\S+)', l, re.M) - if match: - members.append(match.group(1)) - - return members - - -def get_channel(module, config, group): - match = re.findall(r'^interface (\S+)', config, re.M) - - if not match: - return {} - - channel = {} - for item in set(match): - member = item - channel['mode'] = parse_mode(module, config, group, member) - channel['members'] = parse_members(module, config, group) - - return channel - - -def map_config_to_obj(module): - objs = list() - config = get_config(module) - - for line in config.split('\n'): - l = line.strip() - match = re.search(r'interface Port-channel(\S+)', l, re.M) - if match: - obj = {} - group = match.group(1) - obj['group'] = group - obj.update(get_channel(module, config, group)) - objs.append(obj) - - return objs - - -def main(): - """ main entry point for module execution - """ - element_spec = dict( - group=dict(type='int'), - mode=dict(choices=['active', 'on', 'passive', 'auto', 'desirable']), - members=dict(type='list'), - state=dict(default='present', - choices=['present', 'absent']) - ) - - aggregate_spec = deepcopy(element_spec) - aggregate_spec['group'] = dict(required=True) - - required_one_of = [['group', 'aggregate']] - required_together = [['members', 'mode']] - mutually_exclusive = [['group', 'aggregate']] - - # remove default in aggregate spec, to handle common arguments - remove_default_spec(aggregate_spec) - - argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec, - required_together=required_together), - purge=dict(default=False, type='bool') - ) - - argument_spec.update(element_spec) - argument_spec.update(ios_argument_spec) - - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=required_one_of, - required_together=required_together, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) - - warnings = list() - result = {'changed': False} - if warnings: - result['warnings'] = warnings - - want = map_params_to_obj(module) - have = map_config_to_obj(module) - - commands = map_obj_to_commands((want, have), module) - result['commands'] = commands - - if commands: - if not module.check_mode: - load_config(module, commands) - result['changed'] = True - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_lldp.py b/lib/ansible/modules/network/ios/ios_lldp.py deleted file mode 100644 index 7ba7bf385a..0000000000 --- a/lib/ansible/modules/network/ios/ios_lldp.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_lldp -version_added: "2.5" -author: "Ganesh Nalawade (@ganeshrn)" -short_description: Manage LLDP configuration on Cisco IOS network devices. -description: - - This module provides declarative management of LLDP service - on Cisco IOS network devices. -notes: - - Tested against IOS 15.2 -options: - state: - description: - - State of the LLDP configuration. If value is I(present) lldp will be enabled - else if it is I(absent) it will be disabled. - default: present - choices: ['present', 'absent'] -extends_documentation_fragment: ios -""" - -EXAMPLES = """ -- name: Enable LLDP service - ios_lldp: - state: present - -- name: Disable LLDP service - ios_lldp: - state: absent -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always, except for the platforms that use Netconf transport to manage the device. - type: list - sample: - - lldp run -""" -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.ios import load_config, run_commands -from ansible.module_utils.network.ios.ios import ios_argument_spec - - -def has_lldp(module): - output = run_commands(module, ['show lldp']) - - is_lldp_enable = False - if len(output) > 0 and "LLDP is not enabled" not in output[0]: - is_lldp_enable = True - - return is_lldp_enable - - -def main(): - """ main entry point for module execution - """ - argument_spec = dict( - state=dict(default='present', - choices=['present', 'absent', - 'enabled', 'disabled']) - ) - - argument_spec.update(ios_argument_spec) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - warnings = list() - - result = {'changed': False} - - if warnings: - result['warnings'] = warnings - - HAS_LLDP = has_lldp(module) - - commands = [] - - if module.params['state'] == 'absent' and HAS_LLDP: - commands.append('no lldp run') - elif module.params['state'] == 'present' and not HAS_LLDP: - commands.append('lldp run') - - result['commands'] = commands - - if commands: - if not module.check_mode: - load_config(module, commands) - - result['changed'] = True - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_lldp_global.py b/lib/ansible/modules/network/ios/ios_lldp_global.py deleted file mode 100644 index 49c146f8d2..0000000000 --- a/lib/ansible/modules/network/ios/ios_lldp_global.py +++ /dev/null @@ -1,256 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The module file for ios_lldp_global -""" - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_lldp_global -version_added: 2.9 -short_description: Configure and manage Link Layer Discovery Protocol(LLDP) attributes on IOS platforms. -description: This module configures and manages the Link Layer Discovery Protocol(LLDP) attributes on IOS platforms. -author: Sumit Jaiswal (@justjais) -notes: - - Tested against Cisco IOSv Version 15.2 on VIRL - - This module works with connection C(network_cli), - See L(IOS Platform Options,../network/user_guide/platform_ios.html). -options: - config: - description: A dictionary of LLDP options - type: dict - suboptions: - holdtime: - description: - - LLDP holdtime (in sec) to be sent in packets. - - Refer to vendor documentation for valid values. - type: int - reinit: - description: - - Specify the delay (in secs) for LLDP to initialize. - - Refer to vendor documentation for valid values. - - NOTE, if LLDP reinit is configured with a starting - value, idempotency won't be maintained as the Cisco - device doesn't record the starting reinit configured - value. As such, Ansible cannot verify if the respective - starting reinit value is already configured or not from - the device side. If you try to apply starting reinit - value in every play run, Ansible will show changed as True. - For any other reinit value, idempotency will be maintained - since any other reinit value is recorded in the Cisco device. - type: int - enabled: - description: - - Enable LLDP - type: bool - timer: - description: - - Specify the rate at which LLDP packets are sent (in sec). - - Refer to vendor documentation for valid values. - type: int - tlv_select: - description: - - Selection of LLDP TLVs i.e. type-length-value to send - - NOTE, if tlv-select is configured idempotency won't be maintained - as Cisco device doesn't record configured tlv-select options. As - such, Ansible cannot verify if the respective tlv-select options is - already configured or not from the device side. If you try to apply - tlv-select option in every play run, Ansible will show changed as True. - type: dict - suboptions: - four_wire_power_management: - description: - - Cisco 4-wire Power via MDI TLV - type: bool - mac_phy_cfg: - description: - - IEEE 802.3 MAC/Phy Configuration/status TLV - type: bool - management_address: - description: - - Management Address TLV - type: bool - port_description: - description: - - Port Description TLV - type: bool - port_vlan: - description: - - Port VLAN ID TLV - type: bool - power_management: - description: - - IEEE 802.3 DTE Power via MDI TLV - type: bool - system_capabilities: - description: - - System Capabilities TLV - type: bool - system_description: - description: - - System Description TLV - type: bool - system_name: - description: - - System Name TLV - type: bool - state: - description: - - The state of the configuration after module completion - type: str - choices: - - merged - - replaced - - deleted - default: merged -""" - -EXAMPLES = """ ---- - -# Using merged - -# Before state: -# ------------- -# vios#sh running-config | section ^lldp -# vios1# - - -- name: Merge provided configuration with device configuration - ios_lldp_global: - config: - holdtime: 10 - enabled: True - reinit: 3 - timer: 10 - state: merged - -# After state: -# ------------ -# vios#sh running-config | section ^lldp -# lldp timer 10 -# lldp holdtime 10 -# lldp reinit 3 -# lldp run - - -# Using replaced - -# Before state: -# ------------- -# vios#sh running-config | section ^lldp -# lldp timer 10 -# lldp holdtime 10 -# lldp reinit 3 -# lldp run - - -- name: Replaces LLDP device configuration with provided configuration - ios_lldp_global: - config: - holdtime: 20 - reinit: 5 - state: replaced - -# After state: -# ------------- -# vios#sh running-config | section ^lldp -# lldp holdtime 20 -# lldp reinit 5 - - -# Using Deleted without any config passed -#"(NOTE: This will delete all of configured LLDP module attributes)" - -# Before state: -# ------------- -# vios#sh running-config | section ^lldp -# lldp timer 10 -# lldp holdtime 10 -# lldp reinit 3 -# lldp run - - -- name: "Delete LLDP attributes (Note: This won't delete the interface itself)" - ios_lldp_global: - state: deleted - -# After state: -# ------------- -# vios#sh running-config | section ^lldp -# vios1# - -""" - -RETURN = """ -before: - description: The configuration as structured data prior to module invocation. - returned: always - type: dict - sample: The configuration returned will always be in the same format of the parameters above. -after: - description: The configuration as structured data after module completion. - returned: when changed - type: dict - sample: The configuration returned will always be in the same format of the parameters above. -commands: - description: The set of commands pushed to the remote device - returned: always - type: list - sample: ['lldp holdtime 10', 'lldp run', 'lldp timer 10'] -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.lldp_global.lldp_global import Lldp_globalArgs -from ansible.module_utils.network.ios.config.lldp_global.lldp_global import Lldp_global - - -def main(): - """ - Main entry point for module execution - - :returns: the result form module invocation - """ - required_if = [('state', 'merged', ('config',)), - ('state', 'replaced', ('config',))] - - module = AnsibleModule(argument_spec=Lldp_globalArgs.argument_spec, - required_if=required_if, - supports_check_mode=True) - - result = Lldp_global(module).execute_module() - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_lldp_interfaces.py b/lib/ansible/modules/network/ios/ios_lldp_interfaces.py deleted file mode 100644 index c1bbc274e4..0000000000 --- a/lib/ansible/modules/network/ios/ios_lldp_interfaces.py +++ /dev/null @@ -1,501 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The module file for ios_lldp_interfaces -""" - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network' -} - - -DOCUMENTATION = """ ---- -module: ios_lldp_interfaces -version_added: 2.9 -short_description: Manage link layer discovery protocol (LLDP) attributes of interfaces on Cisco IOS devices. -description: This module manages link layer discovery protocol (LLDP) attributes of interfaces on Cisco IOS devices. -author: Sumit Jaiswal (@justjais) -notes: - - Tested against Cisco IOSv Version 15.2 on VIRL - - This module works with connection C(network_cli), - See L(IOS Platform Options,../network/user_guide/platform_ios.html). -options: - config: - description: A dictionary of LLDP options - type: list - elements: dict - suboptions: - name: - description: - - Full name of the interface excluding any logical unit number, i.e. GigabitEthernet0/1. - type: str - required: True - receive: - description: - - Enable LLDP reception on interface. - type: bool - transmit: - description: - - Enable LLDP transmission on interface. - type: bool - med_tlv_select: - description: - - Selection of LLDP MED TLVs to send - - NOTE, if med-tlv-select is configured idempotency won't be maintained - as Cisco device doesn't record configured med-tlv-select options. As - such, Ansible cannot verify if the respective med-tlv-select options is - already configured or not from the device side. If you try to apply - med-tlv-select option in every play run, Ansible will show changed as - True. - type: dict - suboptions: - inventory_management: - description: - - LLDP MED Inventory Management TLV - type: bool - tlv_select: - description: - - Selection of LLDP type-length-value i.e. TLVs to send - - NOTE, if tlv-select is configured idempotency won't be maintained - as Cisco device doesn't record configured tlv-select options. As - such, Ansible cannot verify if the respective tlv-select options is - already configured or not from the device side. If you try to apply - tlv-select option in every play run, Ansible will show changed as True. - type: dict - suboptions: - power_management: - description: - - IEEE 802.3 DTE Power via MDI TLV - type: bool - state: - description: - - The state of the configuration after module completion - type: str - choices: - - merged - - replaced - - overridden - - deleted - default: merged -""" - -EXAMPLES = """ - -# Using merged -# -# Before state: -# ------------- -# -# vios#sh lldp interface -# GigabitEthernet0/0: -# Tx: enabled -# Rx: disabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/1: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/2: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: INIT -# -# GigabitEthernet0/3: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# - -- name: Merge provided configuration with device configuration - ios_lldp_interfaces: - config: - - name: GigabitEthernet0/1 - receive: True - transmit: True - - name: GigabitEthernet0/2 - receive: True - - name: GigabitEthernet0/3 - transmit: True - state: merged - -# After state: -# ------------ -# -# vios#sh lldp interface -# GigabitEthernet0/0: -# Tx: enabled -# Rx: disabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/1: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/2: -# Tx: disabled -# Rx: enabled -# Tx state: IDLE -# Rx state: INIT -# -# GigabitEthernet0/3: -# Tx: enabled -# Rx: disabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# - -# Using overridden -# -# Before state: -# ------------- -# -# vios#sh lldp interface -# GigabitEthernet0/0: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/1: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/2: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: INIT -# -# GigabitEthernet0/3: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# - -- name: Override device configuration of all lldp_interfaces with provided configuration - ios_lldp_interfaces: - config: - - name: GigabitEthernet0/2 - receive: True - transmit: True - state: overridden - -# After state: -# ------------ -# -# vios#sh lldp interface -# GigabitEthernet0/0: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/1: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/2: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: INIT -# -# GigabitEthernet0/3: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME - -# Using replaced -# -# Before state: -# ------------- -# -# vios#sh lldp interface -# GigabitEthernet0/0: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/1: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/2: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: INIT -# -# GigabitEthernet0/3: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# - -- name: Replaces device configuration of listed lldp_interfaces with provided configuration - ios_lldp_interfaces: - config: - - name: GigabitEthernet0/2 - receive: True - transmit: True - - name: GigabitEthernet0/3 - receive: True - state: replaced - -# After state: -# ------------ -# -# vios#sh lldp interface -# GigabitEthernet0/0: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/1: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/2: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: INIT -# -# GigabitEthernet0/3: -# Tx: disabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# - -# Using Deleted -# -# Before state: -# ------------- -# -# vios#sh lldp interface -# GigabitEthernet0/0: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/1: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/2: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: INIT -# -# GigabitEthernet0/3: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# - -- name: "Delete LLDP attributes of given interfaces (Note: This won't delete the interface itself)" - ios_lldp_interfaces: - config: - - name: GigabitEthernet0/1 - state: deleted - -# After state: -# ------------- -# -# vios#sh lldp interface -# GigabitEthernet0/0: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/1: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/2: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: INIT -# -# GigabitEthernet0/3: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# - -# Using Deleted without any config passed -# "(NOTE: This will delete all of configured LLDP module attributes)" -# -# Before state: -# ------------- -# -# vios#sh lldp interface -# GigabitEthernet0/0: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/1: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/2: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: INIT -# -# GigabitEthernet0/3: -# Tx: enabled -# Rx: enabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# - -- name: "Delete LLDP attributes for all configured interfaces (Note: This won't delete the interface itself)" - ios_lldp_interfaces: - state: deleted - -# After state: -# ------------- -# -# vios#sh lldp interface -# GigabitEthernet0/0: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/1: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# -# GigabitEthernet0/2: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: INIT -# -# GigabitEthernet0/3: -# Tx: disabled -# Rx: disabled -# Tx state: IDLE -# Rx state: WAIT FOR FRAME -# - -""" - -RETURN = """ -before: - description: The configuration as structured data prior to module invocation. - returned: always - type: list - sample: > - The configuration returned will always be in the same format - of the parameters above. -after: - description: The configuration as structured data after module completion. - returned: when changed - type: list - sample: > - The configuration returned will always be in the same format - of the parameters above. -commands: - description: The set of commands pushed to the remote device. - returned: always - type: list - sample: ['interface GigabitEthernet 0/1', 'lldp transmit', 'lldp receive'] -""" - - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.lldp_interfaces.lldp_interfaces import Lldp_InterfacesArgs -from ansible.module_utils.network.ios.config.lldp_interfaces.lldp_interfaces import Lldp_Interfaces - - -def main(): - """ - Main entry point for module execution - - :returns: the result form module invocation - """ - required_if = [('state', 'merged', ('config',)), - ('state', 'replaced', ('config',)), - ('state', 'overridden', ('config',))] - - module = AnsibleModule(argument_spec=Lldp_InterfacesArgs.argument_spec, - required_if=required_if, - supports_check_mode=True) - - result = Lldp_Interfaces(module).execute_module() - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_logging.py b/lib/ansible/modules/network/ios/ios_logging.py deleted file mode 100644 index b91f3ff2b9..0000000000 --- a/lib/ansible/modules/network/ios/ios_logging.py +++ /dev/null @@ -1,429 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# -# This file is part of Ansible by Red Hat -# -# 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 <http://www.gnu.org/licenses/>. -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - -DOCUMENTATION = """ ---- -module: ios_logging -version_added: "2.4" -author: "Trishna Guha (@trishnaguha)" -short_description: Manage logging on network devices -description: - - This module provides declarative management of logging - on Cisco Ios devices. -notes: - - Tested against IOS 15.6 -options: - dest: - description: - - Destination of the logs. - choices: ['on', 'host', 'console', 'monitor', 'buffered', 'trap'] - name: - description: - - The hostname or IP address of the destination. - - Required when I(dest=host). - size: - description: - - Size of buffer. The acceptable value is in range from 4096 to - 4294967295 bytes. - default: 4096 - facility: - description: - - Set logging facility. - level: - description: - - Set logging severity levels. - default: debugging - choices: ['emergencies', 'alerts', 'critical', 'errors', 'warnings', 'notifications', 'informational', 'debugging'] - aggregate: - description: List of logging definitions. - state: - description: - - State of the logging configuration. - default: present - choices: ['present', 'absent'] -extends_documentation_fragment: ios -""" - -EXAMPLES = """ -- name: configure host logging - ios_logging: - dest: host - name: 172.16.0.1 - state: present - -- name: remove host logging configuration - ios_logging: - dest: host - name: 172.16.0.1 - state: absent - -- name: configure console logging level and facility - ios_logging: - dest: console - facility: local7 - level: debugging - state: present - -- name: enable logging to all - ios_logging: - dest : on - -- name: configure buffer size - ios_logging: - dest: buffered - size: 5000 - -- name: Configure logging using aggregate - ios_logging: - aggregate: - - { dest: console, level: notifications } - - { dest: buffered, size: 9000 } - -- name: remove logging using aggregate - ios_logging: - aggregate: - - { dest: console, level: notifications } - - { dest: buffered, size: 9000 } - state: absent -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always - type: list - sample: - - logging facility local7 - - logging host 172.16.0.1 -""" - -import re - -from copy import deepcopy -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import remove_default_spec, validate_ip_address -from ansible.module_utils.network.ios.ios import get_config, load_config -from ansible.module_utils.network.ios.ios import get_capabilities -from ansible.module_utils.network.ios.ios import ios_argument_spec - - -def validate_size(value, module): - if value: - if not int(4096) <= int(value) <= int(4294967295): - module.fail_json(msg='size must be between 4096 and 4294967295') - else: - return value - - -def map_obj_to_commands(updates, module, os_version): - dest_group = ('console', 'monitor', 'buffered', 'on', 'trap') - commands = list() - want, have = updates - for w in want: - dest = w['dest'] - name = w['name'] - size = w['size'] - facility = w['facility'] - level = w['level'] - state = w['state'] - del w['state'] - - if facility: - w['dest'] = 'facility' - - if state == 'absent' and w in have: - if dest: - if dest == 'host': - if '12.' in os_version: - commands.append('no logging {0}'.format(name)) - else: - commands.append('no logging host {0}'.format(name)) - - elif dest in dest_group: - commands.append('no logging {0}'.format(dest)) - - else: - module.fail_json(msg='dest must be among console, monitor, buffered, host, on, trap') - - if facility: - commands.append('no logging facility {0}'.format(facility)) - - if state == 'present' and w not in have: - if facility: - present = False - - for entry in have: - if entry['dest'] == 'facility' and entry['facility'] == facility: - present = True - - if not present: - commands.append('logging facility {0}'.format(facility)) - - if dest == 'host': - if '12.' in os_version: - commands.append('logging {0}'.format(name)) - else: - commands.append('logging host {0}'.format(name)) - - elif dest == 'on': - commands.append('logging on') - - elif dest == 'buffered' and size: - present = False - - for entry in have: - if entry['dest'] == 'buffered' and entry['size'] == size and entry['level'] == level: - present = True - - if not present: - if level and level != 'debugging': - commands.append('logging buffered {0} {1}'.format(size, level)) - else: - commands.append('logging buffered {0}'.format(size)) - - else: - if dest: - dest_cmd = 'logging {0}'.format(dest) - if level: - dest_cmd += ' {0}'.format(level) - commands.append(dest_cmd) - return commands - - -def parse_facility(line, dest): - facility = None - if dest == 'facility': - match = re.search(r'logging facility (\S+)', line, re.M) - if match: - facility = match.group(1) - - return facility - - -def parse_size(line, dest): - size = None - - if dest == 'buffered': - match = re.search(r'logging buffered(?: (\d+))?(?: [a-z]+)?', line, re.M) - if match: - if match.group(1) is not None: - size = match.group(1) - else: - size = "4096" - - return size - - -def parse_name(line, dest): - if dest == 'host': - match = re.search(r'logging host (\S+)', line, re.M) - if match: - name = match.group(1) - else: - name = None - - return name - - -def parse_level(line, dest): - level_group = ('emergencies', 'alerts', 'critical', 'errors', 'warnings', - 'notifications', 'informational', 'debugging') - - if dest == 'host': - level = 'debugging' - - else: - if dest == 'buffered': - match = re.search(r'logging buffered(?: \d+)?(?: ([a-z]+))?', line, re.M) - else: - match = re.search(r'logging {0} (\S+)'.format(dest), line, re.M) - - if match and match.group(1) in level_group: - level = match.group(1) - else: - level = 'debugging' - - return level - - -def map_config_to_obj(module): - obj = [] - dest_group = ('console', 'host', 'monitor', 'buffered', 'on', 'facility', 'trap') - - data = get_config(module, flags=['| include logging']) - - for line in data.split('\n'): - match = re.search(r'^logging (\S+)', line, re.M) - if match: - if match.group(1) in dest_group: - dest = match.group(1) - - obj.append({ - 'dest': dest, - 'name': parse_name(line, dest), - 'size': parse_size(line, dest), - 'facility': parse_facility(line, dest), - 'level': parse_level(line, dest) - }) - elif validate_ip_address(match.group(1)): - dest = 'host' - obj.append({ - 'dest': dest, - 'name': match.group(1), - 'size': parse_size(line, dest), - 'facility': parse_facility(line, dest), - 'level': parse_level(line, dest) - }) - else: - ip_match = re.search(r'\d+\.\d+\.\d+\.\d+', match.group(1), re.M) - if ip_match: - dest = 'host' - obj.append({ - 'dest': dest, - 'name': match.group(1), - 'size': parse_size(line, dest), - 'facility': parse_facility(line, dest), - 'level': parse_level(line, dest) - }) - return obj - - -def map_params_to_obj(module, required_if=None): - obj = [] - aggregate = module.params.get('aggregate') - - if aggregate: - for item in aggregate: - for key in item: - if item.get(key) is None: - item[key] = module.params[key] - - module._check_required_if(required_if, item) - - d = item.copy() - if d['dest'] != 'host': - d['name'] = None - - if d['dest'] == 'buffered': - if 'size' in d: - d['size'] = str(validate_size(d['size'], module)) - elif 'size' not in d: - d['size'] = str(4096) - else: - pass - - if d['dest'] != 'buffered': - d['size'] = None - - obj.append(d) - - else: - if module.params['dest'] != 'host': - module.params['name'] = None - - if module.params['dest'] == 'buffered': - if not module.params['size']: - module.params['size'] = str(4096) - else: - module.params['size'] = None - - if module.params['size'] is None: - obj.append({ - 'dest': module.params['dest'], - 'name': module.params['name'], - 'size': module.params['size'], - 'facility': module.params['facility'], - 'level': module.params['level'], - 'state': module.params['state'] - }) - - else: - obj.append({ - 'dest': module.params['dest'], - 'name': module.params['name'], - 'size': str(validate_size(module.params['size'], module)), - 'facility': module.params['facility'], - 'level': module.params['level'], - 'state': module.params['state'] - }) - return obj - - -def main(): - """ main entry point for module execution - """ - element_spec = dict( - dest=dict(type='str', choices=['on', 'host', 'console', 'monitor', 'buffered', 'trap']), - name=dict(type='str'), - size=dict(type='int'), - facility=dict(type='str'), - level=dict(type='str', default='debugging', choices=['emergencies', 'alerts', 'critical', 'errors', 'warnings', - 'notifications', 'informational', 'debugging']), - state=dict(default='present', choices=['present', 'absent']), - ) - - aggregate_spec = deepcopy(element_spec) - - # remove default in aggregate spec, to handle common arguments - remove_default_spec(aggregate_spec) - - argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), - ) - - argument_spec.update(element_spec) - argument_spec.update(ios_argument_spec) - - required_if = [('dest', 'host', ['name'])] - - module = AnsibleModule(argument_spec=argument_spec, - required_if=required_if, - supports_check_mode=True) - - device_info = get_capabilities(module) - os_version = device_info['device_info']['network_os_version'] - - warnings = list() - - result = {'changed': False} - if warnings: - result['warnings'] = warnings - - want = map_params_to_obj(module, required_if=required_if) - have = map_config_to_obj(module) - - commands = map_obj_to_commands((want, have), module, os_version) - result['commands'] = commands - - if commands: - if not module.check_mode: - load_config(module, commands) - result['changed'] = True - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_ntp.py b/lib/ansible/modules/network/ios/ios_ntp.py deleted file mode 100644 index 682140c375..0000000000 --- a/lib/ansible/modules/network/ios/ios_ntp.py +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/python -# Copyright: Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = ''' ---- -module: ios_ntp -extends_documentation_fragment: ios -version_added: "2.8" -short_description: Manages core NTP configuration. -description: - - Manages core NTP configuration. -author: - - Federico Olivieri (@Federico87) -options: - server: - description: - - Network address of NTP server. - source_int: - description: - - Source interface for NTP packets. - acl: - description: - - ACL for peer/server access restricition. - logging: - description: - - Enable NTP logs. Data type boolean. - type: bool - default: False - auth: - description: - - Enable NTP authentication. Data type boolean. - type: bool - default: False - auth_key: - description: - - md5 NTP authentication key of tye 7. - key_id: - description: - - auth_key id. Data type string - state: - description: - - Manage the state of the resource. - default: present - choices: ['present', 'absent'] -''' - -EXAMPLES = ''' -# Set new NTP server and source interface -- ios_ntp: - server: 10.0.255.10 - source_int: Loopback0 - logging: false - state: present - -# Remove NTP ACL and logging -- ios_ntp: - acl: NTP_ACL - logging: true - state: absent - -# Set NTP authentication -- ios_ntp: - key_id: 10 - auth_key: 15435A030726242723273C21181319000A - auth: true - state: present - -# Set new NTP configuration -- ios_ntp: - server: 10.0.255.10 - source_int: Loopback0 - acl: NTP_ACL - logging: true - key_id: 10 - auth_key: 15435A030726242723273C21181319000A - auth: true - state: present -''' - -RETURN = ''' -commands: - description: command sent to the device - returned: always - type: list - sample: ["no ntp server 10.0.255.10", "no ntp source Loopback0"] -''' -import re - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.ios import get_config, load_config -from ansible.module_utils.network.ios.ios import ios_argument_spec - - -def parse_server(line, dest): - if dest == 'server': - match = re.search(r'(ntp server )(\d+\.\d+\.\d+\.\d+)', line, re.M) - if match: - server = match.group(2) - return server - - -def parse_source_int(line, dest): - if dest == 'source': - match = re.search(r'(ntp source )(\S+)', line, re.M) - if match: - source = match.group(2) - return source - - -def parse_acl(line, dest): - if dest == 'access-group': - match = re.search(r'ntp access-group (?:peer|serve)(?:\s+)(\S+)', line, re.M) - if match: - acl = match.group(1) - return acl - - -def parse_logging(line, dest): - if dest == 'logging': - logging = dest - return logging - - -def parse_auth_key(line, dest): - if dest == 'authentication-key': - match = re.search(r'(ntp authentication-key \d+ md5 )(\w+)', line, re.M) - if match: - auth_key = match.group(2) - return auth_key - - -def parse_key_id(line, dest): - if dest == 'trusted-key': - match = re.search(r'(ntp trusted-key )(\d+)', line, re.M) - if match: - auth_key = match.group(2) - return auth_key - - -def parse_auth(dest): - if dest == 'authenticate': - return dest - - -def map_config_to_obj(module): - - obj_dict = {} - obj = [] - server_list = [] - - config = get_config(module, flags=['| include ntp']) - - for line in config.splitlines(): - match = re.search(r'ntp (\S+)', line, re.M) - if match: - dest = match.group(1) - - server = parse_server(line, dest) - source_int = parse_source_int(line, dest) - acl = parse_acl(line, dest) - logging = parse_logging(line, dest) - auth = parse_auth(dest) - auth_key = parse_auth_key(line, dest) - key_id = parse_key_id(line, dest) - - if server: - server_list.append(server) - if source_int: - obj_dict['source_int'] = source_int - if acl: - obj_dict['acl'] = acl - if logging: - obj_dict['logging'] = True - if auth: - obj_dict['auth'] = True - if auth_key: - obj_dict['auth_key'] = auth_key - if key_id: - obj_dict['key_id'] = key_id - - obj_dict['server'] = server_list - obj.append(obj_dict) - - return obj - - -def map_params_to_obj(module): - obj = [] - obj.append({ - 'state': module.params['state'], - 'server': module.params['server'], - 'source_int': module.params['source_int'], - 'logging': module.params['logging'], - 'acl': module.params['acl'], - 'auth': module.params['auth'], - 'auth_key': module.params['auth_key'], - 'key_id': module.params['key_id'] - }) - - return obj - - -def map_obj_to_commands(want, have, module): - - commands = list() - - server_have = have[0].get('server', None) - source_int_have = have[0].get('source_int', None) - acl_have = have[0].get('acl', None) - logging_have = have[0].get('logging', None) - auth_have = have[0].get('auth', None) - auth_key_have = have[0].get('auth_key', None) - key_id_have = have[0].get('key_id', None) - - for w in want: - server = w['server'] - source_int = w['source_int'] - acl = w['acl'] - logging = w['logging'] - state = w['state'] - auth = w['auth'] - auth_key = w['auth_key'] - key_id = w['key_id'] - - if state == 'absent': - if server_have and server in server_have: - commands.append('no ntp server {0}'.format(server)) - if source_int and source_int_have: - commands.append('no ntp source {0}'.format(source_int)) - if acl and acl_have: - commands.append('no ntp access-group peer {0}'.format(acl)) - if logging is True and logging_have: - commands.append('no ntp logging') - if auth is True and auth_have: - commands.append('no ntp authenticate') - if key_id and key_id_have: - commands.append('no ntp trusted-key {0}'.format(key_id)) - if auth_key and auth_key_have: - if key_id and key_id_have: - commands.append('no ntp authentication-key {0} md5 {1} 7'.format(key_id, auth_key)) - - elif state == 'present': - if server is not None and server not in server_have: - commands.append('ntp server {0}'.format(server)) - if source_int is not None and source_int != source_int_have: - commands.append('ntp source {0}'.format(source_int)) - if acl is not None and acl != acl_have: - commands.append('ntp access-group peer {0}'.format(acl)) - if logging is not None and logging != logging_have and logging is not False: - commands.append('ntp logging') - if auth is not None and auth != auth_have and auth is not False: - commands.append('ntp authenticate') - if key_id is not None and key_id != key_id_have: - commands.append('ntp trusted-key {0}'.format(key_id)) - if auth_key is not None and auth_key != auth_key_have: - if key_id is not None: - commands.append('ntp authentication-key {0} md5 {1} 7'.format(key_id, auth_key)) - - return commands - - -def main(): - - argument_spec = dict( - server=dict(), - source_int=dict(), - acl=dict(), - logging=dict(type='bool', default=False), - auth=dict(type='bool', default=False), - auth_key=dict(), - key_id=dict(), - state=dict(choices=['absent', 'present'], default='present') - ) - - argument_spec.update(ios_argument_spec) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True - ) - - result = {'changed': False} - - warnings = list() - if warnings: - result['warnings'] = warnings - - want = map_params_to_obj(module) - have = map_config_to_obj(module) - - commands = map_obj_to_commands(want, have, module) - result['commands'] = commands - - if commands: - if not module.check_mode: - load_config(module, commands) - result['changed'] = True - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_ping.py b/lib/ansible/modules/network/ios/ios_ping.py deleted file mode 100644 index 6b7fca9261..0000000000 --- a/lib/ansible/modules/network/ios/ios_ping.py +++ /dev/null @@ -1,210 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'community'} - -DOCUMENTATION = r''' ---- -module: ios_ping -short_description: Tests reachability using ping from Cisco IOS network devices -description: -- Tests reachability using ping from switch to a remote destination. -- For a general purpose network module, see the M(net_ping) module. -- For Windows targets, use the M(win_ping) module instead. -- For targets running Python, use the M(ping) module instead. -author: -- Jacob McGill (@jmcgill298) -version_added: '2.4' -extends_documentation_fragment: ios -options: - count: - description: - - Number of packets to send. - default: 5 - dest: - description: - - The IP Address or hostname (resolvable by switch) of the remote node. - required: true - source: - description: - - The source IP Address. - state: - description: - - Determines if the expected result is success or fail. - choices: [ absent, present ] - default: present - vrf: - description: - - The VRF to use for forwarding. - default: default -notes: - - For a general purpose network module, see the M(net_ping) module. - - For Windows targets, use the M(win_ping) module instead. - - For targets running Python, use the M(ping) module instead. -''' - -EXAMPLES = r''' -- name: Test reachability to 10.10.10.10 using default vrf - ios_ping: - dest: 10.10.10.10 - -- name: Test reachability to 10.20.20.20 using prod vrf - ios_ping: - dest: 10.20.20.20 - vrf: prod - -- name: Test unreachability to 10.30.30.30 using default vrf - ios_ping: - dest: 10.30.30.30 - state: absent - -- name: Test reachability to 10.40.40.40 using prod vrf and setting count and source - ios_ping: - dest: 10.40.40.40 - source: loopback0 - vrf: prod - count: 20 -''' - -RETURN = ''' -commands: - description: Show the command sent. - returned: always - type: list - sample: ["ping vrf prod 10.40.40.40 count 20 source loopback0"] -packet_loss: - description: Percentage of packets lost. - returned: always - type: str - sample: "0%" -packets_rx: - description: Packets successfully received. - returned: always - type: int - sample: 20 -packets_tx: - description: Packets successfully transmitted. - returned: always - type: int - sample: 20 -rtt: - description: Show RTT stats. - returned: always - type: dict - sample: {"avg": 2, "max": 8, "min": 1} -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.ios import run_commands -from ansible.module_utils.network.ios.ios import ios_argument_spec -import re - - -def main(): - """ main entry point for module execution - """ - argument_spec = dict( - count=dict(type="int"), - dest=dict(type="str", required=True), - source=dict(type="str"), - state=dict(type="str", choices=["absent", "present"], default="present"), - vrf=dict(type="str") - ) - - argument_spec.update(ios_argument_spec) - - module = AnsibleModule(argument_spec=argument_spec) - - count = module.params["count"] - dest = module.params["dest"] - source = module.params["source"] - vrf = module.params["vrf"] - - warnings = list() - - results = {} - if warnings: - results["warnings"] = warnings - - results["commands"] = [build_ping(dest, count, source, vrf)] - - ping_results = run_commands(module, commands=results["commands"]) - ping_results_list = ping_results[0].split("\n") - - stats = "" - for line in ping_results_list: - if line.startswith('Success'): - stats = line - - success, rx, tx, rtt = parse_ping(stats) - loss = abs(100 - int(success)) - results["packet_loss"] = str(loss) + "%" - results["packets_rx"] = int(rx) - results["packets_tx"] = int(tx) - - # Convert rtt values to int - for k, v in rtt.items(): - if rtt[k] is not None: - rtt[k] = int(v) - - results["rtt"] = rtt - - validate_results(module, loss, results) - - module.exit_json(**results) - - -def build_ping(dest, count=None, source=None, vrf=None): - """ - Function to build the command to send to the terminal for the switch - to execute. All args come from the module's unique params. - """ - if vrf is not None: - cmd = "ping vrf {0} {1}".format(vrf, dest) - else: - cmd = "ping {0}".format(dest) - - if count is not None: - cmd += " repeat {0}".format(str(count)) - - if source is not None: - cmd += " source {0}".format(source) - - return cmd - - -def parse_ping(ping_stats): - """ - Function used to parse the statistical information from the ping response. - Example: "Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/8 ms" - Returns the percent of packet loss, received packets, transmitted packets, and RTT dict. - """ - rate_re = re.compile(r"^\w+\s+\w+\s+\w+\s+(?P<pct>\d+)\s+\w+\s+\((?P<rx>\d+)/(?P<tx>\d+)\)") - rtt_re = re.compile(r".*,\s+\S+\s+\S+\s+=\s+(?P<min>\d+)/(?P<avg>\d+)/(?P<max>\d+)\s+\w+\s*$|.*\s*$") - - rate = rate_re.match(ping_stats) - rtt = rtt_re.match(ping_stats) - - return rate.group("pct"), rate.group("rx"), rate.group("tx"), rtt.groupdict() - - -def validate_results(module, loss, results): - """ - This function is used to validate whether the ping results were unexpected per "state" param. - """ - state = module.params["state"] - if state == "present" and loss == 100: - module.fail_json(msg="Ping failed unexpectedly", **results) - elif state == "absent" and loss < 100: - module.fail_json(msg="Ping succeeded unexpectedly", **results) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/network/ios/ios_static_route.py b/lib/ansible/modules/network/ios/ios_static_route.py deleted file mode 100644 index 541a76a0c1..0000000000 --- a/lib/ansible/modules/network/ios/ios_static_route.py +++ /dev/null @@ -1,313 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# -# This file is part of Ansible by Red Hat -# -# 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 <http://www.gnu.org/licenses/>. -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_static_route -version_added: "2.4" -author: "Ricardo Carrillo Cruz (@rcarrillocruz)" -short_description: Manage static IP routes on Cisco IOS network devices -description: - - This module provides declarative management of static - IP routes on Cisco IOS network devices. -notes: - - Tested against IOS 15.6 -options: - prefix: - description: - - Network prefix of the static route. - mask: - description: - - Network prefix mask of the static route. - next_hop: - description: - - Next hop IP of the static route. - vrf: - description: - - VRF of the static route. - version_added: "2.8" - interface: - description: - - Interface of the static route. - version_added: "2.8" - name: - description: - - Name of the static route - aliases: ['description'] - version_added: "2.8" - admin_distance: - description: - - Admin distance of the static route. - tag: - description: - - Set tag of the static route. - version_added: "2.8" - track: - description: - - Tracked item to depend on for the static route. - version_added: "2.8" - aggregate: - description: List of static route definitions. - state: - description: - - State of the static route configuration. - default: present - choices: ['present', 'absent'] -extends_documentation_fragment: ios -""" - -EXAMPLES = """ -- name: configure static route - ios_static_route: - prefix: 192.168.2.0 - mask: 255.255.255.0 - next_hop: 10.0.0.1 - -- name: configure black hole in vrf blue depending on tracked item 10 - ios_static_route: - prefix: 192.168.2.0 - mask: 255.255.255.0 - vrf: blue - interface: null0 - track: 10 - -- name: configure ultimate route with name and tag - ios_static_route: - prefix: 192.168.2.0 - mask: 255.255.255.0 - interface: GigabitEthernet1 - name: hello world - tag: 100 - -- name: remove configuration - ios_static_route: - prefix: 192.168.2.0 - mask: 255.255.255.0 - next_hop: 10.0.0.1 - state: absent - -- name: Add static route aggregates - ios_static_route: - aggregate: - - { prefix: 172.16.32.0, mask: 255.255.255.0, next_hop: 10.0.0.8 } - - { prefix: 172.16.33.0, mask: 255.255.255.0, next_hop: 10.0.0.8 } - -- name: Remove static route aggregates - ios_static_route: - aggregate: - - { prefix: 172.16.32.0, mask: 255.255.255.0, next_hop: 10.0.0.8 } - - { prefix: 172.16.33.0, mask: 255.255.255.0, next_hop: 10.0.0.8 } - state: absent -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always - type: list - sample: - - ip route 192.168.2.0 255.255.255.0 10.0.0.1 -""" -from copy import deepcopy -from re import findall - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import remove_default_spec, validate_ip_address -from ansible.module_utils.network.ios.ios import get_config, load_config -from ansible.module_utils.network.ios.ios import ios_argument_spec - - -def map_obj_to_commands(want, have): - commands = list() - - for w in want: - state = w['state'] - del w['state'] - # Try to match an existing config with the desired config - for h in have: - # To delete admin_distance param from have if not it want before comparing both fields - if not w.get('admin_distance') and h.get('admin_distance'): - del h['admin_distance'] - diff = list(set(w.items()) ^ set(h.items())) - if not diff: - break - # if route is present with name or name already starts with wanted name it will not change - elif len(diff) == 2 and diff[0][0] == diff[1][0] == 'name' and (not w['name'] or h['name'].startswith(w['name'])): - break - # If no matches found, clear `h` - else: - h = None - - command = 'ip route' - prefix = w['prefix'] - mask = w['mask'] - vrf = w.get('vrf') - if vrf: - command = ' '.join((command, 'vrf', vrf, prefix, mask)) - else: - command = ' '.join((command, prefix, mask)) - - for key in ['interface', 'next_hop', 'admin_distance', 'tag', 'name', 'track']: - if w.get(key): - if key == 'name' and len(w.get(key).split()) > 1: - command = ' '.join((command, key, '"%s"' % w.get(key))) # name with multiple words needs to be quoted - elif key in ('name', 'tag', 'track'): - command = ' '.join((command, key, w.get(key))) - else: - command = ' '.join((command, w.get(key))) - - if state == 'absent' and h: - commands.append('no %s' % command) - elif state == 'present' and not h: - commands.append(command) - - return commands - - -def map_config_to_obj(module): - obj = [] - - out = get_config(module, flags='| include ip route') - - for line in out.splitlines(): - splitted_line = findall(r'[^"\s]\S*|".+?"', line) # Split by whitespace but do not split quotes, needed for name parameter - - if splitted_line[2] == 'vrf': - route = {'vrf': splitted_line[3]} - del splitted_line[:4] # Removes the words ip route vrf vrf_name - else: - route = {} - del splitted_line[:2] # Removes the words ip route - - prefix = splitted_line[0] - mask = splitted_line[1] - route.update({'prefix': prefix, 'mask': mask, 'admin_distance': '1'}) - - next_word = None - for word in splitted_line[2:]: - if next_word: - route[next_word] = word.strip('"') # Remove quotes which is needed for name - next_word = None - elif validate_ip_address(word): - route.update(next_hop=word) - elif word.isdigit(): - route.update(admin_distance=word) - elif word in ('tag', 'name', 'track'): - next_word = word - else: - route.update(interface=word) - - obj.append(route) - - return obj - - -def map_params_to_obj(module, required_together=None): - keys = ['prefix', 'mask', 'state', 'next_hop', 'vrf', 'interface', 'name', 'admin_distance', 'track', 'tag'] - obj = [] - - aggregate = module.params.get('aggregate') - if aggregate: - for item in aggregate: - route = item.copy() - for key in keys: - if route.get(key) is None: - route[key] = module.params.get(key) - - route = dict((k, v) for k, v in route.items() if v is not None) - module._check_required_together(required_together, route) - obj.append(route) - else: - module._check_required_together(required_together, module.params) - route = dict() - for key in keys: - if module.params.get(key) is not None: - route[key] = module.params.get(key) - obj.append(route) - - return obj - - -def main(): - """ main entry point for module execution - """ - element_spec = dict( - prefix=dict(type='str'), - mask=dict(type='str'), - next_hop=dict(type='str'), - vrf=dict(type='str'), - interface=dict(type='str'), - name=dict(type='str', aliases=['description']), - admin_distance=dict(type='str'), - track=dict(type='str'), - tag=dict(type='str'), - state=dict(default='present', choices=['present', 'absent']) - ) - - aggregate_spec = deepcopy(element_spec) - aggregate_spec['prefix'] = dict(required=True) - - # remove default in aggregate spec, to handle common arguments - remove_default_spec(aggregate_spec) - - argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec), - ) - - argument_spec.update(element_spec) - argument_spec.update(ios_argument_spec) - - required_one_of = [['aggregate', 'prefix']] - required_together = [['prefix', 'mask']] - mutually_exclusive = [['aggregate', 'prefix']] - - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) - - warnings = list() - - result = {'changed': False} - if warnings: - result['warnings'] = warnings - want = map_params_to_obj(module, required_together=required_together) - have = map_config_to_obj(module) - - commands = map_obj_to_commands(want, have) - result['commands'] = commands - - if commands: - if not module.check_mode: - load_config(module, commands) - - result['changed'] = True - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_static_routes.py b/lib/ansible/modules/network/ios/ios_static_routes.py deleted file mode 100644 index dc76d04ffe..0000000000 --- a/lib/ansible/modules/network/ios/ios_static_routes.py +++ /dev/null @@ -1,710 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The module file for ios_static_routes -""" - - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - -DOCUMENTATION = """ ---- -module: ios_static_routes -version_added: "2.10" -short_description: Configure and manage static routes on IOS devices. -description: This module configures and manages the static routes on IOS platforms. -author: Sumit Jaiswal (@justjais) -notes: -- Tested against Cisco IOSv Version 15.2 on VIRL -- This module works with connection C(network_cli). - See L(IOS Platform Options,../network/user_guide/platform_ios.html). -options: - config: - description: A dictionary of static route options - type: list - elements: dict - suboptions: - vrf: - description: - - IP VPN Routing/Forwarding instance name. - - NOTE, In case of IPV4/IPV6 VRF routing table should pre-exist before - configuring. - - NOTE, if the vrf information is not provided then the routes shall be - configured under global vrf. - type: str - address_families: - elements: dict - description: - - Address family to use for the static routes - type: list - suboptions: - afi: - description: - - Top level address family indicator. - required: true - type: str - choices: - - ipv4 - - ipv6 - routes: - description: Configuring static route - type: list - elements: dict - suboptions: - dest: - description: Destination prefix with its subnet mask - type: str - required: true - topology: - description: - - Configure static route for a Topology Routing/Forwarding instance - - NOTE, VRF and Topology can be used together only with Multicast and - Topology should pre-exist before it can be used - type: str - next_hops: - description: - - next hop address or interface - type: list - elements: dict - suboptions: - forward_router_address: - description: Forwarding router's address - type: str - interface: - description: Interface for directly connected static routes - type: str - dhcp: - description: Default gateway obtained from DHCP - type: bool - distance_metric: - description: Distance metric for this route - type: int - global: - description: Next hop address is global - type: bool - name: - description: Specify name of the next hop - type: str - multicast: - description: multicast route - type: bool - permanent: - description: permanent route - type: bool - tag: - description: - - Set tag for this route - - Refer to vendor documentation for valid values. - type: int - track: - description: - - Install route depending on tracked item with tracked object number. - - Tracking does not support multicast - - Refer to vendor documentation for valid values. - type: int - running_config: - description: - - The module, by default, will connect to the remote device and - retrieve the current running-config to use as a base for comparing - against the contents of source. There are times when it is not - desirable to have the task get the current running-config for - every task in a playbook. The I(running_config) argument allows the - implementer to pass in the configuration to use as the base - config for comparison. This value of this option should be the - output received from device by executing command - C(show configuration commands | grep 'static route') - type: str - state: - description: - - The state the configuration should be left in - - The states I(rendered), I(gathered) and I(parsed) does not perform any change on the - device. - - The state I(rendered) will transform the configuration in C(config) option to platform - specific CLI commands which will be returned in the I(rendered) key within the result. - For state I(rendered) active connection to remote host is not required. - - The state I(gathered) will fetch the running configuration from device and transform - it into structured data in the format as per the resource module argspec and the - value is returned in the I(gathered) key within the result. - - The state I(parsed) reads the configuration from C(running_config) option and transforms - it into JSON format as per the resource module parameters and the value is returned in - the I(parsed) key within the result. The value of C(running_config) option should be the - same format as the output of command I(show running-config | include ip route|ipv6 route) - executed on device. For state I(parsed) active connection to remote host is not required. - type: str - choices: - - merged - - replaced - - overridden - - deleted - - gathered - - rendered - - parsed - default: merged -""" - -EXAMPLES = """ ---- - -# Using merged - -# Before state: -# ------------- -# -# vios#show running-config | include ip route|ipv6 route - -- name: Merge provided configuration with device configuration - ios_static_routes: - config: - - vrf: blue - address_families: - - afi: ipv4 - routes: - - dest: 192.0.2.0/24 - next_hops: - - forward_router_address: 192.0.2.1 - name: merged_blue - tag: 50 - track: 150 - - address_families: - - afi: ipv4 - routes: - - dest: 198.51.100.0/24 - next_hops: - - forward_router_address: 198.51.101.1 - name: merged_route_1 - distance_metric: 110 - tag: 40 - multicast: True - - forward_router_address: 198.51.101.2 - name: merged_route_2 - distance_metric: 30 - - forward_router_address: 198.51.101.3 - name: merged_route_3 - - afi: ipv6 - routes: - - dest: 2001:DB8:0:3::/64 - next_hops: - - forward_router_address: 2001:DB8:0:3::2 - name: merged_v6 - tag: 105 - state: merged - -# Commands fired: -# --------------- -# ip route vrf blue 192.0.2.0 255.255.255.0 10.0.0.8 name merged_blue track 150 tag 50 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name merged_route_1 tag 40 -# ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name merged_route_2 -# ip route 198.51.100.0 255.255.255.0 198.51.101.3 name merged_route_3 -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 name merged_v6 tag 105 - -# After state: -# ------------ -# -# vios#show running-config | include ip route|ipv6 route -# ip route vrf blue 192.0.2.0 255.255.255.0 192.0.2.1 tag 50 name merged_blue track 150 -# ip route 198.51.100.0 255.255.255.0 198.51.101.3 name merged_route_3 -# ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name merged_route_2 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 tag 40 name merged_route_1 multicast -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 tag 105 name merged_v6 - -# Using replaced - -# Before state: -# ------------- -# -# vios#show running-config | include ip route|ipv6 route -# ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 name test_vrf track 150 tag 50 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name route_1 tag 40 -# ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 name test_v6 tag 105 - -- name: Replace provided configuration with device configuration - ios_static_routes: - config: - - address_families: - - afi: ipv4 - routes: - - dest: 198.51.100.0/24 - next_hops: - - forward_router_address: 198.51.101.1 - name: replaced_route - distance_metric: 175 - tag: 70 - multicast: True - state: replaced - -# Commands fired: -# --------------- -# no ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name route_1 tag 40 -# no ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# no ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 175 name replaced_route track 150 tag 70 - -# After state: -# ------------ -# -# vios#show running-config | include ip route|ipv6 route -# ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 name test_vrf track 150 tag 50 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 175 name replaced_route track 150 tag 70 -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 tag 105 name test_v6 - -# Using overridden - -# Before state: -# ------------- -# -# vios#show running-config | include ip route|ipv6 route -# ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 name test_vrf track 150 tag 50 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name route_1 tag 40 -# ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 name test_v6 tag 105 - -- name: Override provided configuration with device configuration - ios_static_routes: - config: - - vrf: blue - address_families: - - afi: ipv4 - routes: - - dest: 192.0.2.0/24 - next_hops: - - forward_router_address: 192.0.2.1 - name: override_vrf - tag: 50 - track: 150 - state: overridden - -# Commands fired: -# --------------- -# no ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name route_1 tag 40 -# no ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# no ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# no ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 198.51.101.8 name test_vrf track 150 tag 50 -# no ipv6 route FD5D:12C9:2201:1::/64 FD5D:12C9:2202::2 name test_v6 tag 105 -# ip route vrf blue 192.0.2.0 255.255.255.0 198.51.101.4 name override_vrf track 150 tag 50 - -# After state: -# ------------ -# -# vios#show running-config | include ip route|ipv6 route -# ip route vrf blue 192.0.2.0 255.255.255.0 192.0.2.1 tag 50 name override_vrf track 150 - -# Using Deleted - -# Example 1: -# ---------- -# To delete the exact static routes, with all the static routes explicitly mentioned in want - -# Before state: -# ------------- -# -# vios#show running-config | include ip route|ipv6 route -# ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 name test_vrf track 150 tag 50 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name route_1 tag 40 -# ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 name test_v6 tag 105 - -- name: Delete provided configuration from the device configuration - ios_static_routes: - config: - - vrf: ansible_temp_vrf - address_families: - - afi: ipv4 - routes: - - dest: 192.0.2.0/24 - next_hops: - - forward_router_address: 192.0.2.1 - name: test_vrf - tag: 50 - track: 150 - - address_families: - - afi: ipv4 - routes: - - dest: 198.51.100.0/24 - next_hops: - - forward_router_address: 198.51.101.1 - name: route_1 - distance_metric: 110 - tag: 40 - multicast: True - - forward_router_address: 198.51.101.2 - name: route_2 - distance_metric: 30 - - forward_router_address: 198.51.101.3 - name: route_3 - - afi: ipv6 - routes: - - dest: 2001:DB8:0:3::/64 - next_hops: - - forward_router_address: 2001:DB8:0:3::2 - name: test_v6 - tag: 105 - state: deleted - -# Commands fired: -# --------------- -# no ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 198.51.101.8 name test_vrf track 150 tag 50 -# no ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name route_1 tag 40 -# no ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# no ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# no ipv6 route FD5D:12C9:2201:1::/64 FD5D:12C9:2202::2 name test_v6 tag 105 - -# After state: -# ------------ -# -# vios#show running-config | include ip route|ipv6 route - -# Example 2: -# ---------- -# To delete the destination specific static routes - -# Before state: -# ------------- -# -# vios#show running-config | include ip route|ipv6 route -# ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 name test_vrf track 150 tag 50 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name route_1 tag 40 -# ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 name test_v6 tag 105 - -- name: Delete provided configuration from the device configuration - ios_static_routes: - config: - - address_families: - - afi: ipv4 - routes: - - dest: 198.51.100.0/24 - state: deleted - -# Commands fired: -# --------------- -# no ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# no ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# no ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 tag 40 name route_1 multicast - -# After state: -# ------------ -# -# vios#show running-config | include ip route|ipv6 route -# ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 tag 50 name test_vrf track 150 -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 tag 105 name test_v6 - - -# Example 3: -# ---------- -# To delete the vrf specific static routes - -# Before state: -# ------------- -# -# vios#show running-config | include ip route|ipv6 route -# ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 name test_vrf track 150 tag 50 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name route_1 tag 40 -# ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 name test_v6 tag 105 - -- name: Delete provided configuration from the device configuration - ios_static_routes: - config: - - vrf: ansible_temp_vrf - state: deleted - -# Commands fired: -# --------------- -# no ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 name test_vrf track 150 tag 50 - -# After state: -# ------------ -# -# vios#show running-config | include ip route|ipv6 route -# ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 tag 40 name route_1 multicast -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 tag 105 name test_v6 - -# Using Deleted without any config passed -#"(NOTE: This will delete all of configured resource module attributes from each configured interface)" - -# Before state: -# ------------- -# -# vios#show running-config | include ip route|ipv6 route -# ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 name test_vrf track 150 tag 50 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name route_1 tag 40 -# ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 name test_v6 tag 105 - -- name: Delete ALL configured IOS static routes - ios_static_routes: - state: deleted - -# Commands fired: -# --------------- -# no ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 tag 50 name test_vrf track 150 -# no ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# no ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# no ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 tag 40 name route_1 multicast -# no ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 tag 105 name test_v6 - -# After state: -# ------------- -# -# vios#show running-config | include ip route|ipv6 route -# - -# Using gathered - -# Before state: -# ------------- -# -# vios#show running-config | include ip route|ipv6 route -# ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 name test_vrf track 150 tag 50 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name route_1 tag 40 -# ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 name test_v6 tag 105 - -- name: Gather listed static routes with provided configurations - ios_static_routes: - config: - state: gathered - -# Module Execution Result: -# ------------------------ -# -# "gathered": [ -# { -# "address_families": [ -# { -# "afi": "ipv4", -# "routes": [ -# { -# "dest": "192.0.2.0/24", -# "next_hops": [ -# { -# "forward_router_address": "192.0.2.1", -# "name": "test_vrf", -# "tag": 50, -# "track": 150 -# } -# ] -# } -# ] -# } -# ], -# "vrf": "ansible_temp_vrf" -# }, -# { -# "address_families": [ -# { -# "afi": "ipv6", -# "routes": [ -# { -# "dest": "2001:DB8:0:3::/64", -# "next_hops": [ -# { -# "forward_router_address": "2001:DB8:0:3::2", -# "name": "test_v6", -# "tag": 105 -# } -# ] -# } -# ] -# }, -# { -# "afi": "ipv4", -# "routes": [ -# { -# "dest": "198.51.100.0/24", -# "next_hops": [ -# { -# "distance_metric": 110, -# "forward_router_address": "198.51.101.1", -# "multicast": true, -# "name": "route_1", -# "tag": 40 -# }, -# { -# "distance_metric": 30, -# "forward_router_address": "198.51.101.2", -# "name": "route_2" -# }, -# { -# "forward_router_address": "198.51.101.3", -# "name": "route_3" -# } -# ] -# } -# ] -# } -# ] -# } -# ] - -# After state: -# ------------ -# -# vios#show running-config | include ip route|ipv6 route -# ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 name test_vrf track 150 tag 50 -# ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name route_1 tag 40 -# ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2 -# ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3 -# ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 name test_v6 tag 105 - -# Using rendered - -- name: Render the commands for provided configuration - ios_static_routes: - config: - - vrf: ansible_temp_vrf - address_families: - - afi: ipv4 - routes: - - dest: 192.0.2.0/24 - next_hops: - - forward_router_address: 192.0.2.1 - name: test_vrf - tag: 50 - track: 150 - - address_families: - - afi: ipv4 - routes: - - dest: 198.51.100.0/24 - next_hops: - - forward_router_address: 198.51.101.1 - name: route_1 - distance_metric: 110 - tag: 40 - multicast: True - - forward_router_address: 198.51.101.2 - name: route_2 - distance_metric: 30 - - forward_router_address: 198.51.101.3 - name: route_3 - - afi: ipv6 - routes: - - dest: 2001:DB8:0:3::/64 - next_hops: - - forward_router_address: 2001:DB8:0:3::2 - name: test_v6 - tag: 105 - state: rendered - -# Module Execution Result: -# ------------------------ -# -# "rendered": [ -# "ip route vrf ansible_temp_vrf 192.0.2.0 255.255.255.0 192.0.2.1 name test_vrf track 150 tag 50", -# "ip route 198.51.100.0 255.255.255.0 198.51.101.1 110 multicast name route_1 tag 40", -# "ip route 198.51.100.0 255.255.255.0 198.51.101.2 30 name route_2", -# "ip route 198.51.100.0 255.255.255.0 198.51.101.3 name route_3", -# "ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::2 name test_v6 tag 105" -# ] - -""" - -RETURN = """ -before: - description: The configuration as structured data prior to module invocation. - returned: always - type: list - sample: The configuration returned will always be in the same format of the parameters above. -after: - description: The configuration as structured data after module completion. - returned: when changed - type: list - sample: The configuration returned will always be in the same format of the parameters above. -commands: - description: The set of commands pushed to the remote device - returned: always - type: list - sample: ['ip route vrf test 172.31.10.0 255.255.255.0 10.10.10.2 name new_test multicast'] -rendered: - description: The set of CLI commands generated from the value in C(config) option - returned: When C(state) is I(rendered) - type: list - sample: ['interface Ethernet1/1', 'mtu 1800'] -gathered: - description: - - The configuration as structured data transformed for the running configuration - fetched from remote host - returned: When C(state) is I(gathered) - type: list - sample: > - The configuration returned will always be in the same format - of the parameters above. -parsed: - description: - - The configuration as structured data transformed for the value of - C(running_config) option - returned: When C(state) is I(parsed) - type: list - sample: > - The configuration returned will always be in the same format - of the parameters above. -""" - - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.static_routes.static_routes import Static_RoutesArgs -from ansible.module_utils.network.ios.config.static_routes.static_routes import Static_Routes - - -def main(): - """ - Main entry point for module execution - - :returns: the result form module invocation - """ - required_if = [('state', 'merged', ('config',)), - ('state', 'replaced', ('config',)), - ('state', 'overridden', ('config',)), - ('state', 'rendered', ('config',)), - ('state', 'parsed', ('running_config',))] - mutually_exclusive = [('config', 'running_config')] - - module = AnsibleModule(argument_spec=Static_RoutesArgs.argument_spec, - required_if=required_if, - supports_check_mode=True, - mutually_exclusive=mutually_exclusive) - - result = Static_Routes(module).execute_module() - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_system.py b/lib/ansible/modules/network/ios/ios_system.py deleted file mode 100644 index cb1d7824c6..0000000000 --- a/lib/ansible/modules/network/ios/ios_system.py +++ /dev/null @@ -1,380 +0,0 @@ -#!/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 <http://www.gnu.org/licenses/>. -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_system -version_added: "2.3" -author: "Peter Sprygada (@privateip)" -short_description: Manage the system attributes on Cisco IOS devices -description: - - This module provides declarative management of node system attributes - on Cisco IOS devices. It provides an option to configure host system - parameters or remove those parameters from the device active - configuration. -extends_documentation_fragment: ios -notes: - - Tested against IOS 15.6 -options: - hostname: - description: - - Configure the device hostname parameter. This option takes an ASCII string value. - domain_name: - description: - - Configure the IP domain name - on the remote device to the provided value. Value - should be in the dotted name form and will be - appended to the C(hostname) to create a fully-qualified - domain name. - domain_search: - description: - - Provides the list of domain suffixes to - append to the hostname for the purpose of doing name resolution. - This argument accepts a list of names and will be reconciled - with the current active configuration on the running node. - lookup_source: - description: - - Provides one or more source - interfaces to use for performing DNS lookups. The interface - provided in C(lookup_source) must be a valid interface configured - on the device. - lookup_enabled: - description: - - Administrative control - for enabling or disabling DNS lookups. When this argument is - set to True, lookups are performed and when it is set to False, - lookups are not performed. - type: bool - name_servers: - description: - - List of DNS name servers by IP address to use to perform name resolution - lookups. This argument accepts either a list of DNS servers See - examples. - state: - description: - - State of the configuration - values in the device's current active configuration. When set - to I(present), the values should be configured in the device active - configuration and when set to I(absent) the values should not be - in the device active configuration - default: present - choices: ['present', 'absent'] -""" - -EXAMPLES = """ -- name: configure hostname and domain name - ios_system: - hostname: ios01 - domain_name: test.example.com - domain_search: - - ansible.com - - redhat.com - - cisco.com - -- name: remove configuration - ios_system: - state: absent - -- name: configure DNS lookup sources - ios_system: - lookup_source: MgmtEth0/0/CPU0/0 - lookup_enabled: yes - -- name: configure name servers - ios_system: - name_servers: - - 8.8.8.8 - - 8.8.4.4 -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always - type: list - sample: - - hostname ios01 - - ip domain name test.example.com -""" -import re - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.ios import get_config, load_config -from ansible.module_utils.network.ios.ios import ios_argument_spec -from ansible.module_utils.network.common.utils import ComplexList - -_CONFIGURED_VRFS = None - - -def has_vrf(module, vrf): - global _CONFIGURED_VRFS - if _CONFIGURED_VRFS is not None: - return vrf in _CONFIGURED_VRFS - config = get_config(module) - _CONFIGURED_VRFS = re.findall(r'vrf definition (\S+)', config) - return vrf in _CONFIGURED_VRFS - - -def requires_vrf(module, vrf): - if not has_vrf(module, vrf): - module.fail_json(msg='vrf %s is not configured' % vrf) - - -def diff_list(want, have): - adds = [w for w in want if w not in have] - removes = [h for h in have if h not in want] - return (adds, removes) - - -def map_obj_to_commands(want, have, module): - commands = list() - state = module.params['state'] - - def needs_update(x): - return want.get(x) is not None and (want.get(x) != have.get(x)) - - if state == 'absent': - if have['hostname'] != 'Router': - commands.append('no hostname') - - if have['lookup_source']: - commands.append('no ip domain lookup source-interface %s' % have['lookup_source']) - - if have['lookup_enabled'] is False: - commands.append('ip domain lookup') - - vrfs = set() - for item in have['domain_name']: - if item['vrf'] and item['vrf'] not in vrfs: - vrfs.add(item['vrf']) - commands.append('no ip domain name vrf %s' % item['vrf']) - elif None not in vrfs: - vrfs.add(None) - commands.append('no ip domain name') - - vrfs = set() - for item in have['domain_search']: - if item['vrf'] and item['vrf'] not in vrfs: - vrfs.add(item['vrf']) - commands.append('no ip domain list vrf %s' % item['vrf']) - elif None not in vrfs: - vrfs.add(None) - commands.append('no ip domain list') - - vrfs = set() - for item in have['name_servers']: - if item['vrf'] and item['vrf'] not in vrfs: - vrfs.add(item['vrf']) - commands.append('no ip name-server vrf %s' % item['vrf']) - elif None not in vrfs: - vrfs.add(None) - commands.append('no ip name-server') - - elif state == 'present': - if needs_update('hostname'): - commands.append('hostname %s' % want['hostname']) - - if needs_update('lookup_source'): - commands.append('ip domain lookup source-interface %s' % want['lookup_source']) - - if needs_update('lookup_enabled'): - cmd = 'ip domain lookup' - if want['lookup_enabled'] is False: - cmd = 'no %s' % cmd - commands.append(cmd) - - if want['domain_name']: - adds, removes = diff_list(want['domain_name'], have['domain_name']) - for item in removes: - if item['vrf']: - commands.append('no ip domain name vrf %s %s' % (item['vrf'], item['name'])) - else: - commands.append('no ip domain name %s' % item['name']) - for item in adds: - if item['vrf']: - requires_vrf(module, item['vrf']) - commands.append('ip domain name vrf %s %s' % (item['vrf'], item['name'])) - else: - commands.append('ip domain name %s' % item['name']) - - if want['domain_search']: - adds, removes = diff_list(want['domain_search'], have['domain_search']) - for item in removes: - if item['vrf']: - commands.append('no ip domain list vrf %s %s' % (item['vrf'], item['name'])) - else: - commands.append('no ip domain list %s' % item['name']) - for item in adds: - if item['vrf']: - requires_vrf(module, item['vrf']) - commands.append('ip domain list vrf %s %s' % (item['vrf'], item['name'])) - else: - commands.append('ip domain list %s' % item['name']) - - if want['name_servers']: - adds, removes = diff_list(want['name_servers'], have['name_servers']) - for item in removes: - if item['vrf']: - commands.append('no ip name-server vrf %s %s' % (item['vrf'], item['server'])) - else: - commands.append('no ip name-server %s' % item['server']) - for item in adds: - if item['vrf']: - requires_vrf(module, item['vrf']) - commands.append('ip name-server vrf %s %s' % (item['vrf'], item['server'])) - else: - commands.append('ip name-server %s' % item['server']) - - return commands - - -def parse_hostname(config): - match = re.search(r'^hostname (\S+)', config, re.M) - return match.group(1) - - -def parse_domain_name(config): - match = re.findall(r'^ip domain[- ]name (?:vrf (\S+) )*(\S+)', config, re.M) - matches = list() - for vrf, name in match: - if not vrf: - vrf = None - matches.append({'name': name, 'vrf': vrf}) - return matches - - -def parse_domain_search(config): - match = re.findall(r'^ip domain[- ]list (?:vrf (\S+) )*(\S+)', config, re.M) - matches = list() - for vrf, name in match: - if not vrf: - vrf = None - matches.append({'name': name, 'vrf': vrf}) - return matches - - -def parse_name_servers(config): - match = re.findall(r'^ip name-server (?:vrf (\S+) )*(.*)', config, re.M) - matches = list() - for vrf, servers in match: - if not vrf: - vrf = None - for server in servers.split(): - matches.append({'server': server, 'vrf': vrf}) - return matches - - -def parse_lookup_source(config): - match = re.search(r'ip domain[- ]lookup source-interface (\S+)', config, re.M) - if match: - return match.group(1) - - -def map_config_to_obj(module): - config = get_config(module) - return { - 'hostname': parse_hostname(config), - 'domain_name': parse_domain_name(config), - 'domain_search': parse_domain_search(config), - 'lookup_source': parse_lookup_source(config), - 'lookup_enabled': 'no ip domain lookup' not in config and 'no ip domain-lookup' not in config, - 'name_servers': parse_name_servers(config) - } - - -def map_params_to_obj(module): - obj = { - 'hostname': module.params['hostname'], - 'lookup_source': module.params['lookup_source'], - 'lookup_enabled': module.params['lookup_enabled'], - } - - domain_name = ComplexList(dict( - name=dict(key=True), - vrf=dict() - ), module) - - domain_search = ComplexList(dict( - name=dict(key=True), - vrf=dict() - ), module) - - name_servers = ComplexList(dict( - server=dict(key=True), - vrf=dict() - ), module) - - for arg, cast in [('domain_name', domain_name), - ('domain_search', domain_search), - ('name_servers', name_servers)]: - - if module.params[arg]: - obj[arg] = cast(module.params[arg]) - else: - obj[arg] = None - - return obj - - -def main(): - """ Main entry point for Ansible module execution - """ - argument_spec = dict( - hostname=dict(), - - domain_name=dict(type='list'), - domain_search=dict(type='list'), - name_servers=dict(type='list'), - - lookup_source=dict(), - lookup_enabled=dict(type='bool'), - - state=dict(choices=['present', 'absent'], default='present') - ) - - argument_spec.update(ios_argument_spec) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - result = {'changed': False} - - warnings = list() - result['warnings'] = warnings - - want = map_params_to_obj(module) - have = map_config_to_obj(module) - - commands = map_obj_to_commands(want, have, module) - result['commands'] = commands - - if commands: - if not module.check_mode: - load_config(module, commands) - result['changed'] = True - - module.exit_json(**result) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/network/ios/ios_user.py b/lib/ansible/modules/network/ios/ios_user.py deleted file mode 100644 index 37afe741dd..0000000000 --- a/lib/ansible/modules/network/ios/ios_user.py +++ /dev/null @@ -1,533 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# -# This file is part of Ansible by Red Hat -# -# 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 <http://www.gnu.org/licenses/>. -# - -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - -DOCUMENTATION = """ ---- -module: ios_user -version_added: "2.4" -author: "Trishna Guha (@trishnaguha)" -short_description: Manage the aggregate of local users on Cisco IOS device -description: - - This module provides declarative management of the local usernames - configured on network devices. It allows playbooks to manage - either individual usernames or the aggregate of usernames in the - current running config. It also supports purging usernames from the - configuration that are not explicitly defined. -notes: - - Tested against IOS 15.6 -options: - aggregate: - description: - - The set of username objects to be configured on the remote - Cisco IOS device. The list entries can either be the username - or a hash of username and properties. This argument is mutually - exclusive with the C(name) argument. - aliases: ['users', 'collection'] - name: - description: - - The username to be configured on the Cisco IOS device. - This argument accepts a string value and is mutually exclusive - with the C(aggregate) argument. - Please note that this option is not same as C(provider username). - configured_password: - description: - - The password to be configured on the Cisco IOS device. The - password needs to be provided in clear and it will be encrypted - on the device. - Please note that this option is not same as C(provider password). - update_password: - description: - - Since passwords are encrypted in the device running config, this - argument will instruct the module when to change the password. When - set to C(always), the password will always be updated in the device - and when set to C(on_create) the password will be updated only if - the username is created. - default: always - choices: ['on_create', 'always'] - password_type: - description: - - This argument determines whether a 'password' or 'secret' will be - configured. - default: secret - choices: ['secret', 'password'] - version_added: "2.8" - hashed_password: - description: - - This option allows configuring hashed passwords on Cisco IOS devices. - suboptions: - type: - description: - - Specifies the type of hash (e.g., 5 for MD5, 8 for PBKDF2, etc.) - - For this to work, the device needs to support the desired hash type - type: int - required: True - value: - description: - - The actual hashed password to be configured on the device - required: True - version_added: "2.8" - privilege: - description: - - The C(privilege) argument configures the privilege level of the - user when logged into the system. This argument accepts integer - values in the range of 1 to 15. - view: - description: - - Configures the view for the username in the - device running configuration. The argument accepts a string value - defining the view name. This argument does not check if the view - has been configured on the device. - aliases: ['role'] - sshkey: - description: - - Specifies one or more SSH public key(s) to configure - for the given username. - - This argument accepts a valid SSH key value. - version_added: "2.7" - nopassword: - description: - - Defines the username without assigning - a password. This will allow the user to login to the system - without being authenticated by a password. - type: bool - purge: - description: - - Instructs the module to consider the - resource definition absolute. It will remove any previously - configured usernames on the device with the exception of the - `admin` user (the current defined set of users). - type: bool - default: false - state: - description: - - Configures the state of the username definition - as it relates to the device operational configuration. When set - to I(present), the username(s) should be configured in the device active - configuration and when set to I(absent) the username(s) should not be - in the device active configuration - default: present - choices: ['present', 'absent'] -extends_documentation_fragment: ios -""" - -EXAMPLES = """ -- name: create a new user - ios_user: - name: ansible - nopassword: True - sshkey: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" - state: present - -- name: create a new user with multiple keys - ios_user: - name: ansible - sshkey: - - "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" - - "{{ lookup('file', '~/path/to/public_key') }}" - state: present - -- name: remove all users except admin - ios_user: - purge: yes - -- name: remove all users except admin and these listed users - ios_user: - aggregate: - - name: testuser1 - - name: testuser2 - - name: testuser3 - purge: yes - -- name: set multiple users to privilege level 15 - ios_user: - aggregate: - - name: netop - - name: netend - privilege: 15 - state: present - -- name: set user view/role - ios_user: - name: netop - view: network-operator - state: present - -- name: Change Password for User netop - ios_user: - name: netop - configured_password: "{{ new_password }}" - update_password: always - state: present - -- name: Aggregate of users - ios_user: - aggregate: - - name: ansibletest2 - - name: ansibletest3 - view: network-admin - -- name: Add a user specifying password type - ios_user: - name: ansibletest4 - configured_password: "{{ new_password }}" - password_type: password - -- name: Add a user with MD5 hashed password - ios_user: - name: ansibletest5 - hashed_password: - type: 5 - value: $3$8JcDilcYgFZi.yz4ApaqkHG2.8/ - -- name: Delete users with aggregate - ios_user: - aggregate: - - name: ansibletest1 - - name: ansibletest2 - - name: ansibletest3 - state: absent -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always - type: list - sample: - - username ansible secret password - - username admin secret admin -""" -import base64 -import hashlib -import re -from copy import deepcopy -from functools import partial - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import remove_default_spec -from ansible.module_utils.network.ios.ios import get_config, load_config -from ansible.module_utils.network.ios.ios import ios_argument_spec -from ansible.module_utils.six import iteritems - - -def validate_privilege(value, module): - if value and not 1 <= value <= 15: - module.fail_json(msg='privilege must be between 1 and 15, got %s' % value) - - -def user_del_cmd(username): - return { - 'command': 'no username %s' % username, - 'prompt': 'This operation will remove all username related configurations with same name', - 'answer': 'y', - 'newline': False, - } - - -def sshkey_fingerprint(sshkey): - # IOS will accept a MD5 fingerprint of the public key - # and is easier to configure in a single line - # we calculate this fingerprint here - if not sshkey: - return None - if ' ' in sshkey: - # ssh-rsa AAA...== comment - keyparts = sshkey.split(' ') - keyparts[1] = hashlib.md5(base64.b64decode(keyparts[1])).hexdigest().upper() - return ' '.join(keyparts) - else: - # just the key, assume rsa type - return 'ssh-rsa %s' % hashlib.md5(base64.b64decode(sshkey)).hexdigest().upper() - - -def map_obj_to_commands(updates, module): - commands = list() - update_password = module.params['update_password'] - password_type = module.params['password_type'] - - def needs_update(want, have, x): - return want.get(x) and (want.get(x) != have.get(x)) - - def add(command, want, x): - command.append('username %s %s' % (want['name'], x)) - - def add_hashed_password(command, want, x): - command.append('username %s secret %s %s' % (want['name'], x.get('type'), - x.get('value'))) - - def add_ssh(command, want, x=None): - command.append('ip ssh pubkey-chain') - if x: - command.append('username %s' % want['name']) - for item in x: - command.append('key-hash %s' % item) - command.append('exit') - else: - command.append('no username %s' % want['name']) - command.append('exit') - - for update in updates: - want, have = update - - if want['state'] == 'absent': - if have['sshkey']: - add_ssh(commands, want) - else: - commands.append(user_del_cmd(want['name'])) - - if needs_update(want, have, 'view'): - add(commands, want, 'view %s' % want['view']) - - if needs_update(want, have, 'privilege'): - add(commands, want, 'privilege %s' % want['privilege']) - - if needs_update(want, have, 'sshkey'): - add_ssh(commands, want, want['sshkey']) - - if needs_update(want, have, 'configured_password'): - if update_password == 'always' or not have: - if have and password_type != have['password_type']: - module.fail_json(msg='Can not have both a user password and a user secret.' + - ' Please choose one or the other.') - add(commands, want, '%s %s' % (password_type, want['configured_password'])) - - if needs_update(want, have, 'hashed_password'): - add_hashed_password(commands, want, want['hashed_password']) - - if needs_update(want, have, 'nopassword'): - if want['nopassword']: - add(commands, want, 'nopassword') - else: - add(commands, want, user_del_cmd(want['name'])) - - return commands - - -def parse_view(data): - match = re.search(r'view (\S+)', data, re.M) - if match: - return match.group(1) - - -def parse_sshkey(data, user): - sshregex = r'username %s(\n\s+key-hash .+$)+' % user - sshcfg = re.search(sshregex, data, re.M) - key_list = [] - if sshcfg: - match = re.findall(r'key-hash (\S+ \S+(?: .+)?)$', sshcfg.group(), re.M) - if match: - key_list = match - return key_list - - -def parse_privilege(data): - match = re.search(r'privilege (\S+)', data, re.M) - if match: - return int(match.group(1)) - - -def parse_password_type(data): - type = None - if data and data.split()[-3] in ['password', 'secret']: - type = data.split()[-3] - return type - - -def map_config_to_obj(module): - data = get_config(module, flags=['| section username']) - - match = re.findall(r'(?:^(?:u|\s{2}u))sername (\S+)', data, re.M) - if not match: - return list() - - instances = list() - - for user in set(match): - regex = r'username %s .+$' % user - cfg = re.findall(regex, data, re.M) - cfg = '\n'.join(cfg) - obj = { - 'name': user, - 'state': 'present', - 'nopassword': 'nopassword' in cfg, - 'configured_password': None, - 'hashed_password': None, - 'password_type': parse_password_type(cfg), - 'sshkey': parse_sshkey(data, user), - 'privilege': parse_privilege(cfg), - 'view': parse_view(cfg) - } - instances.append(obj) - - return instances - - -def get_param_value(key, item, module): - # if key doesn't exist in the item, get it from module.params - if not item.get(key): - value = module.params[key] - - # if key does exist, do a type check on it to validate it - else: - value_type = module.argument_spec[key].get('type', 'str') - type_checker = module._CHECK_ARGUMENT_TYPES_DISPATCHER[value_type] - type_checker(item[key]) - value = item[key] - - # validate the param value (if validator func exists) - validator = globals().get('validate_%s' % key) - if all((value, validator)): - validator(value, module) - - return value - - -def map_params_to_obj(module): - users = module.params['aggregate'] - if not users: - if not module.params['name'] and module.params['purge']: - return list() - elif not module.params['name']: - module.fail_json(msg='username is required') - else: - aggregate = [{'name': module.params['name']}] - else: - aggregate = list() - for item in users: - if not isinstance(item, dict): - aggregate.append({'name': item}) - elif 'name' not in item: - module.fail_json(msg='name is required') - else: - aggregate.append(item) - - objects = list() - - for item in aggregate: - get_value = partial(get_param_value, item=item, module=module) - item['configured_password'] = get_value('configured_password') - item['hashed_password'] = get_value('hashed_password') - item['nopassword'] = get_value('nopassword') - item['privilege'] = get_value('privilege') - item['view'] = get_value('view') - item['sshkey'] = render_key_list(get_value('sshkey')) - item['state'] = get_value('state') - objects.append(item) - - return objects - - -def render_key_list(ssh_keys): - key_list = [] - if ssh_keys: - for item in ssh_keys: - key_list.append(sshkey_fingerprint(item)) - return key_list - - -def update_objects(want, have): - updates = list() - for entry in want: - item = next((i for i in have if i['name'] == entry['name']), None) - if all((item is None, entry['state'] == 'present')): - updates.append((entry, {})) - elif item: - for key, value in iteritems(entry): - if value and value != item[key]: - updates.append((entry, item)) - return updates - - -def main(): - """ main entry point for module execution - """ - hashed_password_spec = dict( - type=dict(type='int', required=True), - value=dict(no_log=True, required=True) - ) - - element_spec = dict( - name=dict(), - - configured_password=dict(no_log=True), - hashed_password=dict(no_log=True, type='dict', options=hashed_password_spec), - nopassword=dict(type='bool'), - update_password=dict(default='always', choices=['on_create', 'always']), - password_type=dict(default='secret', choices=['secret', 'password']), - - privilege=dict(type='int'), - view=dict(aliases=['role']), - - sshkey=dict(type='list'), - - state=dict(default='present', choices=['present', 'absent']) - ) - aggregate_spec = deepcopy(element_spec) - aggregate_spec['name'] = dict(required=True) - - # remove default in aggregate spec, to handle common arguments - remove_default_spec(aggregate_spec) - - argument_spec = dict( - aggregate=dict(type='list', elements='dict', options=aggregate_spec, aliases=['users', 'collection']), - purge=dict(type='bool', default=False) - ) - - argument_spec.update(element_spec) - argument_spec.update(ios_argument_spec) - - mutually_exclusive = [('name', 'aggregate'), ('nopassword', 'hashed_password', 'configured_password')] - - module = AnsibleModule(argument_spec=argument_spec, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) - - warnings = list() - result = {'changed': False, 'warnings': warnings} - - want = map_params_to_obj(module) - have = map_config_to_obj(module) - - commands = map_obj_to_commands(update_objects(want, have), module) - - if module.params['purge']: - want_users = [x['name'] for x in want] - have_users = [x['name'] for x in have] - for item in set(have_users).difference(want_users): - if item != 'admin': - commands.append(user_del_cmd(item)) - - result['commands'] = commands - - if commands: - if not module.check_mode: - load_config(module, commands) - result['changed'] = True - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_vlans.py b/lib/ansible/modules/network/ios/ios_vlans.py deleted file mode 100644 index 7de87dbb52..0000000000 --- a/lib/ansible/modules/network/ios/ios_vlans.py +++ /dev/null @@ -1,464 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The module file for ios_vlans -""" - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -ANSIBLE_METADATA = { - 'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network' -} - -DOCUMENTATION = """ -module: ios_vlans -version_added: 2.9 -short_description: Manage VLANs on Cisco IOS devices. -description: This module provides declarative management of VLANs on Cisco IOS network devices. -author: Sumit Jaiswal (@justjais) -notes: - - Tested against Cisco IOSv Version 15.2 on VIRL - - This module works with connection C(network_cli). - See L(IOS Platform Options,../network/user_guide/platform_ios.html). -options: - config: - description: A dictionary of VLANs options - type: list - elements: dict - suboptions: - name: - description: - - Ascii name of the VLAN. - - NOTE, I(name) should not be named/appended with I(default) as it is reserved for device default vlans. - type: str - vlan_id: - description: - - ID of the VLAN. Range 1-4094 - type: int - required: True - mtu: - description: - - VLAN Maximum Transmission Unit. - - Refer to vendor documentation for valid values. - type: int - state: - description: - - Operational state of the VLAN - type: str - choices: - - active - - suspend - remote_span: - description: - - Configure as Remote SPAN VLAN - type: bool - shutdown: - description: - - Shutdown VLAN switching. - type: str - choices: - - enabled - - disabled - state: - description: - - The state of the configuration after module completion - type: str - choices: - - merged - - replaced - - overridden - - deleted - default: merged -""" -EXAMPLES = """ ---- -# Using merged - -# Before state: -# ------------- -# -# vios#show vlan -# VLAN Name Status Ports -# ---- -------------------------------- --------- ------------------------------- -# 1 default active Gi0/1, Gi0/2 -# 1002 fddi-default act/unsup -# 1003 token-ring-default act/unsup -# 1004 fddinet-default act/unsup -# 1005 trnet-default act/unsup -# -# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 -# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ -# 1 enet 100001 1500 - - - - - 0 0 -# 1002 fddi 101002 1500 - - - - - 0 0 -# 1003 tr 101003 1500 - - - - - 0 0 -# 1004 fdnet 101004 1500 - - - ieee - 0 0 -# 1005 trnet 101005 1500 - - - ibm - 0 0 - -- name: Merge provided configuration with device configuration - ios_vlans: - config: - - name: Vlan_10 - vlan_id: 10 - state: active - shutdown: disabled - remote_span: 10 - - name: Vlan_20 - vlan_id: 20 - mtu: 610 - state: active - shutdown: enabled - - name: Vlan_30 - vlan_id: 30 - state: suspend - shutdown: enabled - state: merged - -# After state: -# ------------ -# -# vios#show vlan -# VLAN Name Status Ports -# ---- -------------------------------- --------- ------------------------------- -# 1 default active Gi0/1, Gi0/2 -# 10 vlan_10 active -# 20 vlan_20 act/lshut -# 30 vlan_30 sus/lshut -# 1002 fddi-default act/unsup -# 1003 token-ring-default act/unsup -# 1004 fddinet-default act/unsup -# 1005 trnet-default act/unsup -# -# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 -# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ -# 1 enet 100001 1500 - - - - - 0 0 -# 10 enet 100010 1500 - - - - - 0 0 -# 20 enet 100020 610 - - - - - 0 0 -# 30 enet 100030 1500 - - - - - 0 0 -# 1002 fddi 101002 1500 - - - - - 0 0 -# 1003 tr 101003 1500 - - - - - 0 0 -# 1004 fdnet 101004 1500 - - - ieee - 0 0 -# 1005 trnet 101005 1500 - - - ibm - 0 0 -# -# Remote SPAN VLANs -# ------------------------------------------------------------------------------ -# 10 - -# Using overridden - -# Before state: -# ------------- -# -# vios#show vlan -# VLAN Name Status Ports -# ---- -------------------------------- --------- ------------------------------- -# 1 default active Gi0/1, Gi0/2 -# 10 vlan_10 active -# 20 vlan_20 act/lshut -# 30 vlan_30 sus/lshut -# 1002 fddi-default act/unsup -# 1003 token-ring-default act/unsup -# 1004 fddinet-default act/unsup -# 1005 trnet-default act/unsup -# -# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 -# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ -# 1 enet 100001 1500 - - - - - 0 0 -# 10 enet 100010 1500 - - - - - 0 0 -# 20 enet 100020 610 - - - - - 0 0 -# 30 enet 100030 1500 - - - - - 0 0 -# 1002 fddi 101002 1500 - - - - - 0 0 -# 1003 tr 101003 1500 - - - - - 0 0 -# 1004 fdnet 101004 1500 - - - ieee - 0 0 -# 1005 trnet 101005 1500 - - - ibm - 0 0 -# -# Remote SPAN VLANs -# ------------------------------------------------------------------------------ -# 10 - -- name: Override device configuration of all VLANs with provided configuration - ios_vlans: - config: - - name: Vlan_10 - vlan_id: 10 - mtu: 1000 - state: overridden - -# After state: -# ------------ -# -# vios#show vlan -# VLAN Name Status Ports -# ---- -------------------------------- --------- ------------------------------- -# 10 Vlan_10 active -# -# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 -# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ -# 10 enet 100010 1000 - - - - - 0 0 - -# Using replaced - -# Before state: -# ------------- -# -# vios#show vlan -# VLAN Name Status Ports -# ---- -------------------------------- --------- ------------------------------- -# 1 default active Gi0/1, Gi0/2 -# 10 vlan_10 active -# 20 vlan_20 act/lshut -# 30 vlan_30 sus/lshut -# 1002 fddi-default act/unsup -# 1003 token-ring-default act/unsup -# 1004 fddinet-default act/unsup -# 1005 trnet-default act/unsup -# -# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 -# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ -# 1 enet 100001 1500 - - - - - 0 0 -# 10 enet 100010 1500 - - - - - 0 0 -# 20 enet 100020 610 - - - - - 0 0 -# 30 enet 100030 1500 - - - - - 0 0 -# 1002 fddi 101002 1500 - - - - - 0 0 -# 1003 tr 101003 1500 - - - - - 0 0 -# 1004 fdnet 101004 1500 - - - ieee - 0 0 -# 1005 trnet 101005 1500 - - - ibm - 0 0 -# -# Remote SPAN VLANs -# ------------------------------------------------------------------------------ -# 10 - -- name: Replaces device configuration of listed VLANs with provided configuration - ios_vlans: - config: - - vlan_id: 20 - name: Test_VLAN20 - mtu: 700 - shutdown: disabled - - vlan_id: 30 - name: Test_VLAN30 - mtu: 1000 - state: replaced - -# After state: -# ------------ -# -# vios#show vlan -# VLAN Name Status Ports -# ---- -------------------------------- --------- ------------------------------- -# 1 default active Gi0/1, Gi0/2 -# 10 vlan_10 active -# 20 Test_VLAN20 active -# 30 Test_VLAN30 sus/lshut -# 1002 fddi-default act/unsup -# 1003 token-ring-default act/unsup -# 1004 fddinet-default act/unsup -# 1005 trnet-default act/unsup -# -# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 -# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ -# 1 enet 100001 1500 - - - - - 0 0 -# 10 enet 100010 1500 - - - - - 0 0 -# 20 enet 100020 700 - - - - - 0 0 -# 30 enet 100030 1000 - - - - - 0 0 -# 1002 fddi 101002 1500 - - - - - 0 0 -# 1003 tr 101003 1500 - - - - - 0 0 -# 1004 fdnet 101004 1500 - - - ieee - 0 0 -# 1005 trnet 101005 1500 - - - ibm - 0 0 -# -# Remote SPAN VLANs -# ------------------------------------------------------------------------------ -# 10 - -# Using deleted - -# Before state: -# ------------- -# -# vios#show vlan -# VLAN Name Status Ports -# ---- -------------------------------- --------- ------------------------------- -# 1 default active Gi0/1, Gi0/2 -# 10 vlan_10 active -# 20 vlan_20 act/lshut -# 30 vlan_30 sus/lshut -# 1002 fddi-default act/unsup -# 1003 token-ring-default act/unsup -# 1004 fddinet-default act/unsup -# 1005 trnet-default act/unsup -# -# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 -# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ -# 1 enet 100001 1500 - - - - - 0 0 -# 10 enet 100010 1500 - - - - - 0 0 -# 20 enet 100020 610 - - - - - 0 0 -# 30 enet 100030 1500 - - - - - 0 0 -# 1002 fddi 101002 1500 - - - - - 0 0 -# 1003 tr 101003 1500 - - - - - 0 0 -# 1004 fdnet 101004 1500 - - - ieee - 0 0 -# 1005 trnet 101005 1500 - - - ibm - 0 0 -# -# Remote SPAN VLANs -# ------------------------------------------------------------------------------ -# 10 - -- name: Delete attributes of given VLANs - ios_vlans: - config: - - vlan_id: 10 - - vlan_id: 20 - state: deleted - -# After state: -# ------------- -# -# vios#show vlan -# VLAN Name Status Ports -# ---- -------------------------------- --------- ------------------------------- -# 1 default active Gi0/1, Gi0/2 -# 30 vlan_30 sus/lshut -# 1002 fddi-default act/unsup -# 1003 token-ring-default act/unsup -# 1004 fddinet-default act/unsup -# 1005 trnet-default act/unsup -# -# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 -# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ -# 1 enet 100001 1500 - - - - - 0 0 -# 30 enet 100030 1500 - - - - - 0 0 -# 1002 fddi 101002 1500 - - - - - 0 0 -# 1003 tr 101003 1500 - - - - - 0 0 -# 1004 fdnet 101004 1500 - - - ieee - 0 0 -# 1005 trnet 101005 1500 - - - ibm - 0 0 - -# Using Deleted without any config passed -#"(NOTE: This will delete all of configured vlans attributes)" - -# Before state: -# ------------- -# -# vios#show vlan -# VLAN Name Status Ports -# ---- -------------------------------- --------- ------------------------------- -# 1 default active Gi0/1, Gi0/2 -# 10 vlan_10 active -# 20 vlan_20 act/lshut -# 30 vlan_30 sus/lshut -# 1002 fddi-default act/unsup -# 1003 token-ring-default act/unsup -# 1004 fddinet-default act/unsup -# 1005 trnet-default act/unsup -# -# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 -# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ -# 1 enet 100001 1500 - - - - - 0 0 -# 10 enet 100010 1500 - - - - - 0 0 -# 20 enet 100020 610 - - - - - 0 0 -# 30 enet 100030 1500 - - - - - 0 0 -# 1002 fddi 101002 1500 - - - - - 0 0 -# 1003 tr 101003 1500 - - - - - 0 0 -# 1004 fdnet 101004 1500 - - - ieee - 0 0 -# 1005 trnet 101005 1500 - - - ibm - 0 0 -# -# Remote SPAN VLANs -# ------------------------------------------------------------------------------ -# 10 - -- name: Delete attributes of ALL VLANs - ios_vlans: - state: deleted - -# After state: -# ------------- -# -# vios#show vlan -# VLAN Name Status Ports -# ---- -------------------------------- --------- ------------------------------- -# 1 default active Gi0/1, Gi0/2 -# 1002 fddi-default act/unsup -# 1003 token-ring-default act/unsup -# 1004 fddinet-default act/unsup -# 1005 trnet-default act/unsup -# -# VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2 -# ---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------ -# 1 enet 100001 1500 - - - - - 0 0 -# 1002 fddi 101002 1500 - - - - - 0 0 -# 1003 tr 101003 1500 - - - - - 0 0 -# 1004 fdnet 101004 1500 - - - ieee - 0 0 -# 1005 trnet 101005 1500 - - - ibm - 0 0 - -""" -RETURN = """ -before: - description: The configuration as structured data prior to module invocation. - returned: always - type: list - sample: > - The configuration returned will always be in the same format - of the parameters above. -after: - description: The configuration as structured data after module completion. - returned: when changed - type: list - sample: > - The configuration returned will always be in the same format - of the parameters above. -commands: - description: The set of commands pushed to the remote device. - returned: always - type: list - sample: ['vlan 20', 'name vlan_20', 'mtu 600', 'remote-span'] -""" - - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.ios.argspec.vlans.vlans import VlansArgs -from ansible.module_utils.network.ios.config.vlans.vlans import Vlans - - -def main(): - """ - Main entry point for module execution - - :returns: the result form module invocation - """ - required_if = [('state', 'merged', ('config',)), - ('state', 'replaced', ('config',)), - ('state', 'overridden', ('config',))] - - module = AnsibleModule(argument_spec=VlansArgs.argument_spec, - required_if=required_if, - supports_check_mode=True) - - result = Vlans(module).execute_module() - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/network/ios/ios_vrf.py b/lib/ansible/modules/network/ios/ios_vrf.py deleted file mode 100644 index 1ac01e1339..0000000000 --- a/lib/ansible/modules/network/ios/ios_vrf.py +++ /dev/null @@ -1,719 +0,0 @@ -#!/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 <http://www.gnu.org/licenses/>. -# -ANSIBLE_METADATA = {'metadata_version': '1.1', - 'status': ['preview'], - 'supported_by': 'network'} - - -DOCUMENTATION = """ ---- -module: ios_vrf -version_added: "2.3" -author: "Peter Sprygada (@privateip)" -short_description: Manage the collection of VRF definitions on Cisco IOS devices -description: - - This module provides declarative management of VRF definitions on - Cisco IOS devices. It allows playbooks to manage individual or - the entire VRF collection. It also supports purging VRF definitions from - the configuration that are not explicitly defined. -extends_documentation_fragment: ios -notes: - - Tested against IOS 15.6 -options: - vrfs: - description: - - The set of VRF definition objects to be configured on the remote - IOS device. Ths list entries can either be the VRF name or a hash - of VRF definitions and attributes. This argument is mutually - exclusive with the C(name) argument. - name: - description: - - The name of the VRF definition to be managed on the remote IOS - device. The VRF definition name is an ASCII string name used - to uniquely identify the VRF. This argument is mutually exclusive - with the C(vrfs) argument - description: - description: - - Provides a short description of the VRF definition in the - current active configuration. The VRF definition value accepts - alphanumeric characters used to provide additional information - about the VRF. - rd: - description: - - The router-distinguisher value uniquely identifies the VRF to - routing processes on the remote IOS system. The RD value takes - the form of C(A:B) where C(A) and C(B) are both numeric values. - interfaces: - description: - - Identifies the set of interfaces that - should be configured in the VRF. Interfaces must be routed - interfaces in order to be placed into a VRF. - associated_interfaces: - description: - - This is a intent option and checks the operational state of the for given vrf C(name) - for associated interfaces. If the value in the C(associated_interfaces) does not match with - the operational state of vrf interfaces on device it will result in failure. - version_added: "2.5" - delay: - description: - - Time in seconds to wait before checking for the operational state on remote - device. - version_added: "2.4" - default: 10 - purge: - description: - - Instructs the module to consider the - VRF definition absolute. It will remove any previously configured - VRFs on the device. - default: false - type: bool - state: - description: - - Configures the state of the VRF definition - as it relates to the device operational configuration. When set - to I(present), the VRF should be configured in the device active - configuration and when set to I(absent) the VRF should not be - in the device active configuration - default: present - choices: ['present', 'absent'] - route_both: - description: - - Adds an export and import list of extended route target communities to the VRF. - version_added: "2.5" - route_export: - description: - - Adds an export list of extended route target communities to the VRF. - version_added: "2.5" - route_import: - description: - - Adds an import list of extended route target communities to the VRF. - version_added: "2.5" - route_both_ipv4: - description: - - Adds an export and import list of extended route target communities in address-family configuration submode to the VRF. - version_added: "2.7" - route_export_ipv4: - description: - - Adds an export list of extended route target communities in address-family configuration submode to the VRF. - version_added: "2.7" - route_import_ipv4: - description: - - Adds an import list of extended route target communities in address-family configuration submode to the VRF. - version_added: "2.7" - route_both_ipv6: - description: - - Adds an export and import list of extended route target communities in address-family configuration submode to the VRF. - version_added: "2.7" - route_export_ipv6: - description: - - Adds an export list of extended route target communities in address-family configuration submode to the VRF. - version_added: "2.7" - route_import_ipv6: - description: - - Adds an import list of extended route target communities in address-family configuration submode to the VRF. - version_added: "2.7" - -""" -EXAMPLES = """ -- name: configure a vrf named management - ios_vrf: - name: management - description: oob mgmt vrf - interfaces: - - Management1 - -- name: remove a vrf named test - ios_vrf: - name: test - state: absent - -- name: configure set of VRFs and purge any others - ios_vrf: - vrfs: - - red - - blue - - green - purge: yes - -- name: Creates a list of import RTs for the VRF with the same parameters - ios_vrf: - name: test_import - rd: 1:100 - route_import: - - 1:100 - - 3:100 - -- name: Creates a list of import RTs in address-family configuration submode for the VRF with the same parameters - ios_vrf: - name: test_import_ipv4 - rd: 1:100 - route_import_ipv4: - - 1:100 - - 3:100 - -- name: Creates a list of import RTs in address-family configuration submode for the VRF with the same parameters - ios_vrf: - name: test_import_ipv6 - rd: 1:100 - route_import_ipv6: - - 1:100 - - 3:100 - -- name: Creates a list of export RTs for the VRF with the same parameters - ios_vrf: - name: test_export - rd: 1:100 - route_export: - - 1:100 - - 3:100 - -- name: Creates a list of export RTs in address-family configuration submode for the VRF with the same parameters - ios_vrf: - name: test_export_ipv4 - rd: 1:100 - route_export_ipv4: - - 1:100 - - 3:100 - -- name: Creates a list of export RTs in address-family configuration submode for the VRF with the same parameters - ios_vrf: - name: test_export_ipv6 - rd: 1:100 - route_export_ipv6: - - 1:100 - - 3:100 - -- name: Creates a list of import and export route targets for the VRF with the same parameters - ios_vrf: - name: test_both - rd: 1:100 - route_both: - - 1:100 - - 3:100 - -- name: Creates a list of import and export route targets in address-family configuration submode for the VRF with the same parameters - ios_vrf: - name: test_both_ipv4 - rd: 1:100 - route_both_ipv4: - - 1:100 - - 3:100 - -- name: Creates a list of import and export route targets in address-family configuration submode for the VRF with the same parameters - ios_vrf: - name: test_both_ipv6 - rd: 1:100 - route_both_ipv6: - - 1:100 - - 3:100 - -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always - type: list - sample: - - vrf definition ansible - - description management vrf - - rd: 1:100 -start: - description: The time the job started - returned: always - type: str - sample: "2016-11-16 10:38:15.126146" -end: - description: The time the job ended - returned: always - type: str - sample: "2016-11-16 10:38:25.595612" -delta: - description: The time elapsed to perform all operations - returned: always - type: str - sample: "0:00:10.469466" -""" -import re -import time -from functools import partial - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.connection import exec_command -from ansible.module_utils.network.ios.ios import load_config, get_config -from ansible.module_utils.network.ios.ios import ios_argument_spec -from ansible.module_utils.network.common.config import NetworkConfig -from ansible.module_utils.six import iteritems - - -def get_interface_type(interface): - - if interface.upper().startswith('ET'): - return 'ethernet' - elif interface.upper().startswith('VL'): - return 'svi' - elif interface.upper().startswith('LO'): - return 'loopback' - elif interface.upper().startswith('MG'): - return 'management' - elif interface.upper().startswith('MA'): - return 'management' - elif interface.upper().startswith('PO'): - return 'portchannel' - elif interface.upper().startswith('NV'): - return 'nve' - else: - return 'unknown' - - -def add_command_to_vrf(name, cmd, commands): - if 'vrf definition %s' % name not in commands: - commands.extend(['vrf definition %s' % name]) - commands.append(cmd) - - -def map_obj_to_commands(updates, module): - commands = list() - - for update in updates: - want, have = update - - def needs_update(want, have, x): - if isinstance(want.get(x), list) and isinstance(have.get(x), list): - return want.get(x) and (want.get(x) != have.get(x)) and not all(elem in have.get(x) for elem in want.get(x)) - return want.get(x) and (want.get(x) != have.get(x)) - - if want['state'] == 'absent': - commands.append('no vrf definition %s' % want['name']) - continue - - if not have.get('state'): - commands.extend(['vrf definition %s' % want['name']]) - ipv6 = len([k for k, v in module.params.items() if (k.endswith('_ipv6') or k.endswith('_both')) and v]) != 0 - ipv4 = len([k for k, v in module.params.items() if (k.endswith('_ipv4') or k.endswith('_both')) and v]) != 0 - if ipv4: - commands.extend(['address-family ipv4', 'exit']) - if ipv6: - commands.extend(['address-family ipv6', 'exit']) - - if needs_update(want, have, 'description'): - cmd = 'description %s' % want['description'] - add_command_to_vrf(want['name'], cmd, commands) - - if needs_update(want, have, 'rd'): - cmd = 'rd %s' % want['rd'] - add_command_to_vrf(want['name'], cmd, commands) - - if needs_update(want, have, 'route_import'): - for route in want['route_import']: - cmd = 'route-target import %s' % route - add_command_to_vrf(want['name'], cmd, commands) - - if needs_update(want, have, 'route_export'): - for route in want['route_export']: - cmd = 'route-target export %s' % route - add_command_to_vrf(want['name'], cmd, commands) - - if needs_update(want, have, 'route_import_ipv4'): - cmd = 'address-family ipv4' - add_command_to_vrf(want['name'], cmd, commands) - for route in want['route_import_ipv4']: - cmd = 'route-target import %s' % route - add_command_to_vrf(want['name'], cmd, commands) - cmd = 'exit-address-family' - add_command_to_vrf(want['name'], cmd, commands) - - if needs_update(want, have, 'route_export_ipv4'): - cmd = 'address-family ipv4' - add_command_to_vrf(want['name'], cmd, commands) - for route in want['route_export_ipv4']: - cmd = 'route-target export %s' % route - add_command_to_vrf(want['name'], cmd, commands) - cmd = 'exit-address-family' - add_command_to_vrf(want['name'], cmd, commands) - - if needs_update(want, have, 'route_import_ipv6'): - cmd = 'address-family ipv6' - add_command_to_vrf(want['name'], cmd, commands) - for route in want['route_import_ipv6']: - cmd = 'route-target import %s' % route - add_command_to_vrf(want['name'], cmd, commands) - cmd = 'exit-address-family' - add_command_to_vrf(want['name'], cmd, commands) - - if needs_update(want, have, 'route_export_ipv6'): - cmd = 'address-family ipv6' - add_command_to_vrf(want['name'], cmd, commands) - for route in want['route_export_ipv6']: - cmd = 'route-target export %s' % route - add_command_to_vrf(want['name'], cmd, commands) - cmd = 'exit-address-family' - add_command_to_vrf(want['name'], cmd, commands) - - if want['interfaces'] is not None: - # handle the deletes - for intf in set(have.get('interfaces', [])).difference(want['interfaces']): - commands.extend(['interface %s' % intf, - 'no vrf forwarding %s' % want['name']]) - - # handle the adds - for intf in set(want['interfaces']).difference(have.get('interfaces', [])): - cfg = get_config(module) - configobj = NetworkConfig(indent=1, contents=cfg) - children = configobj['interface %s' % intf].children - intf_config = '\n'.join(children) - - commands.extend(['interface %s' % intf, - 'vrf forwarding %s' % want['name']]) - - match = re.search('ip address .+', intf_config, re.M) - if match: - commands.append(match.group()) - - return commands - - -def parse_description(configobj, name): - cfg = configobj['vrf definition %s' % name] - cfg = '\n'.join(cfg.children) - match = re.search(r'description (.+)$', cfg, re.M) - if match: - return match.group(1) - - -def parse_rd(configobj, name): - cfg = configobj['vrf definition %s' % name] - cfg = '\n'.join(cfg.children) - match = re.search(r'rd (.+)$', cfg, re.M) - if match: - return match.group(1) - - -def parse_interfaces(configobj): - vrf_cfg = 'vrf forwarding' - interfaces = dict() - for intf in set(re.findall('^interface .+', str(configobj), re.M)): - for line in configobj[intf].children: - if vrf_cfg in line: - try: - interfaces[line.split()[-1]].append(intf.split(' ')[1]) - except KeyError: - interfaces[line.split()[-1]] = [intf.split(' ')[1]] - return interfaces - - -def parse_import(configobj, name): - cfg = configobj['vrf definition %s' % name] - cfg = '\n'.join(cfg.children) - matches = re.findall(r'route-target\s+import\s+(.+)', cfg, re.M) - return matches - - -def parse_export(configobj, name): - cfg = configobj['vrf definition %s' % name] - cfg = '\n'.join(cfg.children) - matches = re.findall(r'route-target\s+export\s+(.+)', cfg, re.M) - return matches - - -def parse_both(configobj, name, address_family='global'): - rd_pattern = re.compile('(?P<rd>.+:.+)') - matches = list() - export_match = None - import_match = None - if address_family == "global": - export_match = parse_export(configobj, name) - import_match = parse_import(configobj, name) - elif address_family == "ipv4": - export_match = parse_export_ipv4(configobj, name) - import_match = parse_import_ipv4(configobj, name) - elif address_family == "ipv6": - export_match = parse_export_ipv6(configobj, name) - import_match = parse_import_ipv6(configobj, name) - if import_match and export_match: - for ex in export_match: - exrd = rd_pattern.search(ex) - exrd = exrd.groupdict().get('rd') - for im in import_match: - imrd = rd_pattern.search(im) - imrd = imrd.groupdict().get('rd') - if exrd == imrd: - matches.extend([exrd]) if exrd not in matches else None - matches.extend([imrd]) if imrd not in matches else None - return matches - - -def parse_import_ipv4(configobj, name): - cfg = configobj['vrf definition %s' % name] - try: - subcfg = cfg['address-family ipv4'] - subcfg = '\n'.join(subcfg.children) - matches = re.findall(r'route-target\s+import\s+(.+)', subcfg, re.M) - return matches - except KeyError: - pass - - -def parse_export_ipv4(configobj, name): - cfg = configobj['vrf definition %s' % name] - try: - subcfg = cfg['address-family ipv4'] - subcfg = '\n'.join(subcfg.children) - matches = re.findall(r'route-target\s+export\s+(.+)', subcfg, re.M) - return matches - except KeyError: - pass - - -def parse_import_ipv6(configobj, name): - cfg = configobj['vrf definition %s' % name] - try: - subcfg = cfg['address-family ipv6'] - subcfg = '\n'.join(subcfg.children) - matches = re.findall(r'route-target\s+import\s+(.+)', subcfg, re.M) - return matches - except KeyError: - pass - - -def parse_export_ipv6(configobj, name): - cfg = configobj['vrf definition %s' % name] - try: - subcfg = cfg['address-family ipv6'] - subcfg = '\n'.join(subcfg.children) - matches = re.findall(r'route-target\s+export\s+(.+)', subcfg, re.M) - return matches - except KeyError: - pass - - -def map_config_to_obj(module): - config = get_config(module) - configobj = NetworkConfig(indent=1, contents=config) - match = re.findall(r'^vrf definition (\S+)', config, re.M) - if not match: - return list() - - instances = list() - - interfaces = parse_interfaces(configobj) - - for item in set(match): - obj = { - 'name': item, - 'state': 'present', - 'description': parse_description(configobj, item), - 'rd': parse_rd(configobj, item), - 'interfaces': interfaces.get(item), - 'route_import': parse_import(configobj, item), - 'route_export': parse_export(configobj, item), - 'route_both': parse_both(configobj, item), - 'route_import_ipv4': parse_import_ipv4(configobj, item), - 'route_export_ipv4': parse_export_ipv4(configobj, item), - 'route_both_ipv4': parse_both(configobj, item, address_family='ipv4'), - 'route_import_ipv6': parse_import_ipv6(configobj, item), - 'route_export_ipv6': parse_export_ipv6(configobj, item), - 'route_both_ipv6': parse_both(configobj, item, address_family='ipv6'), - } - instances.append(obj) - return instances - - -def get_param_value(key, item, module): - # if key doesn't exist in the item, get it from module.params - if not item.get(key): - value = module.params[key] - - # if key does exist, do a type check on it to validate it - else: - value_type = module.argument_spec[key].get('type', 'str') - type_checker = module._CHECK_ARGUMENT_TYPES_DISPATCHER[value_type] - type_checker(item[key]) - value = item[key] - - # validate the param value (if validator func exists) - validator = globals().get('validate_%s' % key) - if validator: - validator(value, module) - - return value - - -def map_params_to_obj(module): - vrfs = module.params.get('vrfs') - if not vrfs: - if not module.params['name'] and module.params['purge']: - return list() - elif not module.params['name']: - module.fail_json(msg='name is required') - collection = [{'name': module.params['name']}] - else: - collection = list() - for item in vrfs: - if not isinstance(item, dict): - collection.append({'name': item}) - elif 'name' not in item: - module.fail_json(msg='name is required') - else: - collection.append(item) - - objects = list() - for item in collection: - get_value = partial(get_param_value, item=item, module=module) - item['description'] = get_value('description') - item['rd'] = get_value('rd') - item['interfaces'] = get_value('interfaces') - item['state'] = get_value('state') - item['route_import'] = get_value('route_import') - item['route_export'] = get_value('route_export') - item['route_both'] = get_value('route_both') - item['route_import_ipv4'] = get_value('route_import_ipv4') - item['route_export_ipv4'] = get_value('route_export_ipv4') - item['route_both_ipv4'] = get_value('route_both_ipv4') - item['route_import_ipv6'] = get_value('route_import_ipv6') - item['route_export_ipv6'] = get_value('route_export_ipv6') - item['route_both_ipv6'] = get_value('route_both_ipv6') - both_addresses_family = ["", "_ipv6", "_ipv4"] - for address_family in both_addresses_family: - if item["route_both%s" % address_family]: - if not item["route_export%s" % address_family]: - item["route_export%s" % address_family] = list() - if not item["route_import%s" % address_family]: - item["route_import%s" % address_family] = list() - item["route_export%s" % address_family].extend(get_value("route_both%s" % address_family)) - item["route_import%s" % address_family].extend(get_value("route_both%s" % address_family)) - item['associated_interfaces'] = get_value('associated_interfaces') - objects.append(item) - - return objects - - -def update_objects(want, have): - updates = list() - for entry in want: - item = next((i for i in have if i['name'] == entry['name']), None) - if all((item is None, entry['state'] == 'present')): - updates.append((entry, {})) - else: - for key, value in iteritems(entry): - if value: - try: - if isinstance(value, list): - if sorted(value) != sorted(item[key]): - if (entry, item) not in updates: - updates.append((entry, item)) - elif value != item[key]: - if (entry, item) not in updates: - updates.append((entry, item)) - except TypeError: - pass - return updates - - -def check_declarative_intent_params(want, module, result): - if module.params['associated_interfaces']: - - if result['changed']: - time.sleep(module.params['delay']) - - name = module.params['name'] - rc, out, err = exec_command(module, 'show vrf | include {0}'.format(name)) - - if rc == 0: - data = out.strip().split() - # data will be empty if the vrf was just added - if not data: - return - vrf = data[0] - interface = data[-1] - - for w in want: - if w['name'] == vrf: - if w.get('associated_interfaces') is None: - continue - for i in w['associated_interfaces']: - if get_interface_type(i) is not get_interface_type(interface): - module.fail_json(msg="Interface %s not configured on vrf %s" % (interface, name)) - - -def main(): - """ main entry point for module execution - """ - argument_spec = dict( - vrfs=dict(type='list'), - - name=dict(), - description=dict(), - rd=dict(), - route_export=dict(type='list'), - route_import=dict(type='list'), - route_both=dict(type='list'), - route_export_ipv4=dict(type='list'), - route_import_ipv4=dict(type='list'), - route_both_ipv4=dict(type='list'), - route_export_ipv6=dict(type='list'), - route_import_ipv6=dict(type='list'), - route_both_ipv6=dict(type='list'), - - - interfaces=dict(type='list'), - associated_interfaces=dict(type='list'), - - delay=dict(default=10, type='int'), - purge=dict(type='bool', default=False), - state=dict(default='present', choices=['present', 'absent']) - ) - - argument_spec.update(ios_argument_spec) - - mutually_exclusive = [('name', 'vrfs')] - module = AnsibleModule(argument_spec=argument_spec, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True) - - result = {'changed': False} - - warnings = list() - result['warnings'] = warnings - - want = map_params_to_obj(module) - have = map_config_to_obj(module) - commands = map_obj_to_commands(update_objects(want, have), module) - - if module.params['purge']: - want_vrfs = [x['name'] for x in want] - have_vrfs = [x['name'] for x in have] - for item in set(have_vrfs).difference(want_vrfs): - cmd = 'no vrf definition %s' % item - if cmd not in commands: - commands.append(cmd) - - result['commands'] = commands - - if commands: - if not module.check_mode: - load_config(module, commands) - result['changed'] = True - - check_declarative_intent_params(want, module, result) - - module.exit_json(**result) - - -if __name__ == '__main__': - main() |