diff --git a/hardware-to-mkd b/hardware-to-mkd new file mode 100755 index 0000000..f501e81 --- /dev/null +++ b/hardware-to-mkd @@ -0,0 +1,149 @@ +#!/bin/sh + +if [ "$(whoami)" != "root" ]; then + echo "This script is intended to run as root. Exiting" >&2 + exit 1 +fi + +for cmd in lshw jq; do + if ! command -v $cmd > /dev/null; then + echo "Please install $cmd. Exiting." >&2 + exit 1 + fi +done + +if [ "$1" = "" ]; then + echo "Usage: export-hardware.sh PATH_TO_OUTPUT" >&2 + exit 1 +fi + +output=$1 +if [ -d "$1" ]; then + echo "$1 is a directory and cannot be used as output. Exiting." >&2 + exit 1 +fi + +# We extract hardware details only once, as it can be somewhat expensive/slow. +echo "Extracting hardware informations.... " +hardware=$(lshw -json) +hostname=$(hostname --short) +components=$(echo "$hardware" | jq -r -c '..|.children?|select(.!=null)|.[]') +echo "--- OK" + +print_server_component () { + class=$(echo "$@"| jq -j -c .class) + if echo "system processor memory power bus" | grep -w -q "$class"; then + # Motherboards are 'bus' class and what **seem** to be consistent (from a + # server + my laptop) 'Motherboard' description. + if [ "$class" = "bus" ] && [ "$(echo "$@"| jq -j -c .description)" != "Motherboard" ]; then + return + fi + + serial=$(echo "$@"| jq -j -c '.serial // "-"') + name='\(.description // .product)' + manufacturer='\(.vendor // "-")' + model='\(.product // "-")' + + case "$class" in + "power") + name="$name (slot: \\(.slot // \"-\"))" + ;; + "system") + # Ignore irrelevant PnP (and probably others) devices. + if [ "$serial" = "-" ]; then + return + fi + ;; + "memory") + # Ignore CPU cache (= memory entries without serial number). + if [ "$serial" = "-" ]; then + return + fi + + # Extract size of RAM sticks. + units=$(echo "$@"| jq -j -c .units) + size=$(echo "$@"| jq -j -c .size) + if [ "$units" = "bytes" ]; then + model="\(.product) ($(((size / 1024 / 1024 / 1024 ))) GB)" + else + model='\(.product) (\(.size) \(.units),)' + fi + ;; + esac + + echo "$@" | jq -j -c ".|\"| $class | $name | $manufacturer | $model | $serial | \n\"" + fi +} + +get_disk_details () { + product=$(echo "$@" | jq -j -c .product) + size=$(echo "$@" | jq -j -c .size) + units=$(echo "$@" | jq -j -c .units) + serial=$(echo "$@" | jq -j -c .serial) + + if [ "$units" = "bytes" ]; then + size=$(((size / 1024 / 1024 / 1024))) + units='GB' + fi + + cat <<- EOF + $product ($serial, $size $units) + EOF +} + +### Output ### + +touch "$output" + +echo "Generating system section... " +cat <<- EOF > "$output" + # Host: $hostname + + Extracted on $(date -I) by the [hardware-to-mkd script](https://code.recycled.cloud/RecycledCloud/tools/src/branch/master/hardware-to-mkd). + + ## System + + | Class | Name | Manufacturer | Model | Serial | + |-------|------|--------------|-------|--------| + $(print_server_component "$hardware") +EOF + +echo "$components" | while read -r component; do +print_server_component "$component" >> "$output" +done +echo "--- OK" + +echo "Generating disks section... " +cat <<- EOF >> "$output" + + ## Disks + + | Disk | + |------| +EOF + echo "$components" | while read -r component; do + class=$(echo "$component"| jq -j -c .class) + if [ "$class" = "disk" ]; then + echo "| $(get_disk_details "$component") |" >> "$output" + fi +done +echo "--- OK" + +echo "Generating NICs section... " +cat <<- EOF >> "$output" + ## NICs + + | Interface | MAC | + |-----------|-----| +EOF + +echo "$components" | while read -r component; do + class=$(echo "$component"| jq -j -c .class) + if [ "$class" = "network" ]; then + serial=$(echo "$component"| jq -j -c '.serial // "-"') + iface=$(ip -j l | jq -r -c ".[] | select(.address == \"$serial\") | .ifname") + echo "| $iface | $serial |" >> "$output" + fi +done + +echo "--- OK"