File size: 24,871 Bytes
1bd64c1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | #!/usr/bin/env python3
"""
patch_yang_more_vendors.py — close Automate fallback gaps.
Previously Huawei / NVIDIA / SONiC / Extreme / Mikrotik fell through to
AUTO_*.Cisco (dangerous YANG/IOS snippets). This pass injects CLI-first
Netmiko/Ansible renderers for those vendors into every AUTO_* map.
Idempotent via /* MORE_VENDOR_AUTO_EXT */ marker.
"""
from __future__ import annotations
import pathlib
import re
import sys
ROOT = pathlib.Path(__file__).resolve().parent.parent
HTML = ROOT / "index.html"
MARKER = "/* MORE_VENDOR_AUTO_EXT — Huawei/NVIDIA/SONiC/Extreme/Mikrotik */"
MORE_HELPERS = r'''
/* MORE_VENDOR_AUTO_EXT — Huawei/NVIDIA/SONiC/Extreme/Mikrotik */
function moreIfaceIpv4(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei VRP interface IPv4",
[`system-view`,`interface ${v.ifname}`,`ip address ${v.ip} ${v.mask}`,`quit`],
`- name: VRP IPv4 ${v.ifname}
community.network.ce_config:
lines:
- interface ${v.ifname}
- ip address ${v.ip} ${v.mask}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVIDIA NVUE interface IPv4",
[`nv set interface ${v.ifname} ip address ${v.ip}/${v.cidr}`,`nv config apply`],
`- name: NVUE IPv4 ${v.ifname}
nvidia.nvue.command:
commands:
- nv set interface ${v.ifname} ip address ${v.ip}/${v.cidr}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC interface IPv4",
[`sudo config interface ip add ${v.ifname} ${v.ip}/${v.cidr}`],
`- name: SONiC IPv4 ${v.ifname}
ansible.builtin.shell: sudo config interface ip add ${v.ifname} ${v.ip}/${v.cidr}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("Extreme EXOS interface IPv4",
[`configure vlan ${v.ifname} ipaddress ${v.ip} ${v.mask}`],
`- name: EXOS IPv4
community.network.exos_config:
lines:
- configure vlan ${v.ifname} ipaddress ${v.ip} ${v.mask}`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS interface IPv4",
[`/ip address add address=${v.ip}/${v.cidr} interface=${v.ifname}`],
`- name: RouterOS IPv4
community.routeros.command:
commands:
- /ip address add address=${v.ip}/${v.cidr} interface=${v.ifname}`), "mikrotik_routeros");
return null;
}
function moreStatic(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei static route",
[`system-view`,`ip route-static ${v.prefix} ${v.mask} ${v.nh}`],
`- name: VRP static
community.network.ce_config:
lines:
- ip route-static ${v.prefix} ${v.mask} ${v.nh}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE static route",
[`nv set vrf default router static ${v.prefix}/${v.cidr} via ${v.nh}`,`nv config apply`],
`- name: NVUE static
nvidia.nvue.command:
commands:
- nv set vrf default router static ${v.prefix}/${v.cidr} via ${v.nh}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC static route",
[`sudo config route add prefix ${v.prefix}/${v.cidr} nexthop ${v.nh}`],
`- name: SONiC static
ansible.builtin.shell: sudo config route add prefix ${v.prefix}/${v.cidr} nexthop ${v.nh}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS static route",
[`configure iproute add ${v.prefix} ${v.mask} ${v.nh}`],
`- name: EXOS static
community.network.exos_config:
lines:
- configure iproute add ${v.prefix} ${v.mask} ${v.nh}`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS static route",
[`/ip route add dst-address=${v.prefix}/${v.cidr} gateway=${v.nh}`],
`- name: RouterOS static
community.routeros.command:
commands:
- /ip route add dst-address=${v.prefix}/${v.cidr} gateway=${v.nh}`), "mikrotik_routeros");
return null;
}
function moreOspf(vendor, v){
const area = v.area || "0.0.0.0";
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei OSPF",
[`system-view`,`ospf 1`,`area ${area}`,`network ${v.net || "10.0.0.0"} ${v.wildcard || "0.0.0.255"}`],
`- name: VRP OSPF
community.network.ce_config:
lines:
- ospf 1
- area ${area}
- network ${v.net || "10.0.0.0"} ${v.wildcard || "0.0.0.255"}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE OSPF",
[`nv set vrf default router ospf area ${area}`,`nv config apply`],
`- name: NVUE OSPF
nvidia.nvue.command:
commands:
- nv set vrf default router ospf area ${area}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC OSPF via FRR vtysh",
[`sudo vtysh -c 'configure terminal' -c 'router ospf' -c 'network ${v.net || "10.0.0.0"}/24 area ${area}' -c 'end' -c 'write'`],
`- name: SONiC OSPF
ansible.builtin.shell: sudo vtysh -c 'configure terminal' -c 'router ospf' -c 'network ${v.net || "10.0.0.0"}/24 area ${area}' -c 'end' -c 'write'`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS OSPF",
[`enable ospf`,`configure ospf add vlan ${v.ifname || "UNDERLAY"} area ${area}`],
`- name: EXOS OSPF
community.network.exos_config:
lines:
- enable ospf
- configure ospf add vlan ${v.ifname || "UNDERLAY"} area ${area}`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS OSPF",
[`/routing ospf instance add name=def redistribute=connected`,`/routing ospf interface-template add interfaces=${v.ifname} area=backbone`],
`- name: RouterOS OSPF
community.routeros.command:
commands:
- /routing ospf instance add name=def redistribute=connected`), "mikrotik_routeros");
return null;
}
function moreBgp(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei BGP neighbor",
[`system-view`,`bgp ${v.local_as}`,`peer ${v.peer} as-number ${v.remote_as}`],
`- name: VRP BGP
community.network.ce_config:
lines:
- bgp ${v.local_as}
- peer ${v.peer} as-number ${v.remote_as}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE BGP neighbor",
[`nv set vrf default router bgp autonomous-system ${v.local_as}`,`nv set vrf default router bgp neighbor ${v.peer} remote-as ${v.remote_as}`,`nv config apply`],
`- name: NVUE BGP
nvidia.nvue.command:
commands:
- nv set vrf default router bgp autonomous-system ${v.local_as}
- nv set vrf default router bgp neighbor ${v.peer} remote-as ${v.remote_as}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC BGP neighbor",
[`sudo config bgp autonomous-system ${v.local_as}`,`sudo config bgp neighbor add ${v.peer} remote-as ${v.remote_as}`],
`- name: SONiC BGP
ansible.builtin.shell: |
sudo config bgp autonomous-system ${v.local_as}
sudo config bgp neighbor add ${v.peer} remote-as ${v.remote_as}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS BGP neighbor",
[`enable bgp`,`configure bgp as-number ${v.local_as}`,`configure bgp add neighbor ${v.peer} remote-as ${v.remote_as}`],
`- name: EXOS BGP
community.network.exos_config:
lines:
- enable bgp
- configure bgp as-number ${v.local_as}
- configure bgp add neighbor ${v.peer} remote-as ${v.remote_as}`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS BGP neighbor",
[`/routing bgp connection add name=to-peer remote.address=${v.peer} remote.as=${v.remote_as} local.role=ebgp`],
`- name: RouterOS BGP
community.routeros.command:
commands:
- /routing bgp connection add name=to-peer remote.address=${v.peer} remote.as=${v.remote_as} local.role=ebgp`), "mikrotik_routeros");
return null;
}
function moreVlan(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei VLAN",
[`system-view`,`vlan ${v.id}`,`name ${v.name}`],
`- name: VRP VLAN
community.network.ce_config:
lines:
- vlan ${v.id}
- name ${v.name}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE VLAN",
[`nv set bridge domain br_default vlan ${v.id}`,`nv config apply`],
`- name: NVUE VLAN
nvidia.nvue.command:
commands:
- nv set bridge domain br_default vlan ${v.id}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC VLAN",
[`sudo config vlan add ${v.id}`],
`- name: SONiC VLAN
ansible.builtin.shell: sudo config vlan add ${v.id}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS VLAN",
[`create vlan ${v.name} tag ${v.id}`],
`- name: EXOS VLAN
community.network.exos_config:
lines:
- create vlan ${v.name} tag ${v.id}`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS VLAN",
[`/interface vlan add name=${v.name} vlan-id=${v.id} interface=bridge1`],
`- name: RouterOS VLAN
community.routeros.command:
commands:
- /interface vlan add name=${v.name} vlan-id=${v.id} interface=bridge1`), "mikrotik_routeros");
return null;
}
function moreHostname(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei sysname",
[`system-view`,`sysname ${v.hostname}`],
`- name: VRP sysname
community.network.ce_config:
lines:
- sysname ${v.hostname}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE hostname",
[`nv set system hostname ${v.hostname}`,`nv config apply`],
`- name: NVUE hostname
nvidia.nvue.command:
commands:
- nv set system hostname ${v.hostname}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC hostname",
[`sudo config hostname ${v.hostname}`],
`- name: SONiC hostname
ansible.builtin.shell: sudo config hostname ${v.hostname}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS hostname",
[`configure snmp sysName ${v.hostname}`],
`- name: EXOS hostname
community.network.exos_config:
lines:
- configure snmp sysName ${v.hostname}`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS identity",
[`/system identity set name=${v.hostname}`],
`- name: RouterOS identity
community.routeros.command:
commands:
- /system identity set name=${v.hostname}`), "mikrotik_routeros");
return null;
}
function moreNtp(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei NTP",
[`system-view`,`ntp-service unicast-server ${v.server}`],
`- name: VRP NTP
community.network.ce_config:
lines:
- ntp-service unicast-server ${v.server}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE NTP",
[`nv set system ntp server ${v.server}`,`nv config apply`],
`- name: NVUE NTP
nvidia.nvue.command:
commands:
- nv set system ntp server ${v.server}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC NTP",
[`sudo config ntp add ${v.server}`],
`- name: SONiC NTP
ansible.builtin.shell: sudo config ntp add ${v.server}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS NTP",
[`configure ntp server add ${v.server}`,`enable ntp`],
`- name: EXOS NTP
community.network.exos_config:
lines:
- configure ntp server add ${v.server}
- enable ntp`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS NTP",
[`/system ntp client set enabled=yes servers=${v.server}`],
`- name: RouterOS NTP
community.routeros.command:
commands:
- /system ntp client set enabled=yes servers=${v.server}`), "mikrotik_routeros");
return null;
}
function moreSyslog(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei syslog",
[`system-view`,`info-center loghost ${v.host}`],
`- name: VRP syslog
community.network.ce_config:
lines:
- info-center loghost ${v.host}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE syslog",
[`nv set system syslog server ${v.host}`,`nv config apply`],
`- name: NVUE syslog
nvidia.nvue.command:
commands:
- nv set system syslog server ${v.host}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC syslog",
[`sudo config syslog add ${v.host}`],
`- name: SONiC syslog
ansible.builtin.shell: sudo config syslog add ${v.host}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS syslog",
[`configure syslog add ${v.host} local use-local-time`],
`- name: EXOS syslog
community.network.exos_config:
lines:
- configure syslog add ${v.host} local use-local-time`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS syslog",
[`/system logging action set remote remote=${v.host}`],
`- name: RouterOS syslog
community.routeros.command:
commands:
- /system logging action set remote remote=${v.host}`), "mikrotik_routeros");
return null;
}
function moreGeneric(vendor, lines, ansible, dev){
return _withDev(_autoCliBundle(vendor+" config", lines, ansible), dev);
}
'''
MORE_WRAPPERS = {
"AUTO_IFACE_IPV4": " Huawei: v => moreIfaceIpv4('Huawei', v),\n NVIDIA: v => moreIfaceIpv4('NVIDIA', v),\n SONiC: v => moreIfaceIpv4('SONiC', v),\n Extreme: v => moreIfaceIpv4('Extreme', v),\n Mikrotik: v => moreIfaceIpv4('Mikrotik', v),",
"AUTO_STATIC": " Huawei: v => moreStatic('Huawei', v),\n NVIDIA: v => moreStatic('NVIDIA', v),\n SONiC: v => moreStatic('SONiC', v),\n Extreme: v => moreStatic('Extreme', v),\n Mikrotik: v => moreStatic('Mikrotik', v),",
"AUTO_OSPF": " Huawei: v => moreOspf('Huawei', v),\n NVIDIA: v => moreOspf('NVIDIA', v),\n SONiC: v => moreOspf('SONiC', v),\n Extreme: v => moreOspf('Extreme', v),\n Mikrotik: v => moreOspf('Mikrotik', v),",
"AUTO_BGP": " Huawei: v => moreBgp('Huawei', v),\n NVIDIA: v => moreBgp('NVIDIA', v),\n SONiC: v => moreBgp('SONiC', v),\n Extreme: v => moreBgp('Extreme', v),\n Mikrotik: v => moreBgp('Mikrotik', v),",
"AUTO_VLAN": " Huawei: v => moreVlan('Huawei', v),\n NVIDIA: v => moreVlan('NVIDIA', v),\n SONiC: v => moreVlan('SONiC', v),\n Extreme: v => moreVlan('Extreme', v),\n Mikrotik: v => moreVlan('Mikrotik', v),",
"AUTO_HOSTNAME": " Huawei: v => moreHostname('Huawei', v),\n NVIDIA: v => moreHostname('NVIDIA', v),\n SONiC: v => moreHostname('SONiC', v),\n Extreme: v => moreHostname('Extreme', v),\n Mikrotik: v => moreHostname('Mikrotik', v),",
"AUTO_NTP": " Huawei: v => moreNtp('Huawei', v),\n NVIDIA: v => moreNtp('NVIDIA', v),\n SONiC: v => moreNtp('SONiC', v),\n Extreme: v => moreNtp('Extreme', v),\n Mikrotik: v => moreNtp('Mikrotik', v),",
"AUTO_SYSLOG": " Huawei: v => moreSyslog('Huawei', v),\n NVIDIA: v => moreSyslog('NVIDIA', v),\n SONiC: v => moreSyslog('SONiC', v),\n Extreme: v => moreSyslog('Extreme', v),\n Mikrotik: v => moreSyslog('Mikrotik', v),",
"AUTO_DEFAULTRT": " Huawei: v => moreStatic('Huawei', {prefix:'0.0.0.0', cidr:'0', mask:'0.0.0.0', nh:v.nh}),\n NVIDIA: v => moreStatic('NVIDIA', {prefix:'0.0.0.0', cidr:'0', mask:'0.0.0.0', nh:v.nh}),\n SONiC: v => moreStatic('SONiC', {prefix:'0.0.0.0', cidr:'0', mask:'0.0.0.0', nh:v.nh}),\n Extreme: v => moreStatic('Extreme', {prefix:'0.0.0.0', cidr:'0', mask:'0.0.0.0', nh:v.nh}),\n Mikrotik: v => moreStatic('Mikrotik', {prefix:'0.0.0.0', cidr:'0', mask:'0.0.0.0', nh:v.nh}),",
"AUTO_LOOPBACK": " Huawei: v => moreIfaceIpv4('Huawei', {ifname:v.name||'LoopBack0', ip:v.ip, mask:v.mask, cidr:v.cidr}),\n NVIDIA: v => moreIfaceIpv4('NVIDIA', {ifname:v.name||'lo', ip:v.ip, mask:v.mask, cidr:v.cidr}),\n SONiC: v => moreIfaceIpv4('SONiC', {ifname:v.name||'Loopback0', ip:v.ip, mask:v.mask, cidr:v.cidr}),\n Extreme: v => moreIfaceIpv4('Extreme', {ifname:v.name||'Default', ip:v.ip, mask:v.mask, cidr:v.cidr}),\n Mikrotik: v => moreIfaceIpv4('Mikrotik', {ifname:v.name||'bridge1', ip:v.ip, mask:v.mask, cidr:v.cidr}),",
"AUTO_SWITCHPORT": " Huawei: v => moreGeneric('Huawei', [`system-view`,`interface ${v.ifname}`,`port link-type access`,`port default vlan ${v.vlan}`], `- name: VRP access\\n community.network.ce_config:\\n lines:\\n - interface ${v.ifname}\\n - port default vlan ${v.vlan}`, 'huawei'),\n NVIDIA: v => moreGeneric('NVIDIA', [`nv set interface ${v.ifname} bridge domain br_default access ${v.vlan}`,`nv config apply`], `- name: NVUE access\\n nvidia.nvue.command:\\n commands: ['nv set interface ${v.ifname} bridge domain br_default access ${v.vlan}','nv config apply']`, 'linux'),\n SONiC: v => moreGeneric('SONiC', [`sudo config vlan member add ${v.vlan} ${v.ifname}`], `- name: SONiC access\\n ansible.builtin.shell: sudo config vlan member add ${v.vlan} ${v.ifname}`, 'linux'),\n Extreme: v => moreGeneric('Extreme', [`configure vlan ${v.vlan} add ports ${v.ifname} untagged`], `- name: EXOS access\\n community.network.exos_config:\\n lines:\\n - configure vlan ${v.vlan} add ports ${v.ifname} untagged`, 'extreme_exos'),\n Mikrotik: v => moreGeneric('Mikrotik', [`/interface bridge port set [find interface=${v.ifname}] pvid=${v.vlan}`], `- name: RouterOS access\\n community.routeros.command:\\n commands: ['/interface bridge port set [find interface=${v.ifname}] pvid=${v.vlan}']`, 'mikrotik_routeros'),",
"AUTO_IFDESC": " Huawei: v => moreGeneric('Huawei', [`system-view`,`interface ${v.ifname}`,`description ${v.desc}`], `- name: VRP ifDesc\\n community.network.ce_config:\\n lines:\\n - interface ${v.ifname}\\n - description ${v.desc}`, 'huawei'),\n NVIDIA: v => moreGeneric('NVIDIA', [`nv set interface ${v.ifname} description '${v.desc}'`,`nv config apply`], `- name: NVUE ifDesc\\n nvidia.nvue.command:\\n commands: [\"nv set interface ${v.ifname} description '${v.desc}'\",'nv config apply']`, 'linux'),\n SONiC: v => moreGeneric('SONiC', [`sudo config interface description ${v.ifname} '${v.desc}'`], `- name: SONiC ifDesc\\n ansible.builtin.shell: sudo config interface description ${v.ifname} '${v.desc}'`, 'linux'),\n Extreme: v => moreGeneric('Extreme', [`configure ports ${v.ifname} display-string ${v.desc}`], `- name: EXOS ifDesc\\n community.network.exos_config:\\n lines:\\n - configure ports ${v.ifname} display-string ${v.desc}`, 'extreme_exos'),\n Mikrotik: v => moreGeneric('Mikrotik', [`/interface set ${v.ifname} comment=\"${v.desc}\"`], `- name: RouterOS ifDesc\\n community.routeros.command:\\n commands: ['/interface set ${v.ifname} comment=\"${v.desc}\"']`, 'mikrotik_routeros'),",
"AUTO_TRUNK": " Huawei: v => moreGeneric('Huawei', [`system-view`,`interface ${v.ifname}`,`port link-type trunk`,`port trunk allow-pass vlan ${v.vlans}`], `- name: VRP trunk\\n community.network.ce_config:\\n lines:\\n - interface ${v.ifname}\\n - port trunk allow-pass vlan ${v.vlans}`, 'huawei'),\n NVIDIA: v => moreGeneric('NVIDIA', [`nv set interface ${v.ifname} bridge domain br_default vlan ${v.vlans}`,`nv config apply`], `- name: NVUE trunk\\n nvidia.nvue.command:\\n commands: ['nv set interface ${v.ifname} bridge domain br_default vlan ${v.vlans}','nv config apply']`, 'linux'),\n SONiC: v => moreGeneric('SONiC', [`sudo config vlan member add ${v.vlans.split(',')[0]} ${v.ifname} -t`], `- name: SONiC trunk\\n ansible.builtin.shell: sudo config vlan member add ${v.vlans.split(',')[0]} ${v.ifname} -t`, 'linux'),\n Extreme: v => moreGeneric('Extreme', [`configure vlan ${v.vlans.split(',')[0]} add ports ${v.ifname} tagged`], `- name: EXOS trunk\\n community.network.exos_config:\\n lines:\\n - configure vlan ${v.vlans.split(',')[0]} add ports ${v.ifname} tagged`, 'extreme_exos'),\n Mikrotik: v => moreGeneric('Mikrotik', [`/interface bridge vlan add bridge=bridge1 tagged=${v.ifname} vlan-ids=${v.vlans}`], `- name: RouterOS trunk\\n community.routeros.command:\\n commands: ['/interface bridge vlan add bridge=bridge1 tagged=${v.ifname} vlan-ids=${v.vlans}']`, 'mikrotik_routeros'),",
"AUTO_RADIUS": " Huawei: v => moreGeneric('Huawei', [`system-view`,`radius-server template AAA`,`radius-server shared-key cipher ${v.key}`,`radius-server authentication ${v.host}`], `- name: VRP RADIUS\\n community.network.ce_config:\\n lines:\\n - radius-server authentication ${v.host}`, 'huawei'),\n NVIDIA: v => moreGeneric('NVIDIA', [`nv set system aaa authentication-order radius`,`nv config apply`], `- name: NVUE RADIUS note\\n nvidia.nvue.command:\\n commands: ['nv set system aaa authentication-order radius','nv config apply']`, 'linux'),\n SONiC: v => moreGeneric('SONiC', [`# configure host PAM/RADIUS for SONiC mgmt plane`], `- name: SONiC RADIUS note\\n ansible.builtin.debug:\\n msg: configure host PAM RADIUS`, 'linux'),\n Extreme: v => moreGeneric('Extreme', [`configure radius-server add ${v.host} shared-secret ${v.key}`], `- name: EXOS RADIUS\\n community.network.exos_config:\\n lines:\\n - configure radius-server add ${v.host} shared-secret ${v.key}`, 'extreme_exos'),\n Mikrotik: v => moreGeneric('Mikrotik', [`/radius add address=${v.host} secret=${v.key} service=login`], `- name: RouterOS RADIUS\\n community.routeros.command:\\n commands: ['/radius add address=${v.host} secret=${v.key} service=login']`, 'mikrotik_routeros'),",
"AUTO_PORTCHANNEL": " Huawei: v => moreGeneric('Huawei', [`system-view`,`interface Eth-Trunk${v.pcid}`,`mode lacp-static`,`quit`,`interface ${v.ifname}`,`eth-trunk ${v.pcid}`], `- name: VRP Eth-Trunk\\n community.network.ce_config:\\n lines:\\n - interface ${v.ifname}\\n - eth-trunk ${v.pcid}`, 'huawei'),\n NVIDIA: v => moreGeneric('NVIDIA', [`nv set interface bond${v.pcid} bond member ${v.ifname}`,`nv config apply`], `- name: NVUE bond\\n nvidia.nvue.command:\\n commands: ['nv set interface bond${v.pcid} bond member ${v.ifname}','nv config apply']`, 'linux'),\n SONiC: v => moreGeneric('SONiC', [`sudo config portchannel add PortChannel${v.pcid}`,`sudo config portchannel member add PortChannel${v.pcid} ${v.ifname}`], `- name: SONiC LAG\\n ansible.builtin.shell: |\\n sudo config portchannel add PortChannel${v.pcid}\\n sudo config portchannel member add PortChannel${v.pcid} ${v.ifname}`, 'linux'),\n Extreme: v => moreGeneric('Extreme', [`enable sharing ${v.pcid} grouping ${v.ifname} algorithm address-based L3_L4 lacp`], `- name: EXOS LAG\\n community.network.exos_config:\\n lines:\\n - enable sharing ${v.pcid} grouping ${v.ifname} algorithm address-based L3_L4 lacp`, 'extreme_exos'),\n Mikrotik: v => moreGeneric('Mikrotik', [`/interface bonding add name=bond${v.pcid} slaves=${v.ifname} mode=802.3ad`], `- name: RouterOS bond\\n community.routeros.command:\\n commands: ['/interface bonding add name=bond${v.pcid} slaves=${v.ifname} mode=802.3ad']`, 'mikrotik_routeros'),",
}
def inject_helpers(text: str) -> str:
if MARKER in text:
return text
anchor = "/* Per-vendor template renderers — return {netconf, ncclient, ansible} */"
if anchor not in text:
raise SystemExit("AUTO renderer anchor not found")
return text.replace(anchor, MORE_HELPERS + "\n" + anchor, 1)
def inject_keys(text: str) -> str:
for name, block in MORE_WRAPPERS.items():
flag = f"/* more:{name} */"
if flag in text:
continue
# Prefer inserting after existing stack ext flag, else after const {
stack_flag = f"/* ext:{name} */"
if stack_flag in text:
# insert after the stack wrapper block — find flag and insert after next blank-ish
idx = text.find(stack_flag)
# find end of first vendor block cluster: look for blank line after Aruba/FRR keys
# Simpler: insert right after the flag line
nl = text.find("\n", idx)
insert_at = nl + 1
text = text[:insert_at] + flag + "\n" + block + "\n" + text[insert_at:]
continue
m = re.search(rf"(const\s+{name}\s*=\s*\{{)", text)
if not m:
print(f"WARN: {name} not found", file=sys.stderr)
continue
insert = m.group(1) + "\n" + flag + "\n" + block + "\n"
text = text[: m.start()] + insert + text[m.end() :]
return text
def main() -> None:
text = HTML.read_text()
if MARKER in text and all(f"/* more:{n} */" in text for n in MORE_WRAPPERS):
print("already patched")
return
text = inject_helpers(text)
text = inject_keys(text)
if "--dry-run" in sys.argv:
print("dry-run ok, would write", len(text), "bytes")
return
HTML.write_text(text)
print("patched", HTML, "bytes", len(text))
if __name__ == "__main__":
main()
|