treefmt v2.5.0traversed 396 files emitted 361 files for processing formatted 361 files (11 changed) in 878ms M docs/gen-ssh-config.sh M docs/generate-host-info.sh M docs/generate-lldp-graph.sh M docs/get-lldp-neighbors.sh M docs/hosts/README.md M docs/hosts/eta.md M docs/hosts/psi.md M docs/hosts/rho.md M docs/hosts/tau.md M tasks.py M tests/test_generate_network_topology.py diff --git a/docs/gen-ssh-config.sh b/docs/gen-ssh-config.sh index 7d7300d..575c5a6 100755 --- a/docs/gen-ssh-config.sh +++ b/docs/gen-ssh-config.sh @@ -3,10 +3,10 @@ set -euo pipefail user=${1:-} -if [[ -z "$user" ]]; then - echo "Missing username" - echo "Usage: $(basename "$0") username" - exit 1 +if [[ -z $user ]]; then + echo "Missing username" + echo "Usage: $(basename "$0") username" + exit 1 fi # GitHub directory pages change independently of this script; use the stable API. @@ -28,20 +28,20 @@ Host eta EOF curl -fsSL \ - -H 'Accept: application/vnd.github+json' \ - -H 'X-GitHub-Api-Version: 2022-11-28' \ - 'https://api.github.com/repos/SBEE-Lab/infra/contents/hosts?ref=main' \ - > "$tempfile" -machines=$(grep -oE '"name"[[:space:]]*:[[:space:]]*"[^"]+\.nix"' "$tempfile" \ - | sed -E 's/.*"([^"]+)\.nix"/\1/' \ - | sort -u) + -H 'Accept: application/vnd.github+json' \ + -H 'X-GitHub-Api-Version: 2022-11-28' \ + 'https://api.github.com/repos/SBEE-Lab/infra/contents/hosts?ref=main' \ + >"$tempfile" +machines=$(grep -oE '"name"[[:space:]]*:[[:space:]]*"[^"]+\.nix"' "$tempfile" | + sed -E 's/.*"([^"]+)\.nix"/\1/' | + sort -u) while read -r machine; do - if [[ -z "$machine" || "$machine" == "eta" ]]; then - continue - fi + if [[ -z $machine || $machine == "eta" ]]; then + continue + fi - cat <&2 - exit 1 +if [[ -z ${1:-} ]]; then + echo "Usage: $(basename "$0") host" >&2 + exit 1 fi target=$1 @@ -13,15 +13,15 @@ lstopo="$hostname.lstopo.svg" printf '# %s ``` -' "$hostname" > "$report" -ssh "$target" -- "nix-shell -p 'inxi.override { withRecommends = true; }' --run 'sudo inxi -F -a -i --slots -xxx -c0 -z -m'" >> "$report" +' "$hostname" >"$report" +ssh "$target" -- "nix-shell -p 'inxi.override { withRecommends = true; }' --run 'sudo inxi -F -a -i --slots -xxx -c0 -z -m'" >>"$report" tempfile=$(mktemp -t sbee-host-info.XXXXXX) -sed -E 's/(uuid: )[^ ]+/\1/g' "$report" > "$tempfile" +sed -E 's/(uuid: )[^ ]+/\1/g' "$report" >"$tempfile" mv "$tempfile" "$report" ssh "$target" -- "nix-shell -p hwloc -p dmidecode --run 'sudo lstopo /tmp/$hostname.lstopo.svg'" scp "$target:/tmp/$hostname.lstopo.svg" "$lstopo" ssh "$target" -- "sudo rm /tmp/$hostname.lstopo.svg" printf '``` ![hardware topology](%s) -' "$lstopo" >> "$report" +' "$lstopo" >>"$report" echo "wrote $report" >&2 diff --git a/docs/generate-lldp-graph.sh b/docs/generate-lldp-graph.sh index facbd2f..7fbaa06 100755 --- a/docs/generate-lldp-graph.sh +++ b/docs/generate-lldp-graph.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash set -euo pipefail -if (( BASH_VERSINFO[0] < 4 )); then - echo "$(basename "$0") requires Bash 4 or newer" >&2 - exit 1 +if ((BASH_VERSINFO[0] < 4)); then + echo "$(basename "$0") requires Bash 4 or newer" >&2 + exit 1 fi report="../graph.md" @@ -11,60 +11,60 @@ url="https://github.com/SBEE-Lab/infra/blob/main/docs/hosts" declare -A interfaces { - echo '```mermaid' - echo ' graph TD' + echo '```mermaid' + echo ' graph TD' - for host_file in *; do - [[ -f "$host_file" ]] || continue - while read -r neighbor; do - [[ -z "$neighbor" ]] && continue - host_interface=$(echo "$neighbor" | cut -d' ' -f1) - link_speed=$(echo "$neighbor" | cut -d' ' -f2) - neighbor_interface=$(echo "$neighbor" | cut -d' ' -f3 | tr -cd '[:alnum:]._-') - neighbor_name=$(echo "$neighbor" | cut -d' ' -f4 | tr -cd '[:alnum:]._-') + for host_file in *; do + [[ -f $host_file ]] || continue + while read -r neighbor; do + [[ -z $neighbor ]] && continue + host_interface=$(echo "$neighbor" | cut -d' ' -f1) + link_speed=$(echo "$neighbor" | cut -d' ' -f2) + neighbor_interface=$(echo "$neighbor" | cut -d' ' -f3 | tr -cd '[:alnum:]._-') + neighbor_name=$(echo "$neighbor" | cut -d' ' -f4 | tr -cd '[:alnum:]._-') - interfaces[$host_file]+=" $host_interface" - interfaces[$neighbor_name]+=" $neighbor_interface" + interfaces[$host_file]+=" $host_interface" + interfaces[$neighbor_name]+=" $neighbor_interface" - echo " ${host_file}.${host_interface}[\"$host_interface\"]-- $link_speed ---${neighbor_name}.${neighbor_interface}[\"$neighbor_interface\"]" - done < "$host_file" - done + echo " ${host_file}.${host_interface}[\"$host_interface\"]-- $link_speed ---${neighbor_name}.${neighbor_interface}[\"$neighbor_interface\"]" + done <"$host_file" + done - for host in "${!interfaces[@]}"; do - interfaces[$host]=$(xargs -n 1 <<< "${interfaces[$host]}" | sort -u | xargs) - echo " subgraph $host" - for interface in ${interfaces[$host]}; do - echo " ${host}.${interface}[\"$interface\"]" - done - echo " end" + for host in "${!interfaces[@]}"; do + interfaces[$host]=$(xargs -n 1 <<<"${interfaces[$host]}" | sort -u | xargs) + echo " subgraph $host" + for interface in ${interfaces[$host]}; do + echo " ${host}.${interface}[\"$interface\"]" done + echo " end" + done - for host in "${!interfaces[@]}"; do - [[ -f "../$host.md" ]] || continue - for interface in ${interfaces[$host]}; do - echo " click ${host}.${interface} \"$url/$host.md\" \"$host\"" - done + for host in "${!interfaces[@]}"; do + [[ -f "../$host.md" ]] || continue + for interface in ${interfaces[$host]}; do + echo " click ${host}.${interface} \"$url/$host.md\" \"$host\"" done + done - echo '```' -} > "$report" + echo '```' +} >"$report" # Remove inverse duplicate links. while true; do - duplicate="" - while read -r link; do - interface_1=$(awk '{print $1}' <<< "$link" | rev | cut -c 3- | rev) - link_speed=$(awk '{print $2}' <<< "$link") - interface_2=$(awk '{print $3}' <<< "$link" | cut -c 4-) - candidate="$interface_2-- $link_speed ---$interface_1" - if grep -q -F "$candidate" "$report"; then - duplicate=$candidate - break - fi - done < <(grep -E -- '-- [[:digit:]]+[GM] ---' "$report") + duplicate="" + while read -r link; do + interface_1=$(awk '{print $1}' <<<"$link" | rev | cut -c 3- | rev) + link_speed=$(awk '{print $2}' <<<"$link") + interface_2=$(awk '{print $3}' <<<"$link" | cut -c 4-) + candidate="$interface_2-- $link_speed ---$interface_1" + if grep -q -F "$candidate" "$report"; then + duplicate=$candidate + break + fi + done < <(grep -E -- '-- [[:digit:]]+[GM] ---' "$report") - [[ -n "$duplicate" ]] || break - tempfile=$(mktemp -t sbee-lldp-graph.XXXXXX) - awk -v pattern="$duplicate" 'index($0, pattern) == 0' "$report" > "$tempfile" - mv "$tempfile" "$report" + [[ -n $duplicate ]] || break + tempfile=$(mktemp -t sbee-lldp-graph.XXXXXX) + awk -v pattern="$duplicate" 'index($0, pattern) == 0' "$report" >"$tempfile" + mv "$tempfile" "$report" done diff --git a/docs/get-lldp-neighbors.sh b/docs/get-lldp-neighbors.sh index 01f8d12..1396412 100755 --- a/docs/get-lldp-neighbors.sh +++ b/docs/get-lldp-neighbors.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash set -euo pipefail -if [[ -z "${1:-}" ]]; then - echo "Usage: $(basename "$0") host" >&2 - exit 1 +if [[ -z ${1:-} ]]; then + echo "Usage: $(basename "$0") host" >&2 + exit 1 fi target=$1 @@ -12,17 +12,17 @@ report="$hostname" lldp=$(ssh "$target" -- networkctl lldp --json=short) while IFS=$' ' read -r interface neighbor_interface neighbor_name; do - [[ -z "$interface" ]] && continue - link_speed=$(ssh "$target" -- cat "/sys/class/net/$interface/speed" < /dev/null) + [[ -z $interface ]] && continue + link_speed=$(ssh "$target" -- cat "/sys/class/net/$interface/speed" = 1000 )); then - speed="$((link_speed / 1000))G" - else - speed="${link_speed}M" - fi - echo "$interface $speed $neighbor_interface $neighbor_name" + if ((link_speed >= 1000)); then + speed="$((link_speed / 1000))G" + else + speed="${link_speed}M" + fi + echo "$interface $speed $neighbor_interface $neighbor_name" done < <( - python3 -c ' + python3 -c ' import json import sys @@ -37,7 +37,7 @@ for interface in data.get("Neighbors", []): ) remote_name = neighbor.get("SystemName") or neighbor.get("ChassisID") print(name, remote_interface, remote_name, sep="\t") -' <<< "$lldp" -) > "$report" +' <<<"$lldp" +) >"$report" echo "wrote $report" >&2 diff --git a/docs/hosts/README.md b/docs/hosts/README.md index 388bc1b..2d07aaf 100644 --- a/docs/hosts/README.md +++ b/docs/hosts/README.md @@ -10,7 +10,7 @@ ## 하드웨어 보고서 -저장소 devShell에서 전체 inventory를 갱신합니다. 대상은 [공용 SSH 설정](../dev/ssh-access.md#공용-ssh-설정)에 등록되어 있어야 하며 원격 `sudo` 권한이 필요합니다. +저장소 devShell에서 전체 inventory를 갱신합니다. 대상은 [공용 SSH 설정](../dev/ssh-access.md#%EA%B3%B5%EC%9A%A9-ssh-%EC%84%A4%EC%A0%95)에 등록되어 있어야 하며 원격 `sudo` 권한이 필요합니다. ```bash nix develop diff --git a/docs/hosts/eta.md b/docs/hosts/eta.md index ee45ad6..94c55e3 100644 --- a/docs/hosts/eta.md +++ b/docs/hosts/eta.md @@ -98,4 +98,5 @@ Info: Packages: pm: nix-default pkgs: 0 pm: nix-sys pkgs: 588 libs: 58 pm: nix-usr pkgs: 0 Compilers: gcc: 15.3.0 Client: Sudo v: 1.9.17p2 inxi: 3.3.41 ``` + ![hardware topology](eta.lstopo.svg) diff --git a/docs/hosts/psi.md b/docs/hosts/psi.md index 8756e00..945eec5 100644 --- a/docs/hosts/psi.md +++ b/docs/hosts/psi.md @@ -187,4 +187,5 @@ Info: Packages: pm: nix-default pkgs: 0 pm: nix-sys pkgs: 557 libs: 86 pm: nix-usr pkgs: 0 Compilers: gcc: 15.3.0 Client: Sudo v: 1.9.17p2 inxi: 3.3.41 ``` + ![hardware topology](psi.lstopo.svg) diff --git a/docs/hosts/rho.md b/docs/hosts/rho.md index 9bb6663..2f011ab 100644 --- a/docs/hosts/rho.md +++ b/docs/hosts/rho.md @@ -130,4 +130,5 @@ Info: Packages: pm: nix-default pkgs: 0 pm: nix-sys pkgs: 438 libs: 54 pm: nix-usr pkgs: 0 Compilers: gcc: 15.3.0 Client: Sudo v: 1.9.17p2 inxi: 3.3.41 ``` + ![hardware topology](rho.lstopo.svg) diff --git a/docs/hosts/tau.md b/docs/hosts/tau.md index 22e4222..4894ab2 100644 --- a/docs/hosts/tau.md +++ b/docs/hosts/tau.md @@ -130,4 +130,5 @@ Info: Packages: pm: nix-default pkgs: 0 pm: nix-sys pkgs: 555 libs: 84 pm: nix-usr pkgs: 0 Compilers: gcc: 15.3.0 Client: Sudo v: 1.9.17p2 inxi: 3.3.41 ``` + ![hardware topology](tau.lstopo.svg) diff --git a/tasks.py b/tasks.py index de1b8a0..a8a9250 100755 --- a/tasks.py +++ b/tasks.py @@ -187,11 +187,10 @@ def update_lldp_info(c: Any, hosts: str = "") -> None: graph_script = ROOT / "docs" / "generate-lldp-graph.sh" output_dir.mkdir(parents=True, exist_ok=True) - with TemporaryDirectory(prefix="lldp-", dir=output_dir) as lldp_dir: - with c.cd(lldp_dir): - for host in inventory_hostnames(hosts): - c.run(f"{shlex.quote(str(collect_script))} {shlex.quote(host)}") - c.run(shlex.quote(str(graph_script))) + with TemporaryDirectory(prefix="lldp-", dir=output_dir) as lldp_dir, c.cd(lldp_dir): + for host in inventory_hostnames(hosts): + c.run(f"{shlex.quote(str(collect_script))} {shlex.quote(host)}") + c.run(shlex.quote(str(graph_script))) @task diff --git a/tests/test_generate_network_topology.py b/tests/test_generate_network_topology.py index 67c98fa..5aee91a 100644 --- a/tests/test_generate_network_topology.py +++ b/tests/test_generate_network_topology.py @@ -2,7 +2,6 @@ import importlib.util import unittest from pathlib import Path - SCRIPT = Path(__file__).parents[1] / "docs" / "generate-network-topology.py"