Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions packages/ytl-linux-digabi2-examnet/discovery/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ default:
format:
@just --unstable --fmt

start prod-mode="false": generate-dev-conf
start prod-mode="false" only-to-console="false": generate-dev-conf
#!/usr/bin/env bash
set -euo pipefail

Expand All @@ -27,11 +27,18 @@ start prod-mode="false": generate-dev-conf
}
EOF
)

if [[ "{{ only-to-console }}" == "true" ]]; then
export CONSOLE_ONLY_OUTPUT=true
fi

deno run dev "$CONFIG"

start-prod:
just start prod-mode="true"
just start true

start-oneshot:
just start false true

test flags="":
LOG_LEVEL=silent deno run tests -- {{ flags }}
Expand Down
4 changes: 2 additions & 2 deletions packages/ytl-linux-digabi2-examnet/discovery/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { z } from '@zod/zod/v4-mini'
import { z } from '@zod/zod'

export const ConfigSchema = z.object({
isProd: z.boolean(),
ktpDomains: z.array(z.string()),
dnsmasqConfigOutputFile: z.string(),
ports: z.object({
discovery: z.int().check(z.minimum(1), z.maximum(0xffff))
discovery: z.int().gte(1).lte(0xffff),
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ export interface DiscoveredKTP {
export async function fetchFromDiscoveryEndpoint(ktpDomain: string, config: Config) {
const discoveryUrl = `https://${ktpDomain}:${config.ports.discovery}${DISCOVERY_PATH}`
logger.debug(`Asking ${ktpDomain} for alias using URL ${discoveryUrl}`)
return await fetch(discoveryUrl)

return await fetch(discoveryUrl, {
signal: AbortSignal.timeout(1000)
})
}

export async function discoverFriendlyNamesInNetwork(
Expand Down
8 changes: 8 additions & 0 deletions packages/ytl-linux-digabi2-examnet/discovery/src/dnsmasq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ function checkForDuplicatesAndRemove(discovered: DiscoveredKTP[]): DiscoveredKTP
}

export async function writeDnsmasqConfig(discovered: DiscoveredKTP[], config: Config) {
if (Deno.env.get('CONSOLE_ONLY_OUTPUT') === 'true') {
logger.info(`Console only output mode enabled, will not write any files and outputting results directly to stdout`)

console.log(JSON.stringify({ discovered }, null, 2))

return
}

const deduped = checkForDuplicatesAndRemove(discovered)
const hostRecordEntries = deduped.map(x => `host-record=${x.alias},${x.target}`)

Expand Down
8 changes: 7 additions & 1 deletion packages/ytl-linux-digabi2-examnet/discovery/src/logger.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import pino from 'pino'
import pretty from 'pino-pretty'

const logger = pino({ level: Deno.env.get('LOG_LEVEL') ?? 'debug' }, pretty())
// When running the discovery in oneshot mode to get its output, we need to direct all logs to stderr so they don't contaminate stdout
const LOG_DESTINATION = Deno.env.get('CONSOLE_ONLY_OUTPUT') === 'true' ? 2 : 1

const logger = pino(
{ level: Deno.env.get('LOG_LEVEL') ?? 'debug' },
pretty({ destination: LOG_DESTINATION, colorize: true })
)

export default logger
109 changes: 10 additions & 99 deletions packages/ytl-linux-digabi2-examnet/ytl-linux-digabi2-examnet
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ readonly EXIT_CODE_CANNOT_RESTART_LAN_DEVICE=12 # Cannot start local netwo
readonly EXIT_CODE_CANNOT_RESTART_DNSMASQ=13 # Cannot restart dnsmasq
readonly EXIT_CODE_CANNOT_RESTART_NM=14 # Cannot restart NetworkManager
readonly EXIT_CODE_WAN_WITH_NO_IP=15 # Given WAN device does not have an IPv4 address
readonly EXIT_CODE_NO_GUI_FOR_ROOT=16 # You shouldn't execute the script by root in GUI mode (use sudo instead)
readonly EXIT_CODE_CANNOT_REMOVE_FILES=17 # The script was executed with --remove, but it could not remove settings files
readonly EXIT_CODE_CANNOT_REMOVE_CONNECTION=18 # The script was executed with --remove, but it could not remove a connection
readonly EXIT_CODE_CANNOT_RESTART_DOCKER=19 # Cannot restart docker
Expand Down Expand Up @@ -72,7 +71,6 @@ readonly BIN_MKDIR=/usr/bin/mkdir
readonly BIN_SYSTEMCTL=/usr/bin/systemctl
readonly BIN_NMCLI=/usr/bin/nmcli
readonly BIN_NM_ONLINE=/usr/bin/nm-online
readonly BIN_ZENITY=/usr/bin/zenity
readonly BIN_SED=/usr/bin/sed
readonly BIN_XARGS=/usr/bin/xargs
readonly BIN_OPENSSL=/usr/bin/openssl
Expand Down Expand Up @@ -113,26 +111,17 @@ function debug() {
function print_error() {
_ERROR_MESSAGE=$1
debug "ERROR: $_ERROR_MESSAGE"
if [ $GUI_MODE -gt 0 ]; then
$BIN_ZENITY --error --text="$_ERROR_MESSAGE"
else
$BIN_ECHO "$SCRIPT_PATH error: $_ERROR_MESSAGE" >&2
fi
$BIN_ECHO "$SCRIPT_PATH error: $_ERROR_MESSAGE" >&2
}

function print_info() {
_INFO_MESSAGE=$1
debug "INFO: $_INFO_MESSAGE"
if [ $GUI_MODE -gt 0 ]; then
$BIN_ZENITY --info --text="$_INFO_MESSAGE"
else
$BIN_ECHO "$SCRIPT_PATH info: $_INFO_MESSAGE"
fi
$BIN_ECHO "$SCRIPT_PATH info: $_INFO_MESSAGE"
}

function print_usage() {
$BIN_ECHO "usage: $SCRIPT_PATH wan-network-device local-network-device server-number [custom-server-name] [--use-static-local-dns]" >&2
$BIN_ECHO " $SCRIPT_PATH --gui" >&2
$BIN_ECHO " $SCRIPT_PATH --daemon" >&2
$BIN_ECHO " $SCRIPT_PATH --discover" >&2
$BIN_ECHO " $SCRIPT_PATH --remove" >&2
Expand Down Expand Up @@ -164,12 +153,6 @@ function current_user_is_root () {
fi
}

function current_user_is_sudo () {
if [ "$SUDO_UID" ] ; then
echo 1
fi
}

function network_enumerate_devices () {
for dir in /sys/class/net/*; do
device=$(basename "$dir")
Expand All @@ -179,44 +162,6 @@ function network_enumerate_devices () {
done
}

function network_enumerate_devices_with_information () {
device_to_skip=$1

devices=$(network_enumerate_devices)

for device in $devices; do
if [ -n "$device_to_skip" ] && [ "$device" == "$device_to_skip" ]; then
continue
fi

ip=$(ip addr show dev "$device" | grep "inet " | awk '{print $2}' | cut -d/ -f1)
if [ -z "$ip" ]; then
ip=-
fi

connect=$(ip link show dev "$device" | grep -q "state UP" && echo "Connected" || echo "Disconnected")
if [ -z "$connect" ]; then
connect=-
fi

echo "$device" "$ip" "$connect"
done
}

function ask_network_device () {
question=$1
device_to_skip=$2

devices=$(network_enumerate_devices_with_information "$device_to_skip")

# shellcheck disable=SC2086
$BIN_ZENITY --list --title "$question" \
--column "Device" --column "IPv4" --column "Connection" \
--width=400 --height=400 \
$devices
}


function network_device_exists() {
_DEVICE=$1
$BIN_IP link show "$_DEVICE" &> /dev/null && $BIN_ECHO "1"
Expand Down Expand Up @@ -564,7 +509,7 @@ function configure_static_dns_records() {

debug "Configuring domain for KTP"
debug "This server's domain based on server number ($SERVER_NUMBER) is: $THIS_SERVER_DOMAIN"
write_file $PATH_NAKSU2_DOMAIN "$THIS_SERVER_DOMAIN" "$NAKSU2_WORKDIR_OWNER"
write_file "$PATH_NAKSU2_DOMAIN" "$THIS_SERVER_DOMAIN" "$NAKSU2_WORKDIR_OWNER"
}

function remove_school_host_entries() {
Expand All @@ -578,8 +523,6 @@ if [ -z "$PARAM_NET_DEVICE_WAN" ]; then
exit_script $EXIT_CODE_NETWORK_DEVICE_NAME_MISSING_WAN
fi

GUI_MODE=0

if [ ! "$(current_user_is_root)" ]; then
print_error "You're not root"
exit_script $EXIT_CODE_MUST_BE_ROOT
Expand Down Expand Up @@ -676,41 +619,14 @@ if [[ $* == *--use-static-local-dns* ]]; then
USE_STATIC_LOCAL_DNS=1
fi

if [[ $* == *--gui* ]]; then
if [ ! "$(current_user_is_sudo)" ]; then
print_error "GUI mode cannot be executed as root, since typically root does not have access to user's desktop session"
exit_script $EXIT_CODE_NO_GUI_FOR_ROOT
fi

GUI_MODE=1
NET_DEVICE_WAN=$(ask_network_device "Select internet (WAN) network device")
if [ -z "$NET_DEVICE_WAN" ]; then
print_error "Missing WAN network device name"
exit_script $EXIT_CODE_NETWORK_DEVICE_NAME_MISSING_WAN
fi
else
NET_DEVICE_WAN=$PARAM_NET_DEVICE_WAN
fi

if [ $GUI_MODE -gt 0 ]; then
NET_DEVICE_LAN=$(ask_network_device "Select local (LAN) network device" "$NET_DEVICE_WAN")
if [ -z "$NET_DEVICE_LAN" ]; then
print_error "Missing LAN network device name"
exit_script $EXIT_CODE_NETWORK_DEVICE_NAME_MISSING_LAN
fi
else
NET_DEVICE_LAN=$PARAM_NET_DEVICE_LAN
fi
NET_DEVICE_WAN=$PARAM_NET_DEVICE_WAN
NET_DEVICE_LAN=$PARAM_NET_DEVICE_LAN

debug "NET_DEVICE_WAN: $NET_DEVICE_WAN"
debug "NET_DEVICE_LAN: $NET_DEVICE_LAN"
check_network_device_names "$NET_DEVICE_WAN" "$NET_DEVICE_LAN"

if [ $GUI_MODE -gt 0 ]; then
SERVER_NUMBER=$($BIN_ZENITY --entry --title="Server number" --text="Enter server number ($CONST_MIN_SERVER_NUMBER-$CONST_MAX_SERVER_NUMBER)")
else
SERVER_NUMBER=$PARAM_SERVER_NUMBER
fi
SERVER_NUMBER=$PARAM_SERVER_NUMBER

debug "SERVER_NUMBER: $SERVER_NUMBER"
check_server_number "$SERVER_NUMBER"
Expand Down Expand Up @@ -769,15 +685,10 @@ NCSI_HOSTNAMES_LIST=$(cat $PATH_EXAMNET_CONFIG/ncsi-hostnames)
debug "NCSI_HOSTNAMES_LIST: $NCSI_HOSTNAMES_LIST"
export NCSI_HOSTNAMES_LIST


if [[ $GUI_MODE -gt 0 ]]; then
SERVER_FRIENDLY_NAME=$($BIN_ZENITY --entry --title="Custom server name" --text="Enter custom name for this server, e.g. 'classroom' (leave empty for no custom name)")
if [[ ! $PARAM_SERVER_FRIENDLY_NAME =~ ^--.+$ ]]; then
SERVER_FRIENDLY_NAME=$PARAM_SERVER_FRIENDLY_NAME
else
if [[ ! $PARAM_SERVER_FRIENDLY_NAME =~ ^--.+$ ]]; then
SERVER_FRIENDLY_NAME=$PARAM_SERVER_FRIENDLY_NAME
else
SERVER_FRIENDLY_NAME=""
fi
SERVER_FRIENDLY_NAME=""
fi

if [ -n "$SERVER_FRIENDLY_NAME" ]; then
Expand All @@ -801,7 +712,7 @@ wait_for_network_online
if [ -z "$SERVER_FRIENDLY_NAME" ]; then
debug "User did not provide friendly name, falling back to static DNS name"
# Fallback to use server's static DNS name (e.g. ktp1)
SERVER_FRIENDLY_NAME=$(cat $PATH_NAKSU2_DOMAIN | cut -d '.' -f1)
SERVER_FRIENDLY_NAME=$(cat "$PATH_NAKSU2_DOMAIN" | cut -d '.' -f1)
fi

debug "SERVER_FRIENDLY_NAME: $SERVER_FRIENDLY_NAME"
Expand Down
Loading