Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[minor_change] Added ndo_mcp_global_policy for fabric policy global MCP configuration (DCNE-70) #574

Merged
merged 5 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
323 changes: 323 additions & 0 deletions plugins/modules/ndo_mcp_global_policy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,323 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright: (c) 2024, Samita Bhattacharjee (@samiib) <[email protected]>

# GNU General Public License v3.0+ (see LICENSE 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: ndo_mcp_global_policy
short_description: Manage the MCP Global Policy in a Fabric Policy Template on Cisco Nexus Dashboard Orchestrator (NDO).
description:
- Manage the MisCabling Protocol (MCP) Global Policy in a Fabric Policy Template on Cisco Nexus Dashboard Orchestrator (NDO).
- There can only be a single MCP Global Policy in a Fabric Policy Template.
- This module is only supported on ND v3.1 (NDO v4.3) and later.
author:
- Samita Bhattacharjee (@samiib)
options:
template:
description:
- The name of the template.
- The template must be a Fabric Policy template.
type: str
aliases: [ fabric_template ]
required: true
name:
description:
- The name of the MCP Global Policy.
type: str
aliases: [ mcp_global_policy ]
uuid:
description:
- The UUID of the MCP Global Policy.
type: str
aliases: [ mcp_global_policy_uuid ]
description:
description:
- The description of the MCP Global Policy.
- Providing an empty string will remove the O(description="") from the MCP Global Policy.
type: str
admin_state:
description:
- The administrative state of the MCP Global Policy.
- Defaults to C(enabled) when unset during creation.
type: str
choices: [ enabled, disabled ]
key:
description:
- The key of the MCP Global Policy.
type: str
per_vlan:
description:
- When enabled MCP will send packets on a per End Point Group (EPG) basis.
- If disabled, the packets will only be sent on untagged EPGs which allows detecting loops in the native VLAN only.
- Defaults to C(disabled) when unset during creation.
type: str
choices: [ enabled, disabled ]
aliases: [ per_epg, mcp_pdu_per_vlan ]
loop_detection_factor:
description:
- The amount of MCP packets that will be received before port disable loop protection action takes place.
- Defaults to 3 when unset during creation.
- The value must be between 1 and 255.
type: int
aliases: [ loop_factor, loop_detection_mult_factor ]
port_disable:
description:
- Enable or disable port disabling when MCP packets are received.
- Defaults to C(enabled) when unset during creation.
type: str
choices: [ enabled, disabled ]
aliases: [ port_disable_protection ]
initial_delay_time:
description:
- The MCP initial delay time in seconds.
- Defaults to 180 when unset during creation.
- The value must be between 0 and 1800.
type: int
aliases: [ initial_delay ]
transmission_frequency_sec:
description:
- The MCP transmission frequency in seconds.
- Defaults to 2 when unset during creation.
- The value must be between 0 and 300.
type: int
aliases: [ tx_freq ]
transmission_frequency_msec:
description:
- The MCP transmission frequency in milliseconds.
- Defaults to 0 when unset during creation.
- The value must be between 0 and 999.
type: int
aliases: [ tx_freq_ms ]
state:
description:
- Use C(absent) for removing.
- Use C(query) for listing an object or multiple objects.
- Use C(present) for creating or updating.
type: str
choices: [ absent, query, present ]
default: query
notes:
- The O(template) must exist before using this module in your playbook.
Use M(cisco.mso.ndo_template) to create the Fabric Policy template.
- Attempts to create any additional MCP Global Policies will only update the existing
object in the Fabric Policy template.
seealso:
- module: cisco.mso.ndo_template
extends_documentation_fragment: cisco.mso.modules
"""

EXAMPLES = r"""
- name: Create the MCP Global Policy object
cisco.mso.ndo_mcp_global_policy:
host: mso_host
username: admin
password: SomeSecretPassword
template: fabric_template
name: example_mcp_global_policy
state: present
register: mcp_global_policy_new

- name: Create the MCP Global Policy object with all attributes
akinross marked this conversation as resolved.
Show resolved Hide resolved
cisco.mso.ndo_mcp_global_policy:
host: mso_host
username: admin
password: SomeSecretPassword
template: fabric_template
name: example_mcp_global_policy
description: A Global MCP Policy
key: cisco
admin_state: enabled
per_vlan: enabled
loop_detection_factor: 3
port_disable: enabled
initial_delay_time: 180
transmission_frequency_sec: 2
transmission_frequency_msec: 10
state: present
register: mcp_global_policy_all

- name: Update the MCP Global Policy object with UUID
cisco.mso.ndo_mcp_global_policy:
host: mso_host
username: admin
password: SomeSecretPassword
template: fabric_template
name: mcp_global_policy_update
uuid: "{{ mcp_global_policy_all.current.uuid }}"
state: present

- name: Query the MCP Global Policy object with name
cisco.mso.ndo_mcp_global_policy:
host: mso_host
username: admin
password: SomeSecretPassword
template: fabric_template
name: example_mcp_global_policy
state: query
register: query_name

- name: Query the MCP Global Policy object with UUID
cisco.mso.ndo_mcp_global_policy:
host: mso_host
username: admin
password: SomeSecretPassword
template: fabric_template
uuid: "{{ mcp_global_policy_all.current.uuid }}"
state: query
register: query_uuid

- name: Query the MCP Global Policy object in a Fabric Template
cisco.mso.ndo_mcp_global_policy:
host: mso_host
username: admin
password: SomeSecretPassword
template: fabric_template
state: query
register: query_all

- name: Delete the MCP Global Policy object with name
cisco.mso.ndo_mcp_global_policy:
host: mso_host
username: admin
password: SomeSecretPassword
template: fabric_template
name: example_mcp_global_policy
state: absent

- name: Delete the MCP Global Policy object with UUID
cisco.mso.ndo_mcp_global_policy:
host: mso_host
username: admin
password: SomeSecretPassword
template: fabric_template
uuid: "{{ mcp_global_policy_all.current.uuid }}"
state: absent
"""

RETURN = r"""
"""

import copy
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.cisco.mso.plugins.module_utils.mso import MSOModule, mso_argument_spec
from ansible_collections.cisco.mso.plugins.module_utils.constants import ENABLED_OR_DISABLED_TO_BOOL_STRING_MAP
from ansible_collections.cisco.mso.plugins.module_utils.template import MSOTemplate
from ansible_collections.cisco.mso.plugins.module_utils.utils import append_update_ops_data


def main():
argument_spec = mso_argument_spec()
argument_spec.update(
template=dict(type="str", required=True, aliases=["fabric_template"]),
name=dict(type="str", aliases=["mcp_global_policy"]),
uuid=dict(type="str", aliases=["mcp_global_policy_uuid"]),
description=dict(type="str"),
admin_state=dict(type="str", choices=["enabled", "disabled"]),
key=dict(type="str", no_log=False),
per_vlan=dict(
type="str",
aliases=["per_epg", "mcp_pdu_per_vlan"],
choices=["enabled", "disabled"],
),
loop_detection_factor=dict(type="int", aliases=["loop_factor", "loop_detection_mult_factor"]),
port_disable=dict(
type="str",
aliases=["port_disable_protection"],
choices=["enabled", "disabled"],
),
initial_delay_time=dict(type="int", aliases=["initial_delay"]),
transmission_frequency_sec=dict(type="int", aliases=["tx_freq"]),
transmission_frequency_msec=dict(type="int", aliases=["tx_freq_ms"]),
state=dict(type="str", default="query", choices=["absent", "query", "present"]),
)

# Enforcing that a user must specify a name or uuid when
# adding, updating or removing even though there is only one policy per template.
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True,
required_if=[
["state", "absent", ["name", "uuid"], True],
["state", "present", ["name", "uuid"], True],
],
)

mso = MSOModule(module)

Check warning on line 254 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L254

Added line #L254 was not covered by tests

name = module.params.get("name")
uuid = module.params.get("uuid")
state = module.params.get("state")
per_vlan = module.params.get("per_vlan")
port_disable = module.params.get("port_disable")

Check warning on line 260 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L256-L260

Added lines #L256 - L260 were not covered by tests

mso_values = {

Check warning on line 262 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L262

Added line #L262 was not covered by tests
akinross marked this conversation as resolved.
Show resolved Hide resolved
"name": name,
"description": module.params.get("description"),
"adminState": module.params.get("admin_state"),
"key": module.params.get("key"),
"enablePduPerVlan": ENABLED_OR_DISABLED_TO_BOOL_STRING_MAP.get(per_vlan),
"loopDetectMultFactor": module.params.get("loop_detection_factor"),
"protectPortDisable": ENABLED_OR_DISABLED_TO_BOOL_STRING_MAP.get(port_disable),
"initialDelayTime": module.params.get("initial_delay_time"),
"txFreq": module.params.get("transmission_frequency_sec"),
"txFreqMsec": module.params.get("transmission_frequency_msec"),
}

ops = []

Check warning on line 275 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L275

Added line #L275 was not covered by tests

mso_template = MSOTemplate(mso, "fabric_policy", module.params.get("template"))
mso_template.validate_template("fabricPolicy")

Check warning on line 278 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L277-L278

Added lines #L277 - L278 were not covered by tests

object_description = "MCP Global Policy"
object_base_path = "/fabricPolicyTemplate/template/mcpGlobalPolicy"

Check warning on line 281 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L280-L281

Added lines #L280 - L281 were not covered by tests

existing_mcp_global_policy = mso_template.template.get("fabricPolicyTemplate", {}).get("template", {}).get("mcpGlobalPolicy", {})

Check warning on line 283 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L283

Added line #L283 was not covered by tests

if state in ["query", "absent"] and existing_mcp_global_policy == {}:
mso.exit_json()

Check warning on line 286 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L286

Added line #L286 was not covered by tests

elif state == "query" and not (name or uuid):
mso.existing = [existing_mcp_global_policy]

Check warning on line 289 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L289

Added line #L289 was not covered by tests

elif existing_mcp_global_policy and (name or uuid):
mso.existing = mso.previous = copy.deepcopy(existing_mcp_global_policy)

Check warning on line 292 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L292

Added line #L292 was not covered by tests
if uuid and mso.existing.get("uuid") != uuid:
mso.fail_json(msg="{0} with the UUID: '{1}' not found".format(object_description, uuid))

Check warning on line 294 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L294

Added line #L294 was not covered by tests

samiib marked this conversation as resolved.
Show resolved Hide resolved
if state == "present":
if mso.existing:
proposed_payload = copy.deepcopy(mso.existing)
append_update_ops_data(ops, proposed_payload, object_base_path, mso_values)
mso.sanitize(proposed_payload, collate=True)

Check warning on line 300 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L298-L300

Added lines #L298 - L300 were not covered by tests
else:
if uuid:
mso.fail_json(msg="{0} cannot be created with a UUID".format(object_description))
mso.sanitize(mso_values)
ops.append(dict(op="add", path=object_base_path, value=mso.sent))

Check warning on line 305 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L303-L305

Added lines #L303 - L305 were not covered by tests

mso.existing = mso.proposed

Check warning on line 307 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L307

Added line #L307 was not covered by tests

elif state == "absent":
if mso.existing:
ops.append(dict(op="remove", path=object_base_path))

Check warning on line 311 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L311

Added line #L311 was not covered by tests

if not module.check_mode and ops:
response_object = mso.request(mso_template.template_path, method="PATCH", data=ops)
mso.existing = response_object.get("fabricPolicyTemplate", {}).get("template", {}).get("mcpGlobalPolicy", {})

Check warning on line 315 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L314-L315

Added lines #L314 - L315 were not covered by tests
elif module.check_mode and state != "query": # When the state is present/absent with check mode
mso.existing = mso.proposed if state == "present" else {}

Check warning on line 317 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L317

Added line #L317 was not covered by tests

mso.exit_json()

Check warning on line 319 in plugins/modules/ndo_mcp_global_policy.py

View check run for this annotation

Codecov / codecov/patch

plugins/modules/ndo_mcp_global_policy.py#L319

Added line #L319 was not covered by tests


if __name__ == "__main__":
main()
2 changes: 2 additions & 0 deletions tests/integration/targets/ndo_mcp_global_policy/aliases
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# No ACI MultiSite infrastructure, so not enabled
# unsupported
Loading
Loading