Skip to content

Commit 4350752

Browse files
committed
Add SAG Support
AI-assisted: Claude Code Signed-off-by: Freerk-Ole Zakfeld <fzakfeld@scaleuptech.com> Avoid requiring gwmac when all anycast addresses for all VLANs are invalid. AI-assisted: Claude Code Signed-off-by: Freerk-Ole Zakfeld <fzakfeld@scaleuptech.com>
1 parent a84614c commit 4350752

2 files changed

Lines changed: 62 additions & 11 deletions

File tree

osism/tasks/conductor/netbox.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,15 +246,25 @@ def get_device_vlans(device):
246246
ip_addresses = interface_ips_map.get(interface.id, [])
247247

248248
addresses = []
249+
anycast_addresses = []
249250
for ip_addr in ip_addresses:
250251
if ip_addr.address:
251-
addresses.append(ip_addr.address)
252+
role = getattr(ip_addr, "role", None)
253+
role_value = (
254+
getattr(role, "value", None) if role else None
255+
)
256+
if role_value == "anycast":
257+
anycast_addresses.append(ip_addr.address)
258+
else:
259+
addresses.append(ip_addr.address)
252260

253-
if addresses:
261+
if addresses or anycast_addresses:
254262
if vid not in vlan_interfaces:
255263
vlan_interfaces[vid] = {}
256-
# Store all IP addresses for this VLAN interface
257-
vlan_interfaces[vid]["addresses"] = addresses
264+
if addresses:
265+
vlan_interfaces[vid]["addresses"] = addresses
266+
if anycast_addresses:
267+
vlan_interfaces[vid]["anycast_addresses"] = anycast_addresses
258268
except (ValueError, IndexError):
259269
# Skip if interface name doesn't follow Vlan<number> pattern
260270
pass

osism/tasks/conductor/sonic/config_generator.py

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,17 +1736,58 @@ def _add_vlan_configuration(config, vlan_info, netbox_interfaces, device):
17361736
member_key = f"{vlan_name}|{sonic_interface_name}"
17371737
config["VLAN_MEMBER"][member_key] = {"tagging_mode": tagging_mode}
17381738

1739-
# Add VLAN interfaces (SVIs)
1739+
# Add VLAN interfaces (SVIs) and SAG entries
1740+
sag_enabled = False
17401741
for vid, interface_data in vlan_info["vlan_interfaces"].items():
17411742
vlan_name = f"Vlan{vid}"
1742-
if "addresses" in interface_data and interface_data["addresses"]:
1743-
# Add the VLAN interface
1743+
addresses = interface_data.get("addresses", [])
1744+
anycast_addresses = interface_data.get("anycast_addresses", [])
1745+
1746+
if addresses or anycast_addresses:
1747+
# Add the VLAN interface base entry
17441748
config["VLAN_INTERFACE"][vlan_name] = {"admin_status": "up"}
17451749

1746-
# Add IP configuration for each address (IPv4 and IPv6)
1747-
for address in interface_data["addresses"]:
1748-
ip_key = f"{vlan_name}|{address}"
1749-
config["VLAN_INTERFACE"][ip_key] = {}
1750+
# Add regular IP configuration for each address (IPv4 and IPv6)
1751+
for address in addresses:
1752+
ip_key = f"{vlan_name}|{address}"
1753+
config["VLAN_INTERFACE"][ip_key] = {}
1754+
1755+
# Add SAG entries for anycast addresses
1756+
if anycast_addresses:
1757+
if "SAG" not in config:
1758+
config["SAG"] = {}
1759+
ipv4_anycast = []
1760+
ipv6_anycast = []
1761+
for addr in anycast_addresses:
1762+
try:
1763+
ip_obj = ipaddress.ip_interface(addr)
1764+
if ip_obj.version == 4:
1765+
ipv4_anycast.append(addr)
1766+
elif ip_obj.version == 6:
1767+
ipv6_anycast.append(addr)
1768+
except ValueError:
1769+
logger.warning(f"Invalid anycast IP address format: {addr}")
1770+
if ipv4_anycast:
1771+
sag_enabled = True
1772+
config["SAG"][f"{vlan_name}|IPv4"] = {"gwip": ipv4_anycast}
1773+
if ipv6_anycast:
1774+
sag_enabled = True
1775+
config["SAG"][f"{vlan_name}|IPv6"] = {"gwip": ipv6_anycast}
1776+
1777+
if sag_enabled:
1778+
gwmac = device.config_context.get("_sag_gwmac")
1779+
if not gwmac:
1780+
raise ValueError(
1781+
f"Device {device.name} has SAG anycast addresses but no '_sag_gwmac' "
1782+
"defined in its config context"
1783+
)
1784+
if "SAG_GLOBAL" not in config:
1785+
config["SAG_GLOBAL"] = {}
1786+
config["SAG_GLOBAL"]["IP"] = {
1787+
"IPv4": "enable",
1788+
"IPv6": "enable",
1789+
"gwmac": gwmac,
1790+
}
17501791

17511792

17521793
def _add_loopback_configuration(config, loopback_info):

0 commit comments

Comments
 (0)