#!/usr/bin/env bash # ScadaBridge#125 — the failover probe against the REAL docker-dev OtOpcUa pair (central-1 :4840 / # central-2 :4841), not the in-process fixture. ScadaBridge's DataConnectionActor connects to central-1 # as primary and central-2 as backup; once it reports a steady primary, central-1's container is killed # (docker kill = abrupt loss) and the probe must land on central-2 with Good values and a fresh # ConditionRefresh. central-1 is started again afterwards. LOCAL docker-dev only — never a wonder box. # # Usage: rig-failover.sh # Anonymous (OpcUa:AllowAnonymous=true on the rig) cannot write there, so writes are off; the rig deploys # no active native alarm, so the alarm check is "ConditionRefresh completes on each node" only. set -euo pipefail probe=$1; out=$2 primary_container=${RIG_PRIMARY_CONTAINER:-otopcua-dev-central-1-1} backup_container=${RIG_BACKUP_CONTAINER:-otopcua-dev-central-2-1} mkdir -p "$out" for c in "$primary_container" "$backup_container"; do mkdir -p "$out/server-certs/$c" docker cp "$c:/app/pki/own/certs/." "$out/server-certs/$c/" done export SCADABRIDGE_PROBE_ANONYMOUS=1 export SCADABRIDGE_PROBE_SERVER_CERTS="$out/server-certs/$primary_container:$out/server-certs/$backup_container" export SCADABRIDGE_PROBE_FAILOVER_TAGS=${RIG_TAGS:-"nsu=https://zb.com/otopcua/raw;s=int3b-mb-01/plc/HR100,nsu=https://zb.com/otopcua/uns;s=a/l/e1/HR5"} export SCADABRIDGE_PROBE_FAILOVER_WRITE_TAG=none export SCADABRIDGE_PROBE_FAILOVER_BACKUP_VALUE=none export SCADABRIDGE_PROBE_FAILOVER_ALARM_PREFIX=none dotnet "$probe" failover opc.tcp://localhost:${RIG_PRIMARY_PORT:-4840} opc.tcp://localhost:${RIG_BACKUP_PORT:-4841} None "$out/consumer" \ > "$out/consumer.log" 2>&1 & pid=$! for _ in $(seq 1 1500); do [[ -f "$out/consumer/primary-ready" ]] && break kill -0 "$pid" 2>/dev/null || break sleep 0.1 done status=0 if [[ -f "$out/consumer/primary-ready" ]]; then python3 -c 'from datetime import datetime, timezone; print(datetime.now(timezone.utc).isoformat())' > "$out/consumer/primary-killed.tmp" docker kill "$primary_container" > /dev/null mv "$out/consumer/primary-killed.tmp" "$out/consumer/primary-killed" wait "$pid" || status=$? docker start "$primary_container" > /dev/null else wait "$pid" || status=$? fi docker inspect "$primary_container" "$backup_container" --format '{{.Name}} {{.Config.Image}} {{.Image}} {{.State.Status}}' > "$out/containers.txt" echo "probe exit $status; result $out/consumer/result.json" exit "$status"