diff --git a/lib/ansible/modules/network/aci/aci_intf_policy_port_channel.py b/lib/ansible/modules/network/aci/aci_intf_policy_port_channel.py index 773970370d0..6750c49db43 100644 --- a/lib/ansible/modules/network/aci/aci_intf_policy_port_channel.py +++ b/lib/ansible/modules/network/aci/aci_intf_policy_port_channel.py @@ -38,17 +38,62 @@ options: max_links: description: - Maximum links (range 1-16). - - The APIC defaults new Port Channel Policies to a max links of 16. + - The APIC defaults new Port Channel Policies to C(16). + choices: [ Ranges from 1 to 16 ] + default: 16 min_links: description: - Minimum links (range 1-16). - - The APIC defaults new Port Channel Policies to a min links of 1. + - The APIC defaults new Port Channel Policies to C(1). + choices: [ Ranges from 1 to 16 ] + default: 1 mode: description: - Port channel interface policy mode. - Determines the LACP method to use for forming port-channels. - - The APIC defaults new Port Channel Polices to a off mode. + - The APIC defaults new Port Channel Polices to C(off). choices: [ active, mac-pin, mac-pin-nicload, off, passive ] + default: off + fast_select: + description: + - Determines if Fast Select is enabled for Hot Standby Ports. + - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties + left undefined or set to false will not exist after the task is ran. + - The APIC defaults new LACP Policies to C(true). + type: bool + default: true + graceful_convergence: + description: + - Determines if Graceful Convergence is enabled. + - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties + left undefined or set to false will not exist after the task is ran. + - The APIC defaults new LACP Policies to C(true). + type: bool + default: true + load_defer: + description: + - Determines if Load Defer is enabled. + - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties + left undefined or set to false will not exist after the task is ran. + - The APIC defaults new LACP Policies to C(false). + type: bool + default: false + suspend_individual: + description: + - Determines if Suspend Individual is enabled. + - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties + left undefined or set to false will not exist after the task is ran. + - The APIC defaults new LACP Policies to C(true). + type: bool + default: true + symmetric_hash: + description: + - Determines if Symmetric Hashing is enabled. + - This makes up the LACP Policy Control Policy; if one setting is defined, then all other Control Properties + left undefined or set to false will not exist after the task is ran. + - The APIC defaults new LACP Policies to C(false). + type: bool + default: false state: description: - Use C(present) or C(absent) for adding or removing. @@ -86,6 +131,11 @@ def main(): min_links=dict(type='int'), max_links=dict(type='int'), mode=dict(type='str', choices=['off', 'mac-pin', 'active', 'passive', 'mac-pin-nicload']), + fast_select=dict(type='bool'), + graceful_convergence=dict(type='bool'), + load_defer=dict(type='bool'), + suspend_individual=dict(type='bool'), + symmetric_hash=dict(type='bool'), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'), # Deprecated starting from v2.6 ) @@ -93,37 +143,57 @@ def main(): module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, + required_if=[ + ['state', 'absent', ['port_channel']], + ['state', 'present', ['port_channel']], + ], ) port_channel = module.params['port_channel'] description = module.params['description'] - # TODO: Validate min_links is in the acceptable range - min_links = module.params['min_link'] - # TODO: Validate max_links is in the acceptable range - min_links = str(min_links) - max_links = module.params['max_link'] - max_links = str(max_links) + min_links = module.params['min_links'] + if min_links is not None and min_links not in range(1, 17): + module.fail_json(msg='The "min_links" must be a value between 1 and 16') + max_links = module.params['max_links'] + if max_links is not None and max_links not in range(1, 17): + module.fail_json(msg='The "max_links" must be a value between 1 and 16') mode = module.params['mode'] state = module.params['state'] - aci = ACIModule(module) - - # TODO: This logic could be cleaner. - if port_channel is not None: - path = 'api/mo/uni/infra/lacplagp-%(port_channel)s.json' % module.params - elif state == 'query': - # Query all objects - path = 'api/node/class/lacplagPol.json' + # Build ctrl value for request + ctrl = [] + if module.params['fast_select'] is True: + ctrl.append('fast-sel-hot-stdby') + if module.params['graceful_convergence'] is True: + ctrl.append('graceful-conv') + if module.params['load_defer'] is True: + ctrl.append('load-defer') + if module.params['suspend_individual'] is True: + ctrl.append('susp-individual') + if module.params['symmetric_hash'] is True: + ctrl.append('symmetric-hash') + if not ctrl: + ctrl = None else: - module.fail_json(msg="Parameter 'port_channel' is required for state 'absent' or 'present'") - - aci.result['url'] = '%(protocol)s://%(hostname)s/' % aci.params + path + ctrl = ",".join(ctrl) + aci = ACIModule(module) + aci.construct_url(root_class='port_channel') aci.get_existing() if state == 'present': # Filter out module parameters with null values - aci.payload(aci_class='lacpLagPol', class_config=dict(name=port_channel, descr=description, minLinks=min_links, maxLinks=max_links, mode=mode)) + aci.payload( + aci_class='lacpLagPol', + class_config=dict( + name=port_channel, + ctrl=ctrl, + descr=description, + minLinks=min_links, + maxLinks=max_links, + mode=mode, + ), + ) # Generate config diff which will be used as POST request body aci.get_diff(aci_class='lacpLagPol')