Skip to content
Open
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ ansible_connection: ansible.netcommon.httpapi
ansible_httpapi_port: 443
ansible_httpapi_use_ssl: true
ansible_httpapi_validate_certs: false
ansible_network_os: cisco.dcnm.dcnm
ansible_network_os: cisco.nd.nd #Change as per ansible_network_os
# NDFC API Credentials
ansible_user: "{{ lookup('env', 'ND_USERNAME') }}"
ansible_password: "{{ lookup('env', 'ND_PASSWORD') }}"
Expand Down
10 changes: 9 additions & 1 deletion plugins/action/dtc/fabric_check_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

from ansible.utils.display import Display
from ansible.plugins.action import ActionBase
from ...plugin_utils.helper_functions import get_rest_module


display = Display()
Expand All @@ -40,8 +41,15 @@ def run(self, tmp=None, task_vars=None):

fabric = self._task.args["fabric"]

network_os = task_vars['ansible_network_os']
rest_module = get_rest_module(network_os)
if not rest_module:
results['failed'] = True
results['msg'] = f"Unsupported network_os: {network_os}"
return results

ndfc_response = self._execute_module(
module_name="cisco.dcnm.dcnm_rest",
module_name=rest_module,
module_args={
"method": "GET",
"path": f"/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{fabric}/inventory/switchesByFabric",
Expand Down
9 changes: 8 additions & 1 deletion plugins/action/dtc/fabrics_config_save.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

from ansible.utils.display import Display
from ansible.plugins.action import ActionBase
from ...plugin_utils.helper_functions import get_rest_module


display = Display()
Expand All @@ -42,8 +43,14 @@ def run(self, tmp=None, task_vars=None):

for fabric in fabrics:
display.display(f"Executing config-save on Fabric: {fabric}")
network_os = task_vars['ansible_network_os']
rest_module = get_rest_module(network_os)
if not rest_module:
results['failed'] = True
results['msg'] = f"Unsupported network_os: {network_os}"
return results
ndfc_config_save = self._execute_module(
module_name="cisco.dcnm.dcnm_rest",
module_name=rest_module,
module_args={
"method": "POST",
"path": f"/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{fabric}/config-save",
Expand Down
10 changes: 9 additions & 1 deletion plugins/action/dtc/fabrics_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

from ansible.utils.display import Display
from ansible.plugins.action import ActionBase
from ...plugin_utils.helper_functions import get_rest_module


display = Display()
Expand All @@ -42,8 +43,15 @@ def run(self, tmp=None, task_vars=None):

for fabric in fabrics:
display.display(f"Executing config-deploy on Fabric: {fabric}")
network_os = task_vars['ansible_network_os']
rest_module = get_rest_module(network_os)
if not rest_module:
results['failed'] = True
results['msg'] = f"Unsupported network_os: {network_os}"
return results

ndfc_deploy = self._execute_module(
module_name="cisco.dcnm.dcnm_rest",
module_name=rest_module,
module_args={
"method": "POST",
"path": f"/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{fabric}/config-deploy?forceShowRun=false",
Expand Down
8 changes: 7 additions & 1 deletion plugins/action/dtc/get_poap_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
__metaclass__ = type

from ansible.plugins.action import ActionBase
from ...plugin_utils.helper_functions import get_rest_module
import json
import re
import inspect
Expand Down Expand Up @@ -151,8 +152,13 @@ def refresh(self) -> None:
self.refresh_succeeded = False
self.refresh_message = None

network_os = self.task_vars['ansible_network_os']
rest_module = get_rest_module(network_os)
if not rest_module:
self.refresh_message = f"Unsupported network_os: {network_os}"
return
data = self.execute_module(
module_name="cisco.dcnm.dcnm_rest",
module_name=rest_module,
module_args={
"method": self.poap_get_method,
"path": self.poap_get_path
Expand Down
12 changes: 10 additions & 2 deletions plugins/action/dtc/manage_child_fabric_networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from ansible.template import Templar
from ansible.errors import AnsibleFileNotFound
from ansible_collections.cisco.nac_dc_vxlan.plugins.filter.version_compare import version_compare
from ...plugin_utils.helper_functions import get_rest_module


import re
Expand Down Expand Up @@ -79,6 +80,13 @@ def run(self, tmp=None, task_vars=None):

child_fabrics = msite_data['child_fabrics_data']

network_os = task_vars['ansible_network_os']
rest_module = get_rest_module(network_os)
if not rest_module:
results['failed'] = True
results['msg'] = f"Unsupported network_os: {network_os}"
return results

for network in networks:
network_attach_group_switches = [
network_attach_groups_dict['switches']
Expand Down Expand Up @@ -157,7 +165,7 @@ def run(self, tmp=None, task_vars=None):
# return results

ndfc_net = self._execute_module(
module_name="cisco.dcnm.dcnm_rest",
module_name=rest_module,
module_args={
"method": "GET",
"path": f"/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{child_fabric}/networks/{network['name']}",
Expand Down Expand Up @@ -222,7 +230,7 @@ def run(self, tmp=None, task_vars=None):
rendered_to_nice_json = templar.environment.filters['to_nice_json'](rendered_content)

ndfc_net_update = self._execute_module(
module_name="cisco.dcnm.dcnm_rest",
module_name=rest_module,
module_args={
"method": "PUT",
"path": f"/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{child_fabric}/networks/{network['name']}",
Expand Down
12 changes: 10 additions & 2 deletions plugins/action/dtc/manage_child_fabric_vrfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from ansible.template import Templar
from ansible.errors import AnsibleFileNotFound
from ansible_collections.cisco.nac_dc_vxlan.plugins.filter.version_compare import version_compare
from ...plugin_utils.helper_functions import get_rest_module


import re
Expand Down Expand Up @@ -89,6 +90,13 @@ def run(self, tmp=None, task_vars=None):

child_fabrics = msite_data['child_fabrics_data']

network_os = task_vars['ansible_network_os']
rest_module = get_rest_module(network_os)
if not rest_module:
results['failed'] = True
results['msg'] = f"Unsupported network_os: {network_os}"
return results

for vrf in vrfs:
vrf_attach_group_switches = [
vrf_attach_group_dict['switches']
Expand Down Expand Up @@ -167,7 +175,7 @@ def run(self, tmp=None, task_vars=None):
# return results

ndfc_vrf = self._execute_module(
module_name="cisco.dcnm.dcnm_rest",
module_name=rest_module,
module_args={
"method": "GET",
"path": f"/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{child_fabric}/vrfs/{vrf['name']}"
Expand Down Expand Up @@ -233,7 +241,7 @@ def run(self, tmp=None, task_vars=None):
rendered_to_nice_json = templar.environment.filters['to_nice_json'](rendered_content)

ndfc_vrf_update = self._execute_module(
module_name="cisco.dcnm.dcnm_rest",
module_name=rest_module,
module_args={
"method": "PUT",
"path": f"/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{child_fabric}/vrfs/{vrf['name']}",
Expand Down
12 changes: 10 additions & 2 deletions plugins/action/dtc/manage_child_fabrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

from ansible.utils.display import Display
from ansible.plugins.action import ActionBase
from ...plugin_utils.helper_functions import get_rest_module

display = Display()

Expand All @@ -42,11 +43,18 @@ def run(self, tmp=None, task_vars=None):
child_fabrics = self._task.args['child_fabrics']
state = self._task.args['state']

network_os = task_vars['ansible_network_os']
rest_module = get_rest_module(network_os)
if not rest_module:
results['failed'] = True
results['msg'] = f"Unsupported network_os: {network_os}"
return results

if state == 'present':
for fabric in child_fabrics:
json_data = '{"destFabric":"%s","sourceFabric":"%s"}' % (parent_fabric, fabric)
add_fabric_result = self._execute_module(
module_name="cisco.dcnm.dcnm_rest",
module_name=rest_module,
module_args={
"method": "POST",
"path": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/msdAdd",
Expand Down Expand Up @@ -75,7 +83,7 @@ def run(self, tmp=None, task_vars=None):
for fabric in child_fabrics:
json_data = '{"destFabric":"%s","sourceFabric":"%s"}' % (parent_fabric, fabric)
remove_fabric_result = self._execute_module(
module_name="cisco.dcnm.dcnm_rest",
module_name=rest_module,
module_args={
"method": "POST",
"path": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/msdExit",
Expand Down
10 changes: 9 additions & 1 deletion plugins/action/dtc/prepare_msite_child_fabrics_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

from ansible.utils.display import Display
from ansible.plugins.action import ActionBase
from ...plugin_utils.helper_functions import get_rest_module

display = Display()

Expand All @@ -42,10 +43,17 @@ def run(self, tmp=None, task_vars=None):
parent_fabric = self._task.args["parent_fabric"]
child_fabrics = self._task.args["child_fabrics"]

network_os = task_vars['ansible_network_os']
rest_module = get_rest_module(network_os)
if not rest_module:
results['failed'] = True
results['msg'] = f"Unsupported network_os: {network_os}"
return results

# This is actaully not an accurrate API endpoint as it returns all fabrics in NDFC, not just the fabrics associated with MSD
# Therefore, we need to get the fabric associations response and filter out the fabrics that are not associated with the parent fabric (MSD)
msd_fabric_associations = self._execute_module(
module_name="cisco.dcnm.dcnm_rest",
module_name=rest_module,
module_args={
"method": "GET",
"path": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/msd/fabric-associations",
Expand Down
10 changes: 9 additions & 1 deletion plugins/action/dtc/prepare_msite_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from ansible.plugins.action import ActionBase
from ansible_collections.cisco.nac_dc_vxlan.plugins.plugin_utils.helper_functions import ndfc_get_fabric_attributes
from ansible_collections.cisco.nac_dc_vxlan.plugins.plugin_utils.helper_functions import ndfc_get_fabric_switches
from ...plugin_utils.helper_functions import get_rest_module
import re

display = Display()
Expand All @@ -44,10 +45,17 @@ def run(self, tmp=None, task_vars=None):
model_data = self._task.args["model_data"]
parent_fabric = self._task.args["parent_fabric"]

network_os = task_vars['ansible_network_os']
rest_module = get_rest_module(network_os)
if not rest_module:
results['failed'] = True
results['msg'] = f"Unsupported network_os: {network_os}"
return results

# This is actaully not an accurrate API endpoint as it returns all fabrics in NDFC, not just the fabrics associated with MSD
# Therefore, we need to get the fabric associations response and filter out the fabrics that are not associated with the parent fabric (MSD)
msd_fabric_associations = self._execute_module(
module_name="cisco.dcnm.dcnm_rest",
module_name=rest_module,
module_args={
"method": "GET",
"path": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/msd/fabric-associations",
Expand Down
105 changes: 105 additions & 0 deletions plugins/action/dtc/rest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Copyright (c) 2024 Cisco Systems, Inc. and its affiliates
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# SPDX-License-Identifier: MIT

from __future__ import absolute_import, division, print_function

__metaclass__ = type

from ansible.utils.display import Display
from ansible.plugins.action import ActionBase
from ...plugin_utils.helper_functions import get_rest_module

display = Display()


class ActionModule(ActionBase):
"""
Action plugin to dynamically select between cisco.nd.nd_rest and cisco.dcnm.dcnm_rest
based on the ansible_network_os variable.
"""

def run(self, tmp=None, task_vars=None):
"""
Execute the action plugin.

Args:
tmp (str, optional): Temporary directory. Defaults to None.
task_vars (dict, optional): Dictionary of task variables. Defaults to None.

Returns:
dict: Results of the REST API call
"""
# Initialize results dictionary
results = super(ActionModule, self).run(tmp, task_vars)
results['changed'] = False
results['failed'] = False

# Get task arguments
module_args = self._task.args.copy()

# Get the network OS from task variables or module arguments
network_os = task_vars.get('ansible_network_os')
display.vvvv(f"Using OS module: {network_os}")

# Determine which module to use based on network_os
rest_module = get_rest_module(network_os)
if not rest_module:
results['failed'] = True
results['msg'] = f"Unsupported network_os: {network_os}"
return results

display.vvvv(f"Using REST module: {rest_module}")

try:
display.vvvv(f"Executing module: {rest_module} with args: {module_args}")

self._task.vars['ansible_rest_os_module'] = rest_module

# Set the connection to httpapi
if 'connection' not in task_vars:
task_vars['connection'] = 'httpapi'

# Execute the appropriate REST module
result = self._execute_module(
module_name=rest_module,
module_args=module_args,
task_vars=task_vars,
tmp=tmp,
wrap_async=False
)

# Update results with the module's results
if result.get('failed'):
results.update(result)
display.error(f"Module execution failed: {result.get('msg')}")
else:
results['changed'] = result.get('changed', False)
results.update(result)
display.vvvv(f"Module execution successful: {result}")

except Exception as e:
import traceback
error_trace = traceback.format_exc()
results['failed'] = True
results['msg'] = f"Failed to execute {rest_module}: {str(e)}\n{error_trace}"
display.error(results['msg'], wrap_text=False)

return results
Loading