From 9dc90ee48b1a067a1da03fe47f51d2277dba44b2 Mon Sep 17 00:00:00 2001 From: Steven Gerhart Date: Fri, 29 Mar 2019 09:22:00 -0400 Subject: [PATCH] ACI: New aci_maintenance_policy module (#48368) * create aci_maintenance_policy module * added adminst for triggering upgrade * fixed argument * Various changes * Capitalize * upgrade to adminst, change bool default, ignoreCompat * upgrade to adminst, change bool default, ignoreCompat --- .../network/aci/aci_maintenance_policy.py | 267 ++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 lib/ansible/modules/network/aci/aci_maintenance_policy.py diff --git a/lib/ansible/modules/network/aci/aci_maintenance_policy.py b/lib/ansible/modules/network/aci/aci_maintenance_policy.py new file mode 100644 index 00000000000..26f8210f2f9 --- /dev/null +++ b/lib/ansible/modules/network/aci/aci_maintenance_policy.py @@ -0,0 +1,267 @@ +#!/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: aci_maintenance_policy +short_description: Manage firmware maintenance policies +version_added: '2.8' +description: +- Manage maintenance policies that defines behavior during an ACI upgrade. +options: + name: + description: + - The name for the maintenance policy. + required: true + aliases: [ maintenance_policy ] + runmode: + description: + - Whether the system pauses on error or just continues through it. + choices: ['pauseOnlyOnFailures', 'pauseNever'] + default: pauseOnlyOnFailures + graceful: + description: + - Whether the system will bring down the nodes gracefully during an upgrade, which reduces traffic lost. + - The APIC defaults to C(no) when unset during creation. + type: bool + scheduler: + description: + - The name of scheduler that is applied to the policy. + type: str + required: true + adminst: + description: + - Will trigger an immediate upgrade for nodes if adminst is set to triggered. + choices: [ triggered, untriggered ] + default: untriggered + ignoreCompat: + description: + - To check whether compatibility checks should be ignored + - The APIC defaults to C(no) when unset during creation. + type: bool + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- aci +notes: +- A scheduler is required for this module, which could have been created using the M(aci_scheduler) module or via the UI. +author: +- Steven Gerhart (@sgerhart) +''' + +EXAMPLES = r''' +- name: Ensure maintenance policy is present + aci_maintenance_policy: + host: '{{ inventory_hostname }}' + username: '{{ user }}' + password: '{{ pass }}' + validate_certs: no + name: maintenancePol1 + scheduler: simpleScheduler + runmode: False + state: present +''' + +RETURN = r''' +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +''' + + +from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec +from ansible.module_utils.basic import AnsibleModule + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update( + name=dict(type='str', aliases=['maintenance_policy']), # Not required for querying all objects + runmode=dict(type='str', default='pauseOnlyOnFailures', choices=['pauseOnlyOnFailures', 'pauseNever']), + graceful=dict(type='bool'), + scheduler=dict(type='str'), + ignoreCompat=dict(type='bool'), + adminst=dict(type='str', default='untriggered', choices=['triggered', 'untriggered']), + state=dict(type='str', default='present', choices=['absent', 'present', 'query']), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ['state', 'absent', ['name']], + ['state', 'present', ['name', 'scheduler']], + ], + ) + + aci = ACIModule(module) + + state = module.params['state'] + name = module.params['name'] + runmode = module.params['runmode'] + scheduler = module.params['scheduler'] + adminst = module.params['adminst'] + graceful = aci.boolean(module.params['graceful']) + ignoreCompat = aci.boolean(module.params['ignoreCompat']) + + aci.construct_url( + root_class=dict( + aci_class='maintMaintP', + aci_rn='fabric/maintpol-{0}'.format(name), + target_filter={'name': name}, + module_object=name, + ), + child_classes=['maintRsPolScheduler'] + + ) + + aci.get_existing() + + if state == 'present': + aci.payload( + aci_class='maintMaintP', + class_config=dict( + name=name, + runMode=runmode, + graceful=graceful, + adminSt=adminst, + ignoreCompat=ignoreCompat, + ), + child_configs=[ + dict( + maintRsPolScheduler=dict( + attributes=dict( + tnTrigSchedPName=scheduler, + ), + ), + ), + ], + + ) + + aci.get_diff(aci_class='maintMaintP') + + aci.post_config() + + elif state == 'absent': + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main()