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

DCNM Security Groups Associations commit after IT/UT complete #321

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
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
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ This collection is intended for use with the following release versions:
<!--start requires_ansible-->
## Ansible version compatibility

This collection has been tested against following Ansible versions: **>=2.9.10**.
This collection has been tested against following Ansible versions: **>=2.15.0**.

For collections that support Ansible 2.9, please ensure you update your `network_os` to use the
fully qualified collection name (for example, `cisco.ios.ios`).
Plugins and modules within a collection may be tested with only specific Ansible versions.
A collection may contain metadata that identifies these versions.
PEP440 is the schema used to describe the versions of Ansible.
Expand All @@ -39,13 +41,15 @@ Name | Description
[cisco.dcnm.dcnm_interface](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_interface_module.rst)|DCNM Ansible Module for managing interfaces.
[cisco.dcnm.dcnm_inventory](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_inventory_module.rst)|Add and remove Switches from a DCNM managed VXLAN fabric.
[cisco.dcnm.dcnm_links](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_links_module.rst)|DCNM ansible module for managing Links.
[cisco.dcnm.dcnm_maintenance_mode](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_maintenance_mode_module.rst)|Manage Maintenance Mode Configuration of NX-OS Switches.
[cisco.dcnm.dcnm_network](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_network_module.rst)|Add and remove Networks from a DCNM managed VXLAN fabric.
[cisco.dcnm.dcnm_policy](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_policy_module.rst)|DCNM Ansible Module for managing policies.
[cisco.dcnm.dcnm_resource_manager](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_resource_manager_module.rst)|DCNM ansible module for managing resources.
[cisco.dcnm.dcnm_rest](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_rest_module.rst)|Send REST API requests to DCNM controller.
[cisco.dcnm.dcnm_service_node](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_service_node_module.rst)|Create/Modify/Delete service node based on type and attached interfaces from a DCNM managed VXLAN fabric.
[cisco.dcnm.dcnm_service_policy](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_service_policy_module.rst)|DCNM ansible module for managing service policies.
[cisco.dcnm.dcnm_service_route_peering](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_service_route_peering_module.rst)|DCNM Ansible Module for managing Service Route Peerings.
[cisco.dcnm.dcnm_sgrp_association](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_sgrp_association_module.rst)|DCNM Ansible Module for managing Security Groups Associatons.
[cisco.dcnm.dcnm_template](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_template_module.rst)|DCNM Ansible Module for managing templates.
[cisco.dcnm.dcnm_vpc_pair](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_vpc_pair_module.rst)|DCNM Ansible Module for managing VPC switch pairs required for VPC interfaces.
[cisco.dcnm.dcnm_vrf](https://github.com/CiscoDevNet/ansible-dcnm/blob/main/docs/cisco.dcnm.dcnm_vrf_module.rst)|Add and remove VRFs from a DCNM managed VXLAN fabric.
Expand Down
460 changes: 460 additions & 0 deletions docs/cisco.dcnm.dcnm_sgrp_association_module.rst

Large diffs are not rendered by default.

257 changes: 257 additions & 0 deletions plugins/module_utils/common/common_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
from __future__ import absolute_import, division, print_function

import logging

from ansible_collections.cisco.dcnm.plugins.module_utils.network.dcnm.dcnm import (
get_fabric_inventory_details,
dcnm_version_supported,
get_ip_sn_dict,
)

__metaclass__ = type
__author__ = "Mallik Mudigonda"


class Version:
def __init__(self):
self.class_name = self.__class__.__name__
self._module = None

@property
def module(self):
return self._module

@module.setter
def module(self, value):
self._module = value

def commit(self):

self.log = logging.getLogger(f"dcnm.{self.class_name}")

if self._module is None:
msg = f"{0}.commit(): ".format(self.class_name)
msg += "module is not set, which is required."
raise ValueError(msg)

self.dcnm_version = dcnm_version_supported(self._module)
self.log.debug(f"Version = {0}\n".format(self.dcnm_version))


class InventoryData:
def __init__(self):

self.class_name = self.__class__.__name__
self.inventory_data = None
self._module = None
self._fabric = None

@property
def module(self):
return self._module

@module.setter
def module(self, value):
self._module = value

@property
def fabric(self):
return self._fabric

@fabric.setter
def fabric(self, value):
self._fabric = value

def commit(self):

self.log = logging.getLogger(f"dcnm.{self.class_name}")

if self._module is None:
msg = f"{0}.commit(): ".format(self.class_name)
msg += "module is not set, which is required."
raise ValueError(msg)

if self._fabric is None:
msg = f"{0}.commit(): ".format(self.class_name)
msg += "fabric is not set, which is required."
raise ValueError(msg)

self.inventory_data = get_fabric_inventory_details(
self._module, self._fabric
)

inv_data = [
{
"IP": d["ipAddress"],
"Sno": d["serialNumber"],
"Logical Name": d["logicalName"],
"Managable": d["managable"],
"Role": d["switchRoleEnum"],
}
for d in self.inventory_data.values()
]
self.log.debug(f"Inventory Data = {0}\n".format(inv_data))


class FabricInfo:
def __init__(self):
self.class_name = self.__class__.__name__
self.monitoring = []
self._module = None
self._fabric = None
self._rest_send = None
self._paths = None

@property
def module(self):
return self._module

@module.setter
def module(self, value):
self._module = value

@property
def fabric(self):
return self._fabric

@fabric.setter
def fabric(self, value):
self._fabric = value

@property
def paths(self):
return self._paths

@paths.setter
def paths(self, value):
self._paths = value

@property
def rest_send(self):
return self._rest_send

@rest_send.setter
def rest_send(self, value):
self._rest_send = value

def commit(self):

self.log = logging.getLogger(f"dcnm.{self.class_name}")

if self._module is None:
msg = f"{0}.commit(): ".format(self.class_name)
msg += "module is not set, which is required."
raise ValueError(msg)

if self._fabric is None:
msg = f"{0}.commit(): ".format(self.class_name)
msg += "fabric is not set, which is required."
raise ValueError(msg)

if self._rest_send is None:
msg = f"{0}.commit(): ".format(self.class_name)
msg += "rest_send is not set, which is required."
raise ValueError(msg)

if self._paths is None:
msg = f"{0}.commit(): ".format(self.class_name)
msg += "paths is not set, which is required."
raise ValueError(msg)

processed_fabrics = []
processed_fabrics.append(self._fabric)

# Get all fabrics which are in monitoring mode. Deploy must be avoided to all fabrics which are part of this list
for fabric in processed_fabrics:

path = self._paths["FABRIC_ACCESS_MODE"].format(fabric)

self._rest_send.path = path
self._rest_send.verb = "GET"
self._rest_send.payload = None
self._rest_send.commit()

resp = self._rest_send.response[0]

self.log.debug(f"RST: Fabric Access Mode Resp = {0}\n".format(resp))

if resp and resp["RETURN_CODE"] == 200:
if str(resp["DATA"]["readonly"]).lower() == "true":
self.monitoring.append(fabric)

# Check if source fabric is in monitoring mode. If so return an error, since fabrics in monitoring mode do not allow
# create/modify/delete and deploy operations.
if self._fabric in self.monitoring:
self._module.fail_json(
msg="Error: Source Fabric '{0}' is in Monitoring mode, No changes are allowed on the fabric\n".format(
self._fabric
)
)


class SwitchInfo:
def __init__(self):
self.class_name = self.__class__.__name__
self._inventory_data = None

@property
def inventory_data(self):
return self._inventory_data

@inventory_data.setter
def inventory_data(self, value):
self._inventory_data = value

def commit(self):

self.log = logging.getLogger(f"dcnm.{self.class_name}")

if self._inventory_data is None:
msg = f"{0}.commit(): ".format(self.class_name)
msg += "inventory data is not set, which is required."
raise ValueError(msg)

self.dcnm_update_switch_mapping_info()
self.dcnm_update_switch_managability_info()

def dcnm_update_switch_mapping_info(self):

# Based on the updated inventory_data, update ip_sn, hn_sn and sn_hn objects
self.ip_sn, self.hn_sn = get_ip_sn_dict(self.inventory_data)
self.sn_hn = dict([(value, key) for key, value in self.hn_sn.items()])
self.sn_ip = dict([(value, key) for key, value in self.ip_sn.items()])

self.log.debug(f"IP_SN = {0}\n".format(self.ip_sn))
self.log.debug(f"SN_HN = {0}\n".format(self.sn_hn))
self.log.debug(f"SN_IP = {0}\n".format(self.sn_ip))

def dcnm_update_switch_managability_info(self):

# Get all switches which are managable. Deploy must be avoided to all switches which are not part of this list
managable_ip = [
(key, self.inventory_data[key]["serialNumber"])
for key in self.inventory_data
if str(self.inventory_data[key]["managable"]).lower() == "true"
]
managable_hosts = [
(
self.inventory_data[key]["logicalName"],
self.inventory_data[key]["serialNumber"],
)
for key in self.inventory_data
if str(self.inventory_data[key]["managable"]).lower() == "true"
]
self.managable = dict(managable_ip + managable_hosts)

self.meta_switches = [
(
key,
self.inventory_data[key]["logicalName"],
self.inventory_data[key]["serialNumber"],
)
for key in self.inventory_data
if self.inventory_data[key]["switchRoleEnum"] is None
]

self.log.debug(f"Meta Switches = {0}\n".format(self.meta_switches))
self.log.debug(f"Managable Switches = {0}\n".format(self.managable))
Loading
Loading