Download scripts/patch_yang_more_vendors.py from gesh75/multivendor-cli-configurator: direct link, hf CLI and curl.
- Browser
- Download file 24.9 kB
-
https://huggingface.co/spaces/gesh75/multivendor-cli-configurator/resolve/main/scripts/patch_yang_more_vendors.py
- Command line
-
hf download hf://spaces/gesh75/multivendor-cli-configurator/scripts/patch_yang_more_vendors.py
-
curl -L -o patch_yang_more_vendors.py https://huggingface.co/spaces/gesh75/multivendor-cli-configurator/resolve/main/scripts/patch_yang_more_vendors.py
24.9 kB
| #!/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() | |