Skip to content

Commit f484304

Browse files
authored
Merge pull request #436 from netascode/0.4.3
Release 0.4.3
2 parents 13cc182 + 6f62170 commit f484304

File tree

52 files changed

+1751
-56
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1751
-56
lines changed

CHANGELOG.rst

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,41 @@ This project adheres to `Semantic Versioning <http://semver.org/>`_.
88

99
.. contents:: ``Release Versions``
1010

11+
`0.4.3`_
12+
=====================
13+
14+
**Release Date:** ``2025-07-02``
15+
16+
Added
17+
-----
18+
19+
* Added support for manual underlay IP address allocation
20+
* Added support for manually allocating vPC domain IDs
21+
* Added support for breakout interfaces
22+
* Added support for dot1q interface type
23+
* Added support for orphan ports, duplex, and native VLAN for interface types access, access port-channel, trunk, and trunk port-channel
24+
25+
Modified
26+
--------
27+
28+
* Updated defaults to include ``domain_id`` and ``lb_id`` defaults for PTP
29+
* Removed the requirement to have ports defined for ``vxlan.overlay.networks.network_attach_groups`` in VXLAN fabrics
30+
* Updated POAP and pre-provision workflow
31+
* This update allows devices to be discovered using discovery mode, poap and pre-provision workflows. Previously the solution did not allow both poap and pre-provision in the same datafile.
32+
* Note: The poap.boostrap setting under the device is only used for POAP mode without pre-provision first. It is not used by a pre-provision or pre-provision + POAP workflow.
33+
34+
Fixed
35+
-----
36+
* https://github.com/netascode/ansible-dc-vxlan/issues/32
37+
* https://github.com/netascode/ansible-dc-vxlan/issues/388
38+
* https://github.com/netascode/ansible-dc-vxlan/issues/391
39+
* https://github.com/netascode/ansible-dc-vxlan/issues/400
40+
* https://github.com/netascode/ansible-dc-vxlan/issues/405
41+
* https://github.com/netascode/ansible-dc-vxlan/issues/409
42+
* https://github.com/netascode/ansible-dc-vxlan/issues/411
43+
* https://github.com/netascode/ansible-dc-vxlan/issues/421
44+
* https://github.com/netascode/ansible-dc-vxlan/issues/424
45+
1146
`0.4.2`_
1247
=====================
1348

@@ -46,15 +81,15 @@ Modified
4681

4782
Fixed
4883
-----
49-
https://github.com/netascode/ansible-dc-vxlan/issues/239
50-
https://github.com/netascode/ansible-dc-vxlan/issues/262
51-
https://github.com/netascode/ansible-dc-vxlan/issues/349
52-
https://github.com/netascode/ansible-dc-vxlan/issues/350
53-
https://github.com/netascode/ansible-dc-vxlan/issues/352
54-
https://github.com/netascode/ansible-dc-vxlan/issues/371
55-
https://github.com/netascode/ansible-dc-vxlan/issues/373
56-
https://github.com/netascode/ansible-dc-vxlan/issues/380
57-
https://github.com/netascode/ansible-dc-vxlan/issues/386
84+
* https://github.com/netascode/ansible-dc-vxlan/issues/239
85+
* https://github.com/netascode/ansible-dc-vxlan/issues/262
86+
* https://github.com/netascode/ansible-dc-vxlan/issues/349
87+
* https://github.com/netascode/ansible-dc-vxlan/issues/350
88+
* https://github.com/netascode/ansible-dc-vxlan/issues/352
89+
* https://github.com/netascode/ansible-dc-vxlan/issues/371
90+
* https://github.com/netascode/ansible-dc-vxlan/issues/373
91+
* https://github.com/netascode/ansible-dc-vxlan/issues/380
92+
* https://github.com/netascode/ansible-dc-vxlan/issues/386
5893

5994
`0.4.1`_
6095
=====================
@@ -251,6 +286,7 @@ The following roles have been added to the collection:
251286

252287
This version of the collection includes support for an IPv4 Underlay only. Support for IPv6 Underlay will be available in the next release.
253288

289+
.. _0.4.3: https://github.com/netascode/ansible-dc-vxlan/compare/0.4.2...0.4.3
254290
.. _0.4.2: https://github.com/netascode/ansible-dc-vxlan/compare/0.4.1...0.4.2
255291
.. _0.4.1: https://github.com/netascode/ansible-dc-vxlan/compare/0.4.0...0.4.1
256292
.. _0.4.0: https://github.com/netascode/ansible-dc-vxlan/compare/0.3.0...0.4.0

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
![Actions Status](https://github.com/netascode/ansible-dc-vxlan/actions/workflows/main.yml/badge.svg?branch=develop)
44

5-
NetAsCode DC VXLAN (nac_dc_vxlan) Ansible Collection for configuring Cisco VXLAN EVPN fabrics using the Cisco Nexus Dashboard Fabric Controller (NDFC). This collection simplifies the configuration of VXLAN fabrics by abstracting the automation using a data model that represents the desired state of the fabric. With this collection, an operator only needs to modify the configuration state in the data model instead of creating custom playbooks with modules and the associated parameters.
5+
NetAsCode DC VXLAN (nac_dc_vxlan) Ansible Collection for configuring Cisco VXLAN EVPN fabrics using the Cisco Nexus Dashboard Fabric Controller (NDFC). This collection simplifies the configuration of VXLAN fabrics by abstracting the automation using a [data model](https://netascode.cisco.com/docs/data_models/vxlan/overview/) that represents the desired state of the fabric. With this collection, an operator only needs to modify the configuration state in the data model instead of creating custom playbooks with modules and the associated parameters.
66

77
This approach allows for consistent and repeatable configuration of VXLAN fabrics and aligns with Infrastructure as Code (IaC) methodology, where the configuration state of NDFC is saved in a version control system and managed as code.
88

@@ -86,9 +86,9 @@ The following control variables are available in this collection.
8686
| `interface_delete_mode` | Remove interface state as part of the remove role | `false` |
8787
| `inventory_delete_mode` | Remove inventory state as part of the remove role | `false` |
8888
| `link_vpc_delete_mode` | Remove vpc link state as part of the remove role | `false` |
89-
| `multisite_child_fabric_delete_mode` | Remove child fabric from MSD/MFD fabric as part of the remove role | `false` |
90-
| `multisite_network_delete_mode` | Remove network state as part of the remove role for multisite (MSD and MFD) fabrics | `false` |
91-
| `multisite_vrf_delete_mode` | Remove vrf state as part of the remove role for multisite (MSD and MFD) fabrics | `false` |
89+
| `multisite_child_fabric_delete_mode` | Remove child fabric from MSD fabric as part of the remove role | `false` |
90+
| `multisite_network_delete_mode` | Remove network state as part of the remove role for multisite (MSD) fabrics | `false` |
91+
| `multisite_vrf_delete_mode` | Remove vrf state as part of the remove role for multisite (MSD) fabrics | `false` |
9292
| `network_delete_mode` | Remove network state as part of the remove role | `false` |
9393
| `policy_delete_mode` | Remove policy state as part of the remove role | `false` |
9494
| `vrf_delete_mode` | Remove vrf state as part of the remove role | `false` |
@@ -416,7 +416,7 @@ A Multi-Site Domain (MSD) is a multifabric administrative domain that is created
416416
### To configure and manage MSD fabrics with VXLAN as Code, you should use the following workflow:
417417
1. Create each member/child fabric that will be managed by MSD using the normal data models for each fabric (or use a combined data model with all child fabrics)
418418
2. Create the MSD fabric. In the data model set the fabric type to MSD and specify each child fabric that will be managed.
419-
Reference the [VXLAN Data Model](https://netascode.cisco.com/data_model/vxlan/overview)
419+
Reference the [VXLAN MultiSite Data Model](https://netascode.cisco.com/docs/data_models/vxlan/multisite/multisite/)
420420
> [!NOTE]
421421
> Any additional changes can be done using the MSD fabric data model or on an individual fabric basis using the respective playbooks.
422422

docs/maintainers.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@ When we are considering publishing a new release, all of the following steps mus
1414
1. Update [galaxy.yml](https://github.com/netascode/ansible-dc-vxlan/blob/develop/galaxy.yml) file
1515
* Update Version
1616
```diff
17-
- "version": "1.0.0",
18-
+ "version": "1.0.1",
17+
- "version": "0.4.0-dev",
18+
+ "version": "0.4.1-dev",
1919
```
2020
* Update authors as required
2121
* Update dependencies as required
2222

2323
1. Update [changelog.](https://github.com/netascode/ansible-dc-vxlan/blob/develop/CHANGELOG.rst)
2424
* Make sure CHANGELOG.md accurately reflects all changes since the last release
25-
* Apply a search filter: `is:issue closed:>=2025-03-01`
25+
* Check all issues closed with search filter: `is:issue closed:>=2025-03-01`
26+
* Check all PRs merged with search filter: `is:pr merged:>=2025-03-01`
2627
* Add any significant changes that weren't documented in the changelog
2728
* Clean up any entries that are overly verbose, unclear, or otherwise could be improved
2829
* Indicate new support (if any)
@@ -36,23 +37,30 @@ When we are considering publishing a new release, all of the following steps mus
3637
1. Scrub README docs
3738
* Update README docs for new support and where applicable
3839

39-
1. Pull release branch based on the `develop` branch
40+
1. Create a release branch based on the `develop` branch
4041
* 0.0.x - a bugfix release
4142
* 0.x.0 - new feature(s)
4243
* x.0.0 - backward-incompatible change (if unvoidable!)
44+
45+
1. On the release branch, edit galaxy.yml and remove the "-dev" from the version
46+
* version: 0.4.1 (instead of version: 0.4.1-dev)
4347

4448
1. Open pull request from release branch against the `main` branch
4549
* Ensure all GitHub Actions tasks have passed
4650
* Merge `release branch` into `main` after approval as `merge commit`
4751

4852
### Post-Merge to `main` branch:
4953

50-
1. Create annotated git tag for the release
54+
1. git clone the repo in a new directory and create annotated git tag for the release
5155
* [HowTo](https://git-scm.com/book/en/v2/Git-Basics-Tagging#Annotated-Tags)
56+
* git clone ....
57+
* git switch main
58+
* git tag -a 0.4.1 -m "Release 0.4.1"
59+
* git show 0.4.1
5260

5361
1. Draft a [new release](https://github.com/netascode/ansible-dc-vxlan/releases) on GitHub
5462

55-
1. Investigating. Merge `main` branch back into `develop` branch safely
63+
1. (Investigating. Merge `main` branch back into `develop` branch safely)
5664

5765
### Publish Release to Ansible Galaxy:
5866

galaxy.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
namespace: cisco
33
name: nac_dc_vxlan
4-
version: 0.4.2
4+
version: 0.4.3
55
readme: README.md
66
authors:
77
- Devendra Gupta <devegupt>
@@ -27,5 +27,5 @@ tags: [cisco, ndfc, dcnm, nxos, networking, vxlan, evpn, nac, sac]
2727

2828
dependencies:
2929
"ansible.netcommon": ">=4.1.0"
30-
"cisco.dcnm": ">=3.8.0"
30+
"cisco.dcnm": ">=3.8.1"
3131
"community.general": ">=8.5.0"

plugins/action/common/prepare_plugins/prep_105_topology_interfaces.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def __init__(self, **kwargs):
2929
# interface modes which are a direct match
3030
self.mode_direct = ['routed', 'routed_po', 'routed_sub', 'loopback', 'fabric_loopback', 'mpls_loopback']
3131
# interface modes which need additional validation
32-
self.mode_indirect = ['access', 'trunk', 'access_po', 'trunk_po', 'access_vpc', 'trunk_vpc', 'all']
32+
self.mode_indirect = ['access', 'dot1q', 'trunk', 'access_po', 'trunk_po', 'access_vpc', 'trunk_vpc', 'all']
3333

3434
def prepare(self):
3535
model_data = self.kwargs['results']['model_extended']
@@ -41,6 +41,10 @@ def prepare(self):
4141
model_data['vxlan']['topology']['interfaces'] = {}
4242
model_data['vxlan']['topology']['interfaces']['modes'] = {}
4343

44+
# Initialize breakout interfaces
45+
model_data['vxlan']['topology']['interfaces']['modes']['breakout'] = {}
46+
model_data['vxlan']['topology']['interfaces']['modes']['breakout']['count'] = 0
47+
4448
# loop through interface modes and initialize with interface count 0
4549
for mode in self.mode_direct:
4650
model_data['vxlan']['topology']['interfaces']['modes'][mode] = {}
@@ -72,6 +76,9 @@ def prepare(self):
7276
else:
7377
model_data['vxlan']['topology']['interfaces']['modes']['access']['count'] += 1
7478
model_data['vxlan']['topology']['interfaces']['modes']['all']['count'] += 1
79+
if interface.get('mode') == 'dot1q':
80+
model_data['vxlan']['topology']['interfaces']['modes']['dot1q']['count'] += 1
81+
model_data['vxlan']['topology']['interfaces']['modes']['all']['count'] += 1
7582
if interface.get('mode') == 'trunk':
7683
# if interface name starts with 'po' and has vpc_id, then it is a vpc trunk interface
7784
if interface.get('name').lower().startswith('po') and interface.get('vpc_id'):
@@ -86,5 +93,13 @@ def prepare(self):
8693
model_data['vxlan']['topology']['interfaces']['modes']['trunk']['count'] += 1
8794
model_data['vxlan']['topology']['interfaces']['modes']['all']['count'] += 1
8895

96+
if switch.get('interface_breakouts'):
97+
for breakout in switch.get('interface_breakouts'):
98+
if breakout.get('to'):
99+
nb_int = breakout['to'] - breakout['from']
100+
model_data['vxlan']['topology']['interfaces']['modes']['breakout']['count'] += nb_int + 1
101+
else:
102+
model_data['vxlan']['topology']['interfaces']['modes']['breakout']['count'] += 1
103+
89104
self.kwargs['results']['model_extended'] = model_data
90105
return self.kwargs['results']

plugins/action/dtc/get_poap_data.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,11 @@ def run(self, tmp=None, task_vars=None):
225225
workflow = POAPDevice(params)
226226
workflow.refresh_discovered()
227227
workflow.check_poap_supported_switches()
228-
workflow.check_preprovision_supported_switches()
228+
#
229+
# TBD: Don't think we need this
230+
# workflow.check_preprovision_supported_switches()
229231

230-
if workflow.poap_supported_switches and not workflow.preprovision_supported_switches:
232+
if workflow.poap_supported_switches:
231233
workflow.refresh()
232234

233235
if workflow.refresh_succeeded:
@@ -240,6 +242,9 @@ def run(self, tmp=None, task_vars=None):
240242
# role is executed later in this run.
241243
fail_msg = workflow.refresh_message
242244
match_text = r"Please\s+enable\s+the\s+DHCP\s+in\s+Fabric\s+Settings\s+to\s+start\s+the\s+bootstrap"
245+
if re.search(match_text, fail_msg, re.IGNORECASE):
246+
pass
247+
match_text = r"Invalid\s+Fabric"
243248
if re.search(match_text, fail_msg, re.IGNORECASE):
244249
pass
245250
else:

plugins/action/dtc/prepare_msite_data.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from ansible.plugins.action import ActionBase
2929
from ...plugin_utils.helper_functions import ndfc_get_fabric_attributes
3030
from ...plugin_utils.helper_functions import ndfc_get_fabric_switches
31+
import re
3132

3233
display = Display()
3334

@@ -88,7 +89,9 @@ def run(self, tmp=None, task_vars=None):
8889
for switch in model_data['vxlan']['multisite']['overlay']['vrf_attach_groups_dict'][grp['name']]:
8990
for child_fabric in child_fabrics_data.keys():
9091
for sw in child_fabrics_data[child_fabric]['switches']:
91-
if switch['hostname'] == sw['hostname']:
92+
# Compare switches with regex to catch hostname when ip domain-name is configured
93+
regex_pattern = f"^{switch['hostname']}$|^{switch['hostname']}\\..*$"
94+
if re.search(regex_pattern, sw['hostname']):
9295
switch['mgmt_ip_address'] = sw['mgmt_ip_address']
9396

9497
# Append switch to a flat list of switches for cross comparison later when we query the
@@ -116,7 +119,8 @@ def run(self, tmp=None, task_vars=None):
116119
for switch in model_data['vxlan']['multisite']['overlay']['network_attach_groups_dict'][grp['name']]:
117120
for child_fabric in child_fabrics_data.keys():
118121
for sw in child_fabrics_data[child_fabric]['switches']:
119-
if switch['hostname'] == sw['hostname']:
122+
regex_pattern = f"^{switch['hostname']}$|^{switch['hostname']}\\..*$"
123+
if re.search(regex_pattern, sw['hostname']):
120124
switch['mgmt_ip_address'] = sw['mgmt_ip_address']
121125
# Append switch to a flat list of switches for cross comparison later when we query the
122126
# MSD fabric information. We need to stop execution if the list returned by the MSD query

plugins/action/dtc/unmanaged_child_fabric_networks.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,12 @@ def run(self, tmp=None, task_vars=None):
150150
# },
151151
# "_ansible_parsed": true
152152
# }
153+
diff_ndfc_network_names = []
153154
if ndfc_networks.get('response'):
154155
ndfc_network_names = [ndfc_network['parent']['networkName'] for ndfc_network in ndfc_networks['response']]
155-
156-
# Take the difference between the networks in the data model and the networks in NDFC
157-
# If the network is in NDFC but not in the data model, delete it
158-
diff_ndfc_network_names = [ndfc_network_name for ndfc_network_name in ndfc_network_names if ndfc_network_name not in network_names]
156+
# Take the difference between the networks in the data model and the networks in NDFC
157+
# If the network is in NDFC but not in the data model, delete it
158+
diff_ndfc_network_names = [ndfc_network_name for ndfc_network_name in ndfc_network_names if ndfc_network_name not in network_names]
159159

160160
if diff_ndfc_network_names:
161161
config = []

plugins/action/dtc/unmanaged_child_fabric_vrfs.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,13 @@ def run(self, tmp=None, task_vars=None):
146146
# },
147147
# "_ansible_parsed": true
148148
# }
149+
diff_ndfc_vrf_names = []
149150
if ndfc_vrfs.get('response'):
150151
ndfc_vrf_names = [ndfc_vrf['parent']['vrfName'] for ndfc_vrf in ndfc_vrfs['response']]
151152

152-
# Take the difference between the vrfs in the data model and the vrfs in NDFC
153-
# If the vrf is in NDFC but not in the data model, delete it
154-
diff_ndfc_vrf_names = [ndfc_vrf_name for ndfc_vrf_name in ndfc_vrf_names if ndfc_vrf_name not in vrf_names]
153+
# Take the difference between the vrfs in the data model and the vrfs in NDFC
154+
# If the vrf is in NDFC but not in the data model, delete it
155+
diff_ndfc_vrf_names = [ndfc_vrf_name for ndfc_vrf_name in ndfc_vrf_names if ndfc_vrf_name not in vrf_names]
155156

156157
if diff_ndfc_vrf_names:
157158
config = []

plugins/plugin_utils/helper_functions.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,12 @@ def ndfc_get_fabric_switches(self, task_vars, tmp, fabric):
225225

226226
fabric_switches = []
227227
for fabric_switch in fabric_response['response']:
228-
fabric_switches.append(
229-
{
230-
'hostname': fabric_switch['hostName'],
231-
'mgmt_ip_address': fabric_switch['ipAddress']
232-
}
233-
)
228+
if 'hostName' in fabric_switch:
229+
fabric_switches.append(
230+
{
231+
'hostname': fabric_switch['hostName'],
232+
'mgmt_ip_address': fabric_switch['ipAddress']
233+
}
234+
)
234235

235236
return fabric_switches

0 commit comments

Comments
 (0)