From 3072e1e78c110de8fd484e2a609c5804e8c60694 Mon Sep 17 00:00:00 2001 From: Astro Date: Wed, 3 Nov 2021 01:07:44 +0100 Subject: [PATCH] pkgs/switches: switch from salt to nix --- nix/lib/config/legacy.nix | 63 ++++++++- nix/lib/config/options.nix | 106 ++++++++++++++- nix/pkgs/{ap.sh => ap.nix} | 173 +++++++++++++------------ nix/pkgs/device-templates.nix | 50 ++----- nix/pkgs/switches/3com-4200G.nix | 160 +++++++++++++++++++++++ nix/pkgs/switches/HP-procurve-2824.nix | 141 ++++++++++++++++++++ nix/pkgs/switches/TL-SG3210.nix | 131 +++++++++++++++++++ nix/pkgs/switches/linksys-srw2048.nix | 105 +++++++++++++++ salt-pillar/switches/init.sls | 13 +- salt/switches/3com-4200G.expect | 151 --------------------- salt/switches/HP-procurve-2824.expect | 129 ------------------ salt/switches/TL-SG3210.expect | 115 ---------------- salt/switches/linksys-srw2048.expect | 104 --------------- 13 files changed, 811 insertions(+), 630 deletions(-) rename nix/pkgs/{ap.sh => ap.nix} (69%) create mode 100644 nix/pkgs/switches/3com-4200G.nix create mode 100644 nix/pkgs/switches/HP-procurve-2824.nix create mode 100644 nix/pkgs/switches/TL-SG3210.nix create mode 100644 nix/pkgs/switches/linksys-srw2048.nix delete mode 100644 salt/switches/3com-4200G.expect delete mode 100644 salt/switches/HP-procurve-2824.expect delete mode 100644 salt/switches/TL-SG3210.expect delete mode 100644 salt/switches/linksys-srw2048.expect diff --git a/nix/lib/config/legacy.nix b/nix/lib/config/legacy.nix index bfed439..2506d3e 100644 --- a/nix/lib/config/legacy.nix +++ b/nix/lib/config/legacy.nix @@ -4,6 +4,16 @@ let mainServers = [ "server1" "server2" ]; pillar = self.lib.saltPillarFor "*"; + clusterServerNets = [ + "mgmt" "pub" "core" "serv" + "c3d2" "cluster" "bmx" "priv23" + ]; + clusterServerInterfaces = builtins.foldl' (result: net: + result // { + "${net}".type = "bridge"; + } + ) {} clusterServerNets; + renameAttr = from: to: attrset: builtins.foldl' (result: name: if name == from @@ -317,6 +327,26 @@ in proto = "tcp"; sourcePort = port; }) [ 25 465 587 110 143 993 995 ]; + + server3.interfaces = clusterServerInterfaces; + server5.interfaces = clusterServerInterfaces; + server6.interfaces = clusterServerInterfaces; + server7.interfaces = clusterServerInterfaces; + server8.interfaces = clusterServerInterfaces; + server9.interfaces = clusterServerInterfaces; + + ap-test1.interfaces = { + mgmt.type = "phys"; + pub.type = "bridge"; + c3d2.type = "bridge"; + bmx.type = "bridge"; + }; + ap-test2.interfaces = { + mgmt.type = "phys"; + pub.type = "bridge"; + c3d2.type = "bridge"; + bmx.type = "bridge"; + }; } # host priv*-gw settings @@ -344,18 +374,47 @@ in builtins.foldl' (result: hosts: result // hosts) {} (builtins.attrValues pillar.hosts-inet6) ) ) - ); + ) // builtins.foldl' (result: container: + result // builtins.mapAttrs (net: interface: { + type = "bridge"; + }) container.interfaces + ) {} (builtins.attrValues pillar.containers); }; }) {} mainServers) (builtins.mapAttrs (_: switch: { inherit (switch) model location password; role = "switch"; + links = builtins.mapAttrs (_: { ports, group ? null, ... }: { + group = if group != null + then toString group + else null; + ports = map toString ( + if builtins.isList ports + then ports + else [ ports ] + ); + }) switch.ports; }) pillar.switches) (builtins.mapAttrs (_: ap: { inherit (ap) model location password; role = "ap"; + interfaces = builtins.foldl' (interfaces: net: interfaces // { + "${net}" = { + type = "bridge"; + }; + }) { + mgmt = { + type = "phys"; + gw4 = "mgmt-gw"; + gw6 = "mgmt-gw"; + }; + } ( + builtins.concatMap ({ ssids, ... }: + map ({ net, ... }: net) (builtins.attrValues ssids) + ) (builtins.attrValues ap.radios) + ); }) pillar.cpe) (builtins.mapAttrs (name: container: @@ -395,7 +454,7 @@ in in lib.optionalAttrs (ctPillar ? ospf && ospfConf ? stubnets-inet) { stubNets4 = ospfConf.stubnets-inet; } // lib.optionalAttrs (ctPillar ? ospf && ospfConf ? stubnets-inet6) { - stubNets6 = ospfConf.stubnets-inet6; + stubNets6 = ospfConf.stubnets-inet6; }; bgp = diff --git a/nix/lib/config/options.nix b/nix/lib/config/options.nix index f5a51a9..6b0aa49 100644 --- a/nix/lib/config/options.nix +++ b/nix/lib/config/options.nix @@ -2,6 +2,79 @@ with lib; let + getLinkNets = link: + let + hostConfig = config.site.hosts.${link}; + sort = builtins.sort (net1: net2: + config.site.net.${net1}.vlan < config.site.net.${net2}.vlan + ); + in + if config.site.hosts ? ${link} + then + + if builtins.elem hostConfig.role [ "container" "server" "ap" ] + then sort (builtins.attrNames hostConfig.interfaces) + + else if hostConfig.role == "switch" + then sort (getSwitchNets link) + + else if hostConfig.role == "client" + then if hostConfig.interfaces == {} + then builtins.trace "No known networks implemented for client \"${link}\"" [] + else sort (builtins.attrNames hostConfig.interfaces) + + else throw "getHostNets not implemented for role \"${hostConfig.role}\"" + + else if config.site.net ? ${link} + then [ link ] + + else builtins.trace "Don't know what nets to configure for link to \"${link}\"" []; + + # breaks the getLinkNets recursion for switches, + # requiring any net to be used by at >1 links + getSwitchNets = hostName: + let + linksNets = builtins.mapAttrs (link: _: + unique ( + getSwitchNets' { "${hostName}" = true; } [ link ] + ) + ) config.site.hosts.${hostName}.links; + allNets = unique ( + builtins.concatLists (builtins.attrValues linksNets) + ); + netLinkCount = net: + builtins.foldl' (netLinkCount: nets: + if builtins.elem net nets + then netLinkCount + 1 + else netLinkCount + ) 0 (builtins.attrValues linksNets); + nets = builtins.filter (net: + netLinkCount net > 1 + ) allNets; + in nets; #builtins.trace "getSwitchNets ${hostName} = ${concatStringsSep "," nets}" nets; + + getSwitchNets' = seen: links: + if links == [] + then [] + else + let + link = builtins.head links; + seen' = seen // { + "${link}" = true; + }; + links' = builtins.tail links; + in + if config.site.hosts ? ${link} && + config.site.hosts.${link}.role == "switch" + then getSwitchNets' seen' ( + links' ++ (builtins.attrNames config.site.hosts.${link}.links) + ) + else getLinkNets link ++ + getSwitchNets' seen' ( + builtins.filter (link: ! seen' ? ${link}) + links' + ); + dhcpOpts = { start = mkOption { description = "First IP address in pool"; @@ -136,7 +209,7 @@ let description = "Static MAC address"; }; type = mkOption { - type = types.enum [ "phys" "veth" "pppoe" ]; + type = types.enum [ "phys" "veth" "pppoe" "bridge" ]; description = '' veth: Virtual ethernet to be attached to a bridge. @@ -307,6 +380,11 @@ let type = types.bool; default = false; }; + links = mkOption { + description = "Which port is connected to what other device? Keys are either network names or known hostnames."; + default = {}; + type = with types; attrsOf (submodule linkOpts); + }; }; }; @@ -325,6 +403,32 @@ let default = {}; }; }; + + linkOpts = { name, ... }: { + options = { + ports = mkOption { + type = with types; listOf str; + description = "Port names"; + }; + group = mkOption { + type = with types; nullOr str; + default = null; + description = "Link aggregation group with a fixed number"; + }; + nets = mkOption { + type = with types; listOf str; + description = "Set for clients, automatically generated for others"; + default = getLinkNets name; + }; + vlans = mkOption { + type = with types; listOf int; + description = "Automatically generated, do not set"; + default = map (net: + config.site.net.${net}.vlan + ) (getLinkNets name); + }; + }; + }; in { options.site = { diff --git a/nix/pkgs/ap.sh b/nix/pkgs/ap.nix similarity index 69% rename from nix/pkgs/ap.sh rename to nix/pkgs/ap.nix index 1b66513..838191e 100644 --- a/nix/pkgs/ap.sh +++ b/nix/pkgs/ap.nix @@ -1,18 +1,20 @@ -#!/usr/bin/env bash - -{% macro uci_network_mgmt(ifname) -%} -set network.mgmt=interface -set network.mgmt.ifname={{ ifname }} -set network.mgmt.proto=static -set network.mgmt.ipaddr={{ pillar['hosts-inet']['mgmt'][hostname] }} -set network.mgmt.netmask=255.255.255.0 -set network.mgmt.gateway={{ pillar['hosts-inet']['mgmt']['mgmt-gw'] }} -set network.mgmt.ip6addr={{ pillar['hosts-inet6']['dn42']['mgmt'][hostname] }}/64 -set network.mgmt.ip6gw={{ pillar['hosts-inet6']['dn42']['mgmt']['mgmt-gw'] }} -delete network.mgmt.dns -add_list network.mgmt.dns={{ pillar['hosts-inet']['serv']['dnscache'] }} -add_list network.mgmt.dns={{ pillar['hosts-inet6']['dn42']['serv']['dnscache'] }} -{%- endmacro %} +{ pkgs, hostName, config, hostConfig, ... }: +let + uciNetworkMgmt = ifname: '' + set network.mgmt=interface + set network.mgmt.ifname={{ ifname }} + set network.mgmt.proto=static + set network.mgmt.ipaddr={{ pillar['hosts-inet']['mgmt'][hostName] }} + set network.mgmt.netmask=255.255.255.0 + set network.mgmt.gateway={{ pillar['hosts-inet']['mgmt']['mgmt-gw'] }} + set network.mgmt.ip6addr={{ pillar['hosts-inet6']['dn42']['mgmt'][hostName] }}/64 + set network.mgmt.ip6gw={{ pillar['hosts-inet6']['dn42']['mgmt']['mgmt-gw'] }} + delete network.mgmt.dns + add_list network.mgmt.dns={{ pillar['hosts-inet']['serv']['dnscache'] }} + add_list network.mgmt.dns={{ pillar['hosts-inet6']['dn42']['serv']['dnscache'] }} + ''; +in '' + #! ${pkgs.runtimeShell} -e {%- if conf.get('firstboot') %} ssh-keygen -R 192.168.1.1 @@ -20,7 +22,7 @@ ssh-keygen -R 192.168.1.1 ssh root@192.168.1.1 \ "ash -e -x" <<__SSH__ {%- else %} -ssh root@{{ pillar['hosts-inet']['mgmt'][hostname] }} \ +ssh root@{{ pillar['hosts-inet']['mgmt'][hostName] }} \ "ash -e -x" <<__SSH__ {%- endif %} @@ -32,7 +34,7 @@ echo "{{ pillar['ssh']['pubkey'] }}" > /etc/dropbear/authorized_keys # System configuration uci batch <<__UCI__ -set system.@system[0].hostname={{ hostname }} +set system.@system[0].hostName={{ hostName }} set dhcp.@dnsmasq[0].enabled=0 set system.@system[0].log_ip={{ pillar['hosts-inet']['mgmt']['logging'] }} set system.@system[0].log_proto=udp @@ -78,7 +80,7 @@ set network.@switch_vlan[{{ switchnum }}].ports='0t 1t' set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}' {%- endfor %} -{{ uci_network_mgmt('eth0.1') }} +${uciNetworkMgmt "eth0.1"} {%- for net in bridges.keys() %} set network.{{ net }}=interface @@ -112,7 +114,7 @@ set network.@switch_vlan[{{ switchnum }}].ports='5t 6t' set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}' {%- endfor %} -{{ uci_network_mgmt('eth0.1') }} +${uciNetworkMgmt "eth0.1"} {%- for net in bridges.keys() %} set network.{{ net }}=interface @@ -150,7 +152,7 @@ set network.@switch_vlan[{{ switchnum }}].ports='1t 6t' set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}' {%- endfor %} -{{ uci_network_mgmt('eth0.1') }} +${uciNetworkMgmt "eth0.1"} {%- for net in bridges.keys() %} set network.{{ net }}=interface @@ -187,7 +189,7 @@ set network.@switch_vlan[{{ switchnum }}].ports='0t 1t' set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}' {%- endfor %} -{{ uci_network_mgmt('eth0.1') }} +${uciNetworkMgmt "eth0.1"} {%- for net in bridges.keys() %} set network.{{ net }}=interface @@ -220,7 +222,7 @@ set network.@switch_vlan[{{ switchnum }}].ports='0t 5t' set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}' {%- endfor %} -{{ uci_network_mgmt('eth0.1') }} +${uciNetworkMgmt "eth0.1"} {%- for net in bridges.keys() %} set network.{{ net }}=interface @@ -235,7 +237,7 @@ set network.@switch[0].reset=1 set network.@switch[0].enable=1 set network.@switch[0].enable_vlan=0 -{{ uci_network_mgmt('eth0.1') }} +${uciNetworkMgmt "eth0.1"} {%- for net in bridges.keys() %} @@ -260,7 +262,7 @@ set network.@switch[0].reset=1 set network.@switch[0].enable=1 set network.@switch[0].enable_vlan=0 -{{ uci_network_mgmt('eth1.1') }} +${uciNetworkMgmt "eth1.1"} {%- for net in bridges.keys() %} @@ -280,7 +282,7 @@ set network.{{ net }}.ifname='{{ ' '.join(ports) }}' {%- elif conf['model'] == 'TL-WA901NDv3' or conf['model'] == 'Ubnt-UniFi-AP-AC-LR' %} {# Only eth0 exists, no switch #} -{{ uci_network_mgmt('eth0.1') }} +${uciNetworkMgmt "eth0.1"} {%- for net in bridges.keys() %} @@ -294,7 +296,7 @@ set network.{{ net }}.ifname='{{ 'eth0.' ~ pillar['vlans'][net] }}' {%- elif conf['model'] == 'Ubnt-UAP-nanoHD' %} {# no switch, eth0 exists but is not usable, using "lan" instead #} -{{ uci_network_mgmt('lan.1') }} +${uciNetworkMgmt "lan.1"} {%- for net in bridges.keys() %} @@ -332,7 +334,7 @@ set network.@switch_vlan[{{ switchnum }}].ports='4t 6t' set network.@switch_vlan[{{ switchnum }}].comment='{{ net }}' {%- endfor %} -{{ uci_network_mgmt('eth0.1') }} +${uciNetworkMgmt "eth0.1"} {%- for net in bridges.keys() %} set network.{{ net }}=interface @@ -348,7 +350,7 @@ set network.@switch[0].reset=1 set network.@switch[0].enable=1 set network.@switch[0].enable_vlan=0 -{{ uci_network_mgmt('eth1.1') }} +${uciNetworkMgmt "eth1.1"} {%- for net in bridges.keys() %} @@ -401,71 +403,71 @@ set wireless.wifi{{ index.iface }}=wifi-iface {%- set ifsuffix = '-eap' %} {%- endif %} {%- else %} -{%- set ifsuffix = '' %} +{%- set ifsuffix = "" %} {%- endif %} -set wireless.wifi{{ index.iface }}.ifname={{ ifprefix }}{{ ssidconf['net'] }}{{ ifsuffix }} -set wireless.wifi{{ index.iface }}.device=radio{{ index.radio }} -set wireless.wifi{{ index.iface }}.ssid='{{ ssid }}' -set wireless.wifi{{ index.iface }}.mode=ap -set wireless.wifi{{ index.iface }}.network={{ ssidconf['net'] }} -{%- if ssidconf.get('psk') %} -set wireless.wifi{{ index.iface }}.encryption=psk2 -set wireless.wifi{{ index.iface }}.key='{{ ssidconf['psk'] }}' -{%- elif ssidconf.get('wpa-eap') %} -set wireless.wifi{{ index.iface }}.encryption=wpa2 -set wireless.wifi{{ index.iface }}.server='{{ ssidconf['wpa-eap']['server'] }}' -set wireless.wifi{{ index.iface }}.port='{{ ssidconf['wpa-eap']['port'] }}' -set wireless.wifi{{ index.iface }}.auth_secret='{{ ssidconf['wpa-eap']['secret'] }}' -{%- else %} -set wireless.wifi{{ index.iface }}.encryption=none -delete wireless.wifi{{ index.iface }}.key -{%- endif %} -set wireless.wifi{{ index.iface }}.mcast_rate=18000 + set wireless.wifi{{ index.iface }}.ifname={{ ifprefix }}{{ ssidconf['net'] }}{{ ifsuffix }} + set wireless.wifi{{ index.iface }}.device=radio{{ index.radio }} + set wireless.wifi{{ index.iface }}.ssid='{{ ssid }}' + set wireless.wifi{{ index.iface }}.mode=ap + set wireless.wifi{{ index.iface }}.network={{ ssidconf['net'] }} + {%- if ssidconf.get('psk') %} + set wireless.wifi{{ index.iface }}.encryption=psk2 + set wireless.wifi{{ index.iface }}.key='{{ ssidconf['psk'] }}' + {%- elif ssidconf.get('wpa-eap') %} + set wireless.wifi{{ index.iface }}.encryption=wpa2 + set wireless.wifi{{ index.iface }}.server='{{ ssidconf['wpa-eap']['server'] }}' + set wireless.wifi{{ index.iface }}.port='{{ ssidconf['wpa-eap']['port'] }}' + set wireless.wifi{{ index.iface }}.auth_secret='{{ ssidconf['wpa-eap']['secret'] }}' + {%- else %} + set wireless.wifi{{ index.iface }}.encryption=none + delete wireless.wifi{{ index.iface }}.key + {%- endif %} + set wireless.wifi{{ index.iface }}.mcast_rate=18000 -{%- set x = index.update({ 'iface': index.iface + 1 }) %} -{%- endfor %} -{%- set x = index.update({ 'radio': index.radio + 1 }) %} -{%- endfor %} + {%- set x = index.update({ 'iface': index.iface + 1 }) %} + {%- endfor %} + {%- set x = index.update({ 'radio': index.radio + 1 }) %} + {%- endfor %} -commit -__UCI__ + commit + __UCI__ -# Cronjob that makes sure WiFi is only visible when server with all -# the gateways is reachable -cat >/etc/crontabs/root <<__CRON__ -* * * * * /usr/sbin/wifi-on-link.sh -__CRON__ -cat >/usr/sbin/wifi-on-link.sh <<__SH__ -#!/bin/sh + # Cronjob that makes sure WiFi is only visible when server with all + # the gateways is reachable + cat >/etc/crontabs/root <<__CRON__ + * * * * * /usr/sbin/wifi-on-link.sh + __CRON__ + cat >/usr/sbin/wifi-on-link.sh <<__SH__ + #!/bin/sh -if (ping -c 1 -W 3 {{ pillar['hosts-inet']['mgmt']['mgmt-gw'] }}) ; then - REACHABLE=y -else - REACHABLE=n -fi + if (ping -c 1 -W 3 {{ pillar['hosts-inet']['mgmt']['mgmt-gw'] }}) ; then + REACHABLE=y + else + REACHABLE=n + fi -if [ "\\\$(cat /sys/class/net/wlan2-pub/operstate)" == "up" ] ; then - UP=y -else - UP=n -fi + if [ "\\\$(cat /sys/class/net/wlan2-pub/operstate)" == "up" ] ; then + UP=y + else + UP=n + fi -{%- if conf.get("error-led") %} -ERROR_LED=/sys/class/leds/{{ conf["error-led"] }}/brightness -[ \\\$REACHABLE = y ] && echo 0 > \\\$ERROR_LED -[ \\\$REACHABLE = n ] && echo 1 > \\\$ERROR_LED -{%- endif %} + {%- if conf.get("error-led") %} + ERROR_LED=/sys/class/leds/{{ conf["error-led"] }}/brightness + [ \\\$REACHABLE = y ] && echo 0 > \\\$ERROR_LED + [ \\\$REACHABLE = n ] && echo 1 > \\\$ERROR_LED + {%- endif %} -[ \\\$REACHABLE = y ] && [ \\\$UP = n ] && wifi up -[ \\\$REACHABLE = n ] && [ \\\$UP = y ] && wifi down + [ \\\$REACHABLE = y ] && [ \\\$UP = n ] && wifi up + [ \\\$REACHABLE = n ] && [ \\\$UP = y ] && wifi down -exit 0 -__SH__ -chmod a+rx /usr/sbin/wifi-on-link.sh -/etc/init.d/cron restart + exit 0 + __SH__ + chmod a+rx /usr/sbin/wifi-on-link.sh + /etc/init.d/cron restart -for svc in dnsmasq uhttpd ; do - rm /etc/rc.d/*\$svc + for svc in dnsmasq uhttpd ; do + rm /etc/rc.d/*\$svc /etc/init.d/\$svc stop done @@ -476,4 +478,7 @@ reboot __SSH__ echo "Base configuration done \\o/" -echo "Later run: `dirname $0`/ap_install_collectd.sh {{ pillar['hosts-inet']['mgmt'][hostname] }}" +echo "Later run: `dirname $0`/ap_install_collectd.sh {{ pillar['hosts-inet']['mgmt'][hostName] }}" + + +'' diff --git a/nix/pkgs/device-templates.nix b/nix/pkgs/device-templates.nix index e5f33ec..4d82a10 100644 --- a/nix/pkgs/device-templates.nix +++ b/nix/pkgs/device-templates.nix @@ -4,43 +4,17 @@ let pkgs = nixpkgs.legacyPackages.${system}; config = self.lib.config; - templates = role: { - ap = _: ./ap.sh; - switch = model: ../../salt/switches + "/${model}.expect"; - }.${role}; - replaceNetmasks = template: - builtins.toFile (builtins.baseNameOf template) ( - builtins.replaceStrings [''{%- import_yaml "netmasks.yaml" as netmasks -%}''] [""] ( - builtins.readFile template - ) - ); - expandTemplate = name: template: data: - self.lib.expandSaltTemplate name (replaceNetmasks template) data; - wrapNixShell = script: - pkgs.runCommand (builtins.baseNameOf script) { - src = script; - } '' - ( - echo '#! /usr/bin/env nix-shell' - echo '#! nix-shell -i "expect -f" -p expect telnet' - cat $src - ) > $out - chmod a+x $out - ''; - device-scripts = - builtins.mapAttrs (hostname: { role, model, ... }: - wrapNixShell ( - expandTemplate "${hostname}.sh" (templates role model) ({ - inherit hostname; - pillar = config.salt-pillar; - netmasks = self.lib.netmasks; - logging = config.salt-pillar.hosts-inet.mgmt.logging; - } // optionalAttrs (config.salt-pillar.switches ? ${hostname}) { - switch = config.salt-pillar.switches.${hostname}; - } // optionalAttrs (config.salt-pillar.cpe ? ${hostname}) { - conf = config.salt-pillar.cpe.${hostname}; - }) + builtins.mapAttrs (hostName: hostConfig@{ role, model, ... }: + pkgs.writeScript "${hostName}.sh" ( + let + args = { + inherit pkgs self hostName config hostConfig; + }; + in { + ap = import ./ap.nix args; + switch = import (./switches + "/${model}.nix") args; + }.${role} ) ) ( filterAttrs (_: { role, ... }: @@ -58,8 +32,8 @@ let chmod a+x $out/bin/ap_install_collectd.sh '' + builtins.concatStringsSep "\n" ( - map (hostname: - "ln -s ${device-scripts.${hostname}} $out/bin/${hostname}.sh" + map (hostName: + "ln -s ${device-scripts.${hostName}} $out/bin/${hostName}.sh" ) (builtins.attrNames device-scripts) ) ); diff --git a/nix/pkgs/switches/3com-4200G.nix b/nix/pkgs/switches/3com-4200G.nix new file mode 100644 index 000000000..3ed41b5 --- /dev/null +++ b/nix/pkgs/switches/3com-4200G.nix @@ -0,0 +1,160 @@ +# http://h20628.www2.hp.com/km-ext/kmcsdirect/emr_na-c02586144-1.pdf +{ self, pkgs, hostName, config, hostConfig, ... }: +with pkgs; +with lib; +'' + #! ${expect}/bin/expect -f + + spawn ${inetutils}/bin/telnet ${config.site.net.mgmt.hosts4.${hostName}} + + expect "Password:" + send "${hostConfig.password}\r" + expect ">" + send "system-view\r" + expect "]" + + send "sysname ${hostName}\r" + expect "]" + + send "user-interface vty 0 4\r" + expect "ui-vty0-4]" + send "screen-length 0\r" + expect "ui-vty0-4]" + send "user privilege level 3\r" + expect "ui-vty0-4]" + send "set authentication password simple ${hostConfig.password}\r" + expect "ui-vty0-4]" + send "quit\r" + expect "${hostName}]" + + send "local-user admin\r" + expect -- "-luser-admin]" + send "password simple ${hostConfig.password}\r" + expect -- "-luser-admin]" + send "quit\r" + expect "${hostName}]" + + # Enable logging + send "info-center enable\r" + expect "]" + send "info-center loghost ${config.site.net.mgmt.hosts4.logging} channel loghost facility local6\r" + expect "]" + send "info-center source default channel loghost log level informational\r" + expect "]" + + ${concatMapStrings (net: + let + netConfig = config.site.net.${net}; + vlan = toString netConfig.vlan; + inherit (config.site.net.${net}) hosts4; + hostAddr4 = hosts4.${hostName}; + prefixLength = elemAt ( + builtins.split "/" netConfig.subnet4 + ) 2; + netmask = self.lib.netmasks.${prefixLength}; + in '' + send "vlan ${vlan}\r" + expect -- "-vlan${vlan}]" + send "name ${net}\r" + expect -- "-vlan${vlan}]" + + ${optionalString (net == "mgmt") '' + # Actually only used for mgmt_vlan, switches are not routers + send "interface Vlan-interface ${vlan}\r" + expect "]" + ${optionalString (hosts4 ? ${hostName}) '' + send "ip address ${hostAddr4} ${netmask}\r" + expect "]" + ''} + ''} + send "quit\r" + expect "${hostName}]" + '') (builtins.attrNames config.site.net) + } + + ${concatMapStrings (name: + let + linkConfig = hostConfig.links.${name}; + isAccess = config.site.net ? ${name}; + netConfig = config.site.net.${name}; + isTrunk = !isAccess; + isBond = isTrunk && builtins.length linkConfig.ports > 1; + in + if isTrunk + then '' + ${optionalString isBond '' + send "link-aggregation group ${linkConfig.group} mode static\r" + expect { + "This aggregation will be modified to static mode. Continue ?" { + send "Y\r" + } + "]" {} + } + send "link-aggregation group ${linkConfig.group} description ${name}\r" + expect "]" + ''} + ${concatMapStrings (port: '' + send "interface ${port}\r" + expect "]" + send "undo stp edged-port\r" + expect "]" + ${if isBond + then '' + send "lacp enable\r" + expect "]" + send "undo port link-aggregation group\r" + expect "]" + send "port link-aggregation group ${linkConfig.group}\r" + '' else '' + send "undo lacp enable\r" + ''} + expect "]" + send "jumboframe enable\r" + expect "]" + + send "port link-type trunk\r" + expect "]" + # Set dummy default vlan + send "port trunk pvid vlan 4094\r" + expect "]" + # Deconfigure all but mgmt vlan + send "undo port trunk permit vlan 2 to 4094\r" + expect "]" + ${concatMapStrings (vlan: '' + send "port trunk permit vlan ${toString vlan}\r" + expect "]" + '') linkConfig.vlans} + send "quit\r" + expect "${hostName}]" + '') linkConfig.ports} + '' else + concatMapStrings (port: '' + send "interface ${port}\r" + expect "]" + send "undo port link-aggregation group\r" + expect "]" + send "port link-type access\r" + expect "]" + ${if name == "mgmt" + then '' + send "undo port access vlan\r" + expect "]" + '' else '' + send "port access vlan ${toString netConfig.vlan}\r" + expect "]" + ''} + send "quit\r" + expect "${hostName}]" + '') (linkConfig.ports) + ) (builtins.attrNames hostConfig.links)} + + send "save main\r" + expect "Y/N]" + send "YES\r" + expect "press the enter key):" + send "\r" + expect "]" + send "quit\r" + expect ">" + send "quit\r" +'' diff --git a/nix/pkgs/switches/HP-procurve-2824.nix b/nix/pkgs/switches/HP-procurve-2824.nix new file mode 100644 index 000000000..99c12e5 --- /dev/null +++ b/nix/pkgs/switches/HP-procurve-2824.nix @@ -0,0 +1,141 @@ +# http://ftp.hp.com/pub/networking/software/2600-2800-4100-6108-MgmtConfig-Oct2005-59906023.pdf + +{ self, pkgs, hostName, config, hostConfig, ... }: +with pkgs; +with lib; +'' + #! ${expect}/bin/expect -f + + spawn ${inetutils}/bin/telnet ${config.site.net.mgmt.hosts4.${hostName}} + expect "Press any key to continue" + send "\r" + expect "assword: " + send "${hostConfig.password}\r" + expect "#" + send "configure terminal\r" + expect "(config)# " + + send "hostname ${hostName}\r" + expect "(config)# " + send "snmp-server location \"${hostConfig.location}\"\r" + expect "(config)# " + send "snmp-server contact \"astro@spaceboyz.net\"\r" + expect "(config)# " + send "password manager\r" + expect "New password for Manager: " + send "${hostConfig.password}\r" + expect "Please retype new password for Manager: " + send "${hostConfig.password}\r" + expect "(config)# " + + # TODO: ssh, password + + # Enable Logging + send "logging ${config.site.net.mgmt.hosts4.logging}\r" + expect "(config)# " + send "logging facility local6\r" + expect "(config)# " + + # todo ntp + # timesync sntp + # ip timep manual {#ntp#} interval 10 + + ${concatMapStrings (net: + let + netConfig = config.site.net.${net}; + vlan = toString netConfig.vlan; + inherit (config.site.net.${net}) hosts4; + hostAddr4 = hosts4.${hostName}; + prefixLength = elemAt ( + builtins.split "/" netConfig.subnet4 + ) 2; + netmask = self.lib.netmasks.${prefixLength}; + in '' + send "vlan ${vlan}\r" + expect "(vlan-${vlan})#" + + send "name ${hostName}\r" + expect "(vlan-${vlan})#" + + send "jumbo\r" + expect "(vlan-${vlan})#" + + # Actually only used for mgmt_vlan, switches are not routers + ${optionalString (hosts4 ? ${hostName}) '' + send "ip address ${hostAddr4} ${netmask}\r" + expect "(vlan-${vlan})#" + ''} + + send "exit\r" + expect "(config)# " + + ${if net == "mgmt" + then '' + send "management-vlan ${vlan}\r" + expect "(config)# " + '' else '' + # If not mgmt, reset all VLAN mappings + send "no vlan ${vlan} tagged all\r" + expect "(config)# " + send "no vlan ${vlan} untagged all\r" + expect "(config)# " + ''} + '') (builtins.attrNames config.site.net) + } + + ${concatMapStrings (name: + let + linkConfig = hostConfig.links.${name}; + isAccess = config.site.net ? ${name}; + netConfig = config.site.net.${name}; + isTrunk = !isAccess; + isBond = isTrunk && builtins.length linkConfig.ports > 1; + ports = concatStringsSep "," linkConfig.ports; + in + if isTrunk && isBond + then '' + send "interface ${ports} lacp active\r" + expect "(config)# " + send "trunk ${ports} trk${linkConfig.group} lacp\r" + expect "(config)# " + + ${concatMapStrings (vlan: '' + send "vlan ${toString vlan} tagged trk${linkConfig.group}\r" + expect "(config)# " + '') linkConfig.vlans} + '' + + else if isTrunk + then '' + send "no trunk ${ports}\r" + expect "(config)# " + send "no interface ${ports} lacp\r" + expect "(config)# " + + ${concatMapStrings (vlan: '' + send "vlan ${toString vlan} tagged ${ports}\r" + expect "(config)# " + '') linkConfig.vlans} + '' + + else '' + send "no trunk ${ports}\r" + expect "(config)# " + + send "vlan ${toString netConfig.vlan} untagged ${ports}\r" + expect "(config)# " + '' + ) (builtins.attrNames hostConfig.links)} + + send "exit\r" + expect "${hostName}# " + + send "write memory\r" + expect "${hostName}# " + send "exit\r" + expect "${hostName}> " + send "exit\r" + expect "Do you want to log out " + expect "y/n]? " + send "y" +'' diff --git a/nix/pkgs/switches/TL-SG3210.nix b/nix/pkgs/switches/TL-SG3210.nix new file mode 100644 index 000000000..9a216ba --- /dev/null +++ b/nix/pkgs/switches/TL-SG3210.nix @@ -0,0 +1,131 @@ +# http://static.tp-link.com/res/down/doc/TL-SG3210(UN)_V2.0_CLI_.pdf +{ self, pkgs, hostName, config, hostConfig, ... }: +with pkgs; +with lib; +'' + #! ${pkgs.expect}/bin/expect -f + + spawn ${pkgs.inetutils}/bin/telnet ${config.site.net.mgmt.hosts4.${hostName}} + expect "Password:" + send "${hostConfig.password}\r" + expect ">" + send "\r" + expect ">" + send "enable\r" + expect "Password:" + send "${hostConfig.password}\r" + expect "#" + send "configure\r" + expect "(config)#" + + send "enable secret 0 ${hostConfig.password}\r" + expect "(config)#" + #send "enable password 0 ${hostConfig.password}\r" + #expect "(config)#" + send "service password-encryption\r" + expect "(config)#" + send "user name admin privilege admin secret 0 ${hostConfig.password}\r" + expect "(config)#" + + send "hostname \"${hostName}\"\r" + expect "(config)#" + send "location \"${hostConfig.location}\"\r" + expect "(config)#" + + send "logging host index 1 ${config.site.net.mgmt.hosts4.logging} 6\r" + expect "(config)#" + + send "ip management-vlan ${toString config.site.net.mgmt.vlan}\r" + expect "(config)#" + send "ip ssh server\r" + expect "(config)#" + send "telnet enable\r" + expect "(config)#" + send "line vty 0 15\r" + expect "(config-line)#" + send "password 0 ${hostConfig.password}\r" + expect "(config-line)#" + send "exit\r" + expect "(config)#" + + ${concatMapStrings (net: + let + netConfig = config.site.net.${net}; + vlan = toString netConfig.vlan; + inherit (config.site.net.${net}) hosts4; + hostAddr4 = hosts4.${hostName}; + prefixLength = elemAt ( + builtins.split "/" netConfig.subnet4 + ) 2; + netmask = self.lib.netmasks.${prefixLength}; + in '' + ${optionalString (net != "mgmt") '' + send "vlan ${vlan}\r" + expect "(config-vlan)#" + send "name \"${net}\"\r" + expect "(config-vlan)#" + send "exit\r" + expect "(config)#" + ''} + + # Actually only used for mgmt_vlan, switches are not routers + send "interface vlan ${vlan}\r" + expect "(config-if)#" + ${optionalString (hosts4 ? ${hostName}) '' + send "ip address ${hostAddr4} ${netmask}\r" + expect "(config-if)#" + ''} + send "exit\r" + expect "(config)#" + '' + ) (builtins.attrNames config.site.net)} + + ${concatMapStrings (name: + let + linkConfig = hostConfig.links.${name}; + isAccess = config.site.net ? ${name}; + netConfig = config.site.net.${name}; + isTrunk = !isAccess; + isBond = isTrunk && builtins.length linkConfig.ports > 1; + ports = concatStringsSep "," linkConfig.ports; + in + if isTrunk + then '' + send "interface range gigabitEthernet 1/0/${ports}\r" + expect "(config-if-range)#" + send "switchport mode trunk\r" + expect "(config-if-range)#" + ${if (builtins.length linkConfig.ports > 1) + then '' + send "channel-group ${linkConfig.group} mode active\r" + expect "(config-if-range)#" + #send "port-channel load-balance src-dst-ip\r" + #expect "(config-if-range)#" + '' else '' + send "no channel-group\r" + expect "(config-if-range)#" + ''} + send "switchport trunk allowed vlan ${concatStringsSep "," (map toString linkConfig.vlans)}\r" + expect "(config-if-range)#" + send "exit\r" + expect "(config)#" + '' else '' + send "interface range gigabitEthernet 1/0/${ports}\r" + expect "(config-if-range)#" + send "switchport mode access\r" + expect "(config-if-range)#" + send "switchport access vlan ${toString netConfig.vlan}\r" + expect "(config-if-range)#" + send "exit\r" + expect "(config)#" + '' + ) (builtins.attrNames hostConfig.links)} + + send "exit\r" + expect "#" + send "copy running-config startup-config\r" + expect "#" + send "exit\r" + expect ">" + send "exit\r" +'' diff --git a/nix/pkgs/switches/linksys-srw2048.nix b/nix/pkgs/switches/linksys-srw2048.nix new file mode 100644 index 000000000..bb2829c --- /dev/null +++ b/nix/pkgs/switches/linksys-srw2048.nix @@ -0,0 +1,105 @@ +# https://www.crc.id.au/real-console-on-linksys-srw2024-switch/ +{ self, pkgs, hostName, config, hostConfig, ... }: +with pkgs; +with lib; +'' + #! ${expect}/bin/expect -f + + spawn ${inetutils}/bin/telnet ${config.site.net.mgmt.hosts4.${hostName}} + expect "Password:" + send "admin\t${hostConfig.password}\r" + + # ^z + send "\x1A" + expect ">" + send "lcli\r" + + expect "User Name:" + send "admin\r" + expect "Password:" + send "${hostConfig.password}\r" + + expect "# " + send "configure\r" + expect "(config)# " + send "hostname ${hostName}\r" + expect "(config)# " + send "management vlan 4094\r" + expect "(config)# " + send "vlan database\r" + expect "(config-vlan)# " + + ${concatMapStrings (net: '' + send "vlan ${toString config.site.net.${net}.vlan}\r" + expect "(config-vlan)#" + '') (builtins.attrNames config.site.net)} + send "exit\r" + expect "(config)#" + + ${concatMapStrings (net: '' + send "interface vlan ${toString config.site.net.${net}.vlan}\r" + expect "(config-if)#" + send "name ${net}\r" + expect "(config-if)#" + send "exit\r" + expect "(config)#" + '') (builtins.attrNames config.site.net)} + + ${concatMapStrings (name: + let + linkConfig = hostConfig.links.${name}; + isAccess = config.site.net ? ${name}; + netConfig = config.site.net.${name}; + isTrunk = !isAccess; + isBond = isTrunk && builtins.length linkConfig.ports > 1; + ports = concatStringsSep "," linkConfig.ports; + in + if isTrunk && isBond + then '' + send "interface range ethernet ${ports}\r" + expect "(config-if)#" + send "switchport trunk allowed vlan remove all\r" + expect "(config-if)#" + send "channel-group ${linkConfig.group} mode auto\r" + expect "(config-if)#" + send "interface port-channel ${linkConfig.group}\r" + expect "(config-if)#" + send "exit\r" + + send "interface port-channel ${linkConfig.group}\r" + expect "(config-if)#" + send "switchport mode trunk\r" + expect "(config-if)#" + send "switchport trunk allowed vlan add ${concatStringsSep "," (map toString linkConfig.vlans)}\r" + expect "(config-if)#" + + send "exit\r" + expect "(config)#" + '' + else if isTrunk + then concatMapStrings (port: '' + send "interface ethernet ${port}\r" + expect "(config-if)#" + send "no channel-group\r" + expect "(config-if)#" + send "switchport mode trunk\r" + expect "(config-if)#" + send "switchport trunk allowed vlan add ${concatStringsSep "," (map toString linkConfig.vlans)}\r" + expect "(config-if)#" + send "exit\r" + expect "(config)#" + '') linkConfig.ports + else concatMapStrings (port: '' + send "interface ethernet ${port}\r" + expect "(config-if)#" + send "no channel-group\r" + expect "(config-if)#" + send "switchport mode access\r" + expect "(config-if)#" + send "switchport access vlan ${toString netConfig.vlan}\r" + expect "(config-if)#" + send "exit\r" + expect "(config)#" + '') linkConfig.ports + ) (builtins.attrNames hostConfig.links)} +'' diff --git a/salt-pillar/switches/init.sls b/salt-pillar/switches/init.sls index a36cfa7..46be677 100644 --- a/salt-pillar/switches/init.sls +++ b/salt-pillar/switches/init.sls @@ -220,7 +220,7 @@ switches: - g39 - g40 vlans: *server1_vlans - c3d2-server5: + server5: mode: bond group: 6 ports: @@ -237,7 +237,7 @@ switches: - cluster - bmx - priv23 - c3d2-server6: + server6: mode: bond group: 8 ports: @@ -246,7 +246,7 @@ switches: - g7 - g8 vlans: *server_vlans - c3d2-server7: + server7: mode: bond group: 7 ports: @@ -255,7 +255,7 @@ switches: - g14 - g15 vlans: *server_vlans - c3d2-server8: + server8: mode: bond group: 5 ports: @@ -421,14 +421,14 @@ switches: - mgmt - pub - priv17 - c3d2-server3: + server3: mode: bond group: 1 ports: - GigabitEthernet1/0/30 - GigabitEthernet1/0/31 vlans: *server_vlans - c3d2-server9: + server9: mode: bond group: 3 ports: @@ -734,6 +734,7 @@ switches: switch-b1: mode: bond ports: 1 + group: 1 vlans: - mgmt - pub diff --git a/salt/switches/3com-4200G.expect b/salt/switches/3com-4200G.expect deleted file mode 100644 index 57e9860..000000000 --- a/salt/switches/3com-4200G.expect +++ /dev/null @@ -1,151 +0,0 @@ -{# http://h20628.www2.hp.com/km-ext/kmcsdirect/emr_na-c02586144-1.pdf #} - -{%- macro increment(dct, key, inc=1) -%} - {% if dct.update({key: dct[key] + inc}) %} {% endif %} -{%- endmacro -%} - -{%- import_yaml "netmasks.yaml" as netmasks -%} -#!/usr/bin/expect -f - -spawn telnet {{ pillar['hosts-inet']['mgmt'][hostname] }} -expect "Password:" -send "{{ switch['password'] }}\r" -expect ">" -send "system-view\r" -expect "]" - -send "sysname {{ hostname }}\r" -expect "]" - -send "user-interface vty 0 4\r" -expect "ui-vty0-4]" -send "screen-length 0\r" -expect "ui-vty0-4]" -send "user privilege level 3\r" -expect "ui-vty0-4]" -send "set authentication password simple {{ switch['password'] }}\r" -expect "ui-vty0-4]" -send "quit\r" -expect "{{ hostname }}]" - -send "local-user admin\r" -expect -- "-luser-admin]" -send "password simple {{ switch['password'] }}\r" -expect -- "-luser-admin]" -send "quit\r" -expect "{{ hostname }}]" - -{# Enable logging #} -send "info-center enable\r" -expect "]" -send "info-center loghost {{logging}} channel loghost facility local6\r" -expect "]" -send "info-center source default channel loghost log level informational\r" -expect "]" - - -{%- for name, vlan in pillar['vlans'].items() %} -send "vlan {{ vlan }}\r" -expect -- "-vlan{{ vlan }}]" -send "name {{ name }}\r" -expect -- "-vlan{{ vlan }}]" - -{%- if name == 'mgmt' %} -{# Actually only used for mgmt_vlan, switches are not routers #} -send "interface Vlan-interface {{ vlan }}\r" -expect "]" -{%- set net_hosts = pillar['hosts-inet'].get(name) %} -{%- set ipaddr = net_hosts and net_hosts.get(hostname) %} -{%- if ipaddr %} -send "ip address {{ ipaddr }} {{ netmasks[pillar['subnets-inet'][name].split('/')[1]] }}\r" -expect "]" -{%- endif %} -{%- endif %} -send "quit\r" -expect "{{ hostname }}]" -{%- endfor %} - -{%- for name, conf in switch['ports'].items() %} -{%- if conf['mode'] == 'trunk' or conf['mode'] == 'bond' %} -{%- if conf['mode'] == 'bond' %} -send "link-aggregation group {{ conf['group'] }} mode static\r" -expect { - "This aggregation will be modified to static mode. Continue ?" { - send "Y\r" - } - "]" {} -} -send "link-aggregation group {{ conf['group'] }} description {{name}}\r" -expect "]" -{%- endif %} -{%- for port in conf['ports'] %} -send "interface {{ port }}\r" -expect "]" -send "undo stp edged-port\r" -expect "]" -{%- if conf['mode'] == 'bond' %} -send "lacp enable\r" -expect "]" -send "undo port link-aggregation group\r" -expect "]" -send "port link-aggregation group {{ conf['group'] }}\r" -{%- else %} -send "undo lacp enable\r" -{%- endif %} -expect "]" -send "jumboframe enable\r" -expect "]" -{%- if conf.get('vlans') %} -send "port link-type trunk\r" -expect "]" -# Set dummy default vlan -send "port trunk pvid vlan 4094\r" -expect "]" -# Deconfigure all but mgmt vlan -send "undo port trunk permit vlan 2 to 4094\r" -expect "]" -{%- for vlan_name in conf['vlans'] %} -send "port trunk permit vlan {{ pillar['vlans'][vlan_name] }}\r" -expect "]" -{%- endfor %} -{%- else %} -send "port link-type access\r" -expect "]" -send "port access vlan {{ pillar['vlans'][conf['access']] }}\r" -expect "]" -{%- endif %} -send "quit\r" -expect "{{ hostname }}]" -{%- endfor %} - -{%- elif conf['mode'] == 'access' %} -{%- for port in conf['ports'] %} -send "interface {{ port }}\r" -expect "]" -send "undo port link-aggregation group\r" -expect "]" -send "port link-type access\r" -expect "]" -{%- if name == 'mgmt' %} -send "undo port access vlan\r" -expect "]" -{%- else %} -send "port access vlan {{ pillar['vlans'][name] }}\r" -expect "]" -{%- endif %} -send "quit\r" -expect "{{ hostname }}]" -{%- endfor %} - -{%- endif %} -{%- endfor %} - -send "save main\r" -expect "Y/N]" -send "YES\r" -expect "press the enter key):" -send "\r" -expect "]" -send "quit\r" -expect ">" -send "quit\r" diff --git a/salt/switches/HP-procurve-2824.expect b/salt/switches/HP-procurve-2824.expect deleted file mode 100644 index cbc7180..000000000 --- a/salt/switches/HP-procurve-2824.expect +++ /dev/null @@ -1,129 +0,0 @@ -{# http://ftp.hp.com/pub/networking/software/2600-2800-4100-6108-MgmtConfig-Oct2005-59906023.pdf #} -{%- import_yaml "netmasks.yaml" as netmasks -%} -#!/usr/bin/expect -f - -spawn telnet {{ pillar['hosts-inet']['mgmt'][hostname] }} -expect "Press any key to continue" -send "\r" -expect "assword: " -send "{{ switch['password'] }}\r" -expect "#" -send "configure terminal\r" -expect "(config)# " - -send "hostname {{ hostname }}\r" -expect "(config)# " -send "snmp-server location \"{{ switch['location'] }}\"\r" -expect "(config)# " -send "snmp-server contact \"astro@spaceboyz.net\"\r" -expect "(config)# " -send "password manager\r" -expect "New password for Manager: " -send "{{ switch['password'] }}\r" -expect "Please retype new password for Manager: " -send "{{ switch['password'] }}\r" -expect "(config)# " - -# TODO: ssh, password - -{# Enable Logging #} -send "logging {{logging}}\r" -expect "(config)# " -send "logging facility local6\r" -expect "(config)# " - -# todo ntp -# timesync sntp -# ip timep manual {#ntp#} interval 10 - -{%- for name, vlan in pillar['vlans'].items() %} -send "vlan {{ vlan }}\r" -expect "(vlan-{{ vlan }})#" - -send "name {{ name }}\r" -expect "(vlan-{{ vlan }})#" - -send "jumbo\r" -expect "(vlan-{{ vlan }})#" - -{# Actually only used for mgmt_vlan, switches are not routers #} -{%- set net_hosts = pillar['hosts-inet'].get(name) %} -{%- set ipaddr = net_hosts and net_hosts.get(hostname) %} -{%- if ipaddr %} -send "ip address {{ ipaddr }} {{ netmasks[pillar['subnets-inet'][name].split('/')[1]] }}\r" -expect "(vlan-{{ vlan }})#" -{%- endif %} - -send "exit\r" -expect "(config)# " - -{%- if name == 'mgmt' %} -send "management-vlan {{ vlan }}\r" -expect "(config)# " -{%- else %} -# If not mgmt, reset all VLAN mappings -send "no vlan {{ vlan }} tagged all\r" -expect "(config)# " -send "no vlan {{ vlan }} untagged all\r" -expect "(config)# " -{%- endif %} - -{%- endfor %} - -{%- for name, conf in switch['ports'].items() %} -{%- if conf['mode'] == 'bond' %} - -{%- if not conf.get('lacp', True) %} -send "trunk {{ conf['ports'] }} trk{{ conf['group'] }} trunk\r" -expect "(config)# " - -{%- else %} -send "interface {{ conf['ports'] }} lacp active\r" -expect "(config)# " -send "trunk {{ conf['ports'] }} trk{{ conf['group'] }} lacp\r" -expect "(config)# " -{%- endif %} - -{%- for vlan_name in conf['vlans'] %} -send "vlan {{ pillar['vlans'][vlan_name] }} tagged trk{{ conf['group'] }}\r" -expect "(config)# " -{%- endfor %} - -{%- elif conf['mode'] == 'trunk' %} -send "no trunk {{ conf['ports'] }}\r" -expect "(config)# " -send "no interface {{ conf['ports'] }} lacp\r" -expect "(config)# " - -{%- for vlan_name in conf['vlans'] %} -send "vlan {{ pillar['vlans'][vlan_name] }} tagged {{ conf['ports'] }}\r" -expect "(config)# " -{%- endfor %} - -{%- elif conf['mode'] == 'access' %} - -send "no trunk {{ conf['ports'] }}\r" -expect "(config)# " - -send "vlan {{ pillar['vlans'][name] }} untagged {{ conf['ports'] }}\r" -expect "(config)# " - -{%- endif %} - -{%- if conf.get('nostp') %} -send "spanning-tree {{ conf['ports'] }} bpdu-filter\r" -expect "(config)# " -{%- endif %} - -{%- endfor %} -send "exit\r" -expect "{{ hostname }}# " - -send "write memory\r" -expect "{{ hostname }}# " -send "exit\r" -expect "{{ hostname }}> " -send "exit\r" -expect "Do you want to log out " -expect "y/n]? " -send "y" diff --git a/salt/switches/TL-SG3210.expect b/salt/switches/TL-SG3210.expect deleted file mode 100644 index b4586b2..000000000 --- a/salt/switches/TL-SG3210.expect +++ /dev/null @@ -1,115 +0,0 @@ -{# http://static.tp-link.com/res/down/doc/TL-SG3210(UN)_V2.0_CLI_.pdf #} -{%- import_yaml "netmasks.yaml" as netmasks -%} -#!/usr/bin/expect -f - -#spawn cu -s 38400 -l /dev/ttyUSB0 -#stty raw -echo -spawn telnet {{ pillar['hosts-inet']['mgmt'][hostname] }} -expect "Password:" -send "{{ switch['password'] }}\r" -expect ">" -send "\r" -expect ">" -send "enable\r" -expect "Password:" -send "{{ switch['password'] }}\r" -expect "#" -send "configure\r" -expect "(config)#" - -send "enable secret 0 {{ switch['password'] }}\r" -expect "(config)#" -#send "enable password 0 {{ switch['password'] }}\r" -#expect "(config)#" -send "service password-encryption\r" -expect "(config)#" -send "user name admin privilege admin secret 0 {{ switch['password'] }}\r" -expect "(config)#" - -send "hostname \"{{ hostname }}\"\r" -expect "(config)#" -send "location \"{{ switch['location'] }}\"\r" -expect "(config)#" - -send "logging host index 1 {{logging}} 6\r" -expect "(config)#" - -{%- set mgmt_vlan = pillar['vlans']['mgmt'] %} -send "ip management-vlan {{ mgmt_vlan }}\r" -expect "(config)#" -send "ip ssh server\r" -expect "(config)#" -send "telnet enable\r" -expect "(config)#" -send "line vty 0 15\r" -expect "(config-line)#" -send "password 0 {{ switch['password'] }}\r" -expect "(config-line)#" -send "exit\r" -expect "(config)#" - -{%- for name, vlan in pillar['vlans'].items() %} -{%- if name != 'mgmt' %} -send "vlan {{ vlan }}\r" -expect "(config-vlan)#" -send "name \"{{ name }}\"\r" -expect "(config-vlan)#" -send "exit\r" -expect "(config)#" -{%- endif %} - -{# Actually only used for mgmt_vlan, switches are not routers #} -send "interface vlan {{ vlan }}\r" -expect "(config-if)#" -{%- set net_hosts = pillar['hosts-inet'].get(name) %} -{%- set ipaddr = net_hosts and net_hosts.get(hostname) %} -{%- if ipaddr %} -send "ip address {{ ipaddr }} {{ netmasks[pillar['subnets-inet'][name].split('/')[1]] }}\r" -expect "(config-if)#" -{%- endif %} -send "exit\r" -expect "(config)#" -{%- endfor %} - -{%- set group = 0 %} -{%- for name, conf in switch['ports'].items() %} -{%- if conf['mode'] == 'trunk' or conf['mode'] == 'bond' %} -send "interface range gigabitEthernet 1/0/{{ conf['ports'] }}\r" -expect "(config-if-range)#" -send "switchport mode trunk\r" -expect "(config-if-range)#" -{%- set group = group + 1 %} -send "channel-group {{ group }} mode passive\r" -expect "(config-if-range)#" -#send "port-channel load-balance src-dst-ip\r" -#expect "(config-if-range)#" -{%- set vlan_ids = [] %} -{%- for name in conf['vlans'] %} -{%- if vlan_ids.append('' ~ pillar['vlans'][name]) %} -{%- endif %} -{%- endfor %} -send "switchport trunk allowed vlan {{ ','.join(vlan_ids) }}\r" -expect "(config-if-range)#" -send "exit\r" -expect "(config)#" -{%- elif conf['mode'] == 'access' %} -{%- for port in conf['ports'] %} -send "interface range gigabitEthernet 1/0/{{ port }}\r" -expect "(config-if-range)#" -send "switchport mode access\r" -expect "(config-if-range)#" -send "switchport access vlan {{ pillar['vlans'][name] }}\r" -expect "(config-if-range)#" -send "exit\r" -expect "(config)#" -{%- endfor %} -{%- endif %} -{%- endfor %} - -send "exit\r" -expect "#" -send "copy running-config startup-config\r" -expect "#" -send "exit\r" -expect ">" -send "exit\r" diff --git a/salt/switches/linksys-srw2048.expect b/salt/switches/linksys-srw2048.expect deleted file mode 100644 index 4ef960a..000000000 --- a/salt/switches/linksys-srw2048.expect +++ /dev/null @@ -1,104 +0,0 @@ -{# https://www.crc.id.au/real-console-on-linksys-srw2024-switch/ #} -{%- import_yaml "netmasks.yaml" as netmasks -%} -#!/usr/bin/expect -f - -spawn telnet {{ pillar['hosts-inet']['mgmt'][hostname] }} -expect "Password:" -send "admin\t{{ switch['password'] }}\r" - -# ^z -send "\x1A" -expect ">" -send "lcli\r" - -expect "User Name:" -send "admin\r" -expect "Password:" -send "{{ switch['password'] }}\r" - -expect "# " -send "configure\r" -expect "(config)# " -send "hostname {{ hostname }}\r" -expect "(config)# " -send "management vlan 4094\r" -expect "(config)# " -send "vlan database\r" -expect "(config-vlan)# " -{%- for name, vlan in pillar['vlans'].items() %} -send "vlan {{ vlan }}\r" -expect "(config-vlan)#" -{%- endfor %} -send "exit\r" -expect "(config)#" -{%- for name, vlan in pillar['vlans'].items() %} -send "interface vlan {{ vlan }}\r" -expect "(config-if)#" -send "name {{ name }}\r" -expect "(config-if)#" -send "exit\r" -expect "(config)#" -{%- endfor %} - -{%- for name, conf in switch['ports'].items() %} - -{%- if conf['mode'] == 'trunk' %} -{%- for port in conf['ports'] %} -send "interface ethernet {{ port }}\r" -expect "(config-if)#" -send "no channel-group\r" -expect "(config-if)#" -send "switchport mode trunk\r" -expect "(config-if)#" -{%- set vlan_ids = [] %} -{%- for name in conf['vlans'] %} -{%- if vlan_ids.append('' ~ pillar['vlans'][name]) %} -{%- endif %} -{%- endfor %} -send "switchport trunk allowed vlan add {{ ','.join(vlan_ids) }}\r" -expect "(config-if)#" -send "exit\r" -expect "(config)#" -{%- endfor %} - -{%- elif conf['mode'] == 'bond' %} -send "interface range ethernet {{ ','.join(conf['ports']) }}\r" -expect "(config-if)#" -send "switchport trunk allowed vlan remove all\r" -expect "(config-if)#" -send "channel-group {{ conf['group'] }} mode auto\r" -expect "(config-if)#" -send "interface port-channel {{ conf['group'] }}\r" -expect "(config-if)#" -send "exit\r" - -send "interface port-channel {{ conf['group'] }}\r" -expect "(config-if)#" -send "switchport mode trunk\r" -expect "(config-if)#" -{%- set vlan_ids = [] %} -{%- for name in conf['vlans'] %} -{%- if vlan_ids.append('' ~ pillar['vlans'][name]) %} -{%- endif %} -{%- endfor %} -send "switchport trunk allowed vlan add {{ ','.join(vlan_ids) }}\r" -expect "(config-if)#" - -send "exit\r" -expect "(config)#" - -{%- elif conf['mode'] == 'access' %} -{%- for port in conf['ports'] %} -send "interface ethernet {{ port }}\r" -expect "(config-if)#" -send "no channel-group\r" -expect "(config-if)#" -send "switchport mode access\r" -expect "(config-if)#" -send "switchport access vlan {{ pillar['vlans'][name] }}\r" -expect "(config-if)#" -send "exit\r" -expect "(config)#" -{%- endfor %} -{%- endif %} -{%- endfor %}