You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
9.8 KiB
216 lines
9.8 KiB
|
2 months ago
|
$ErrorActionPreference = 'Stop'
|
||
|
|
$project = Split-Path -Parent $PSScriptRoot
|
||
|
|
Start-Transcript -Path (Join-Path $project 'runtime/replacement-default-port-transfer.log') -Force | Out-Null
|
||
|
|
$assets = @{}
|
||
|
|
$hashes = @{}
|
||
|
|
$assets['/api'] = Join-Path $project 'final-build/backend/tera-clone-demo-api'
|
||
|
|
$assets['/web'] = Join-Path $project 'final-build/frontend/tera-clone-demo-web'
|
||
|
|
$assets['/timed'] = Join-Path $project 'final-build/backend/tera-timed'
|
||
|
|
$assets['/alarmd'] = Join-Path $project 'final-build/backend/tera-clone-demo-alarmd'
|
||
|
|
$assets['/seriald'] = Join-Path $project 'final-build/backend/tera-seriald'
|
||
|
|
$assets['/logd'] = Join-Path $project 'final-build/backend/tera-logd'
|
||
|
|
$assets['/netd'] = Join-Path $project 'final-build/backend/tera-netd'
|
||
|
|
$assets['/sessiond'] = Join-Path $project 'final-build/backend/tera-sessiond'
|
||
|
|
foreach ($key in $assets.Keys) { $hashes[$key] = (Get-FileHash -LiteralPath $assets[$key] -Algorithm SHA256).Hash.ToLowerInvariant() }
|
||
|
|
$script = @'
|
||
|
|
#!/bin/sh
|
||
|
|
set -eu
|
||
|
|
stage=/tmp/tera-replacement-default-port
|
||
|
|
mkdir -p "$stage"
|
||
|
|
wget -q -T 25 -O "$stage/api" http://192.168.0.100:9001/api
|
||
|
|
echo '__APIHASH__ '"$stage/api" | sha256sum -c -
|
||
|
|
wget -q -T 25 -O "$stage/web" http://192.168.0.100:9001/web
|
||
|
|
echo '__WEBHASH__ '"$stage/web" | sha256sum -c -
|
||
|
|
wget -q -T 25 -O "$stage/timed" http://192.168.0.100:9001/timed
|
||
|
|
echo '__TIMEDHASH__ '"$stage/timed" | sha256sum -c -
|
||
|
|
wget -q -T 25 -O "$stage/alarmd" http://192.168.0.100:9001/alarmd
|
||
|
|
echo '__ALARMDHASH__ '"$stage/alarmd" | sha256sum -c -
|
||
|
|
wget -q -T 25 -O "$stage/seriald" http://192.168.0.100:9001/seriald
|
||
|
|
echo '__SERIALDHASH__ '"$stage/seriald" | sha256sum -c -
|
||
|
|
wget -q -T 25 -O "$stage/logd" http://192.168.0.100:9001/logd
|
||
|
|
echo '__LOGDHASH__ '"$stage/logd" | sha256sum -c -
|
||
|
|
wget -q -T 25 -O "$stage/netd" http://192.168.0.100:9001/netd
|
||
|
|
echo '__NETDHASH__ '"$stage/netd" | sha256sum -c -
|
||
|
|
wget -q -T 25 -O "$stage/sessiond" http://192.168.0.100:9001/sessiond
|
||
|
|
echo '__SESSIONDHASH__ '"$stage/sessiond" | sha256sum -c -
|
||
|
|
backup=/userdata/tera-backups/replacement-default-port-$(date +%Y%m%d-%H%M%S)
|
||
|
|
mkdir -p "$backup"
|
||
|
|
cp -p /etc/tera/teraweb.env "$backup/teraweb.env"
|
||
|
|
echo "BACKUP=$backup"
|
||
|
|
cp -p /usr/bin/tera-api "$backup/api"
|
||
|
|
cp "$stage/api" /usr/bin/tera-api.next
|
||
|
|
chmod 0755 /usr/bin/tera-api.next
|
||
|
|
cp -p /usr/bin/tera-clone-demo-web "$backup/web"
|
||
|
|
cp "$stage/web" /usr/bin/tera-clone-demo-web.next
|
||
|
|
chmod 0755 /usr/bin/tera-clone-demo-web.next
|
||
|
|
cp -p /usr/bin/tera-timed "$backup/timed"
|
||
|
|
cp "$stage/timed" /usr/bin/tera-timed.next
|
||
|
|
chmod 0755 /usr/bin/tera-timed.next
|
||
|
|
cp -p /usr/bin/tera-alarmd "$backup/alarmd"
|
||
|
|
cp "$stage/alarmd" /usr/bin/tera-alarmd.next
|
||
|
|
chmod 0755 /usr/bin/tera-alarmd.next
|
||
|
|
cp -p /usr/bin/tera-seriald "$backup/seriald"
|
||
|
|
cp "$stage/seriald" /usr/bin/tera-seriald.next
|
||
|
|
chmod 0755 /usr/bin/tera-seriald.next
|
||
|
|
cp -p /usr/bin/tera-logd "$backup/logd"
|
||
|
|
cp "$stage/logd" /usr/bin/tera-logd.next
|
||
|
|
chmod 0755 /usr/bin/tera-logd.next
|
||
|
|
cp -p /usr/bin/tera-netd "$backup/netd"
|
||
|
|
cp "$stage/netd" /usr/bin/tera-netd.next
|
||
|
|
chmod 0755 /usr/bin/tera-netd.next
|
||
|
|
cp -p /usr/bin/tera-sessiond "$backup/sessiond"
|
||
|
|
cp "$stage/sessiond" /usr/bin/tera-sessiond.next
|
||
|
|
chmod 0755 /usr/bin/tera-sessiond.next
|
||
|
|
rollback() {
|
||
|
|
trap - EXIT
|
||
|
|
/etc/init.d/S61teraweb stop || true
|
||
|
|
/etc/init.d/S55tera-sessiond stop || true
|
||
|
|
/etc/init.d/S50tera-api stop || true
|
||
|
|
/etc/init.d/S40tera-seriald stop || true
|
||
|
|
/etc/init.d/S47tera-alarmd stop || true
|
||
|
|
/etc/init.d/S43tera-netd stop || true
|
||
|
|
/etc/init.d/S45tera-timed stop || true
|
||
|
|
/etc/init.d/S44tera-logd stop || true
|
||
|
|
sleep 2
|
||
|
|
cp "$backup/api" /usr/bin/tera-api.restore
|
||
|
|
chmod 0755 /usr/bin/tera-api.restore
|
||
|
|
mv /usr/bin/tera-api.restore /usr/bin/tera-api
|
||
|
|
cp "$backup/web" /usr/bin/tera-clone-demo-web.restore
|
||
|
|
chmod 0755 /usr/bin/tera-clone-demo-web.restore
|
||
|
|
mv /usr/bin/tera-clone-demo-web.restore /usr/bin/tera-clone-demo-web
|
||
|
|
cp "$backup/timed" /usr/bin/tera-timed.restore
|
||
|
|
chmod 0755 /usr/bin/tera-timed.restore
|
||
|
|
mv /usr/bin/tera-timed.restore /usr/bin/tera-timed
|
||
|
|
cp "$backup/alarmd" /usr/bin/tera-alarmd.restore
|
||
|
|
chmod 0755 /usr/bin/tera-alarmd.restore
|
||
|
|
mv /usr/bin/tera-alarmd.restore /usr/bin/tera-alarmd
|
||
|
|
cp "$backup/seriald" /usr/bin/tera-seriald.restore
|
||
|
|
chmod 0755 /usr/bin/tera-seriald.restore
|
||
|
|
mv /usr/bin/tera-seriald.restore /usr/bin/tera-seriald
|
||
|
|
cp "$backup/logd" /usr/bin/tera-logd.restore
|
||
|
|
chmod 0755 /usr/bin/tera-logd.restore
|
||
|
|
mv /usr/bin/tera-logd.restore /usr/bin/tera-logd
|
||
|
|
cp "$backup/netd" /usr/bin/tera-netd.restore
|
||
|
|
chmod 0755 /usr/bin/tera-netd.restore
|
||
|
|
mv /usr/bin/tera-netd.restore /usr/bin/tera-netd
|
||
|
|
/etc/init.d/S43tera-netd start || true
|
||
|
|
/etc/init.d/S44tera-logd start || true
|
||
|
|
/etc/init.d/S40tera-seriald start || true
|
||
|
|
/etc/init.d/S45tera-timed start || true
|
||
|
|
/etc/init.d/S47tera-alarmd start || true
|
||
|
|
/etc/init.d/S50tera-api start || true
|
||
|
|
cp "$backup/sessiond" /usr/bin/tera-sessiond.restore
|
||
|
|
chmod 0755 /usr/bin/tera-sessiond.restore
|
||
|
|
mv /usr/bin/tera-sessiond.restore /usr/bin/tera-sessiond
|
||
|
|
/etc/init.d/S55tera-sessiond start || true
|
||
|
|
/etc/init.d/S61teraweb start || true
|
||
|
|
echo REPLACEMENT_DEFAULT_PORT_ROLLED_BACK
|
||
|
|
}
|
||
|
|
trap rollback EXIT
|
||
|
|
/etc/init.d/S55tera-sessiond stop
|
||
|
|
/etc/init.d/S43tera-netd stop
|
||
|
|
/etc/init.d/S61teraweb stop
|
||
|
|
/etc/init.d/S50tera-api stop
|
||
|
|
/etc/init.d/S40tera-seriald stop
|
||
|
|
/etc/init.d/S47tera-alarmd stop
|
||
|
|
/etc/init.d/S45tera-timed stop
|
||
|
|
/etc/init.d/S44tera-logd stop
|
||
|
|
sleep 2
|
||
|
|
mv /usr/bin/tera-netd.next /usr/bin/tera-netd
|
||
|
|
/etc/init.d/S43tera-netd start
|
||
|
|
mv /usr/bin/tera-sessiond.next /usr/bin/tera-sessiond
|
||
|
|
mv /usr/bin/tera-api.next /usr/bin/tera-api
|
||
|
|
mv /usr/bin/tera-clone-demo-web.next /usr/bin/tera-clone-demo-web
|
||
|
|
mv /usr/bin/tera-timed.next /usr/bin/tera-timed
|
||
|
|
mv /usr/bin/tera-alarmd.next /usr/bin/tera-alarmd
|
||
|
|
mv /usr/bin/tera-seriald.next /usr/bin/tera-seriald
|
||
|
|
mv /usr/bin/tera-logd.next /usr/bin/tera-logd
|
||
|
|
/etc/init.d/S44tera-logd start
|
||
|
|
/etc/init.d/S40tera-seriald start
|
||
|
|
/etc/init.d/S45tera-timed start
|
||
|
|
/etc/init.d/S47tera-alarmd start
|
||
|
|
(
|
||
|
|
set -a
|
||
|
|
. /etc/tera/tera-api.env
|
||
|
|
set +a
|
||
|
|
start-stop-daemon -S -q -b -m -p /run/tera-api.pid -c tera:tera -x /bin/sh -- -c 'exec /usr/bin/tera-api > /run/tera-api/replacement-startup.log 2>&1'
|
||
|
|
)
|
||
|
|
/etc/init.d/S55tera-sessiond start
|
||
|
|
/etc/init.d/S61teraweb start
|
||
|
|
ready=0
|
||
|
|
for n in $(seq 1 120); do
|
||
|
|
if wget -q -T 2 -O "$stage/status" http://127.0.0.1/login/backend-status; then
|
||
|
|
if grep -q '"ready":true' "$stage/status" && grep -q '"completed":12' "$stage/status"; then ready=1; break; fi
|
||
|
|
fi
|
||
|
|
if [ $((n % 15)) = 0 ]; then tail -3 /run/tera-api/replacement-startup.log; fi
|
||
|
|
sleep 1
|
||
|
|
done
|
||
|
|
cat "$stage/status"
|
||
|
|
if [ "$ready" != 1 ]; then tail -40 /run/tera-api/replacement-startup.log; exit 1; fi
|
||
|
|
wget -q -T 3 -O "$stage/login.js" http://127.0.0.1/static/js/login.js
|
||
|
|
grep -q '/login/bootstrap-time' "$stage/login.js"
|
||
|
|
grep -q '^PORT=80$' /etc/tera/teraweb.env
|
||
|
|
sha256sum /usr/bin/tera-sessiond /usr/bin/tera-netd /usr/bin/tera-api /usr/bin/tera-clone-demo-web /usr/bin/tera-timed /usr/bin/tera-alarmd /usr/bin/tera-seriald /usr/bin/tera-logd
|
||
|
|
sync
|
||
|
|
trap - EXIT
|
||
|
|
echo REPLACEMENT_DEFAULT_PORT_DEPLOY_OK
|
||
|
|
'@
|
||
|
|
$script = $script.Replace('__APIHASH__', $hashes['/api'])
|
||
|
|
$script = $script.Replace('__WEBHASH__', $hashes['/web'])
|
||
|
|
$script = $script.Replace('__TIMEDHASH__', $hashes['/timed'])
|
||
|
|
$script = $script.Replace('__ALARMDHASH__', $hashes['/alarmd'])
|
||
|
|
$script = $script.Replace('__SERIALDHASH__', $hashes['/seriald'])
|
||
|
|
$script = $script.Replace('__LOGDHASH__', $hashes['/logd'])
|
||
|
|
$script = $script.Replace('__NETDHASH__', $hashes['/netd'])
|
||
|
|
$script = $script.Replace('__SESSIONDHASH__', $hashes['/sessiond'])
|
||
|
|
$script = $script.Replace("`r`n", "`n") + "`n"
|
||
|
|
$rule = 'TERA-replacement-default-port-' + [guid]::NewGuid().ToString('N')
|
||
|
|
$listener = New-Object System.Net.HttpListener
|
||
|
|
$listener.Prefixes.Add('http://192.168.0.100:9001/')
|
||
|
|
$serial = New-Object System.IO.Ports.SerialPort 'COM4',115200,'None',8,'One'
|
||
|
|
$serial.Encoding = [Text.Encoding]::UTF8
|
||
|
|
try {
|
||
|
|
New-NetFirewallRule -DisplayName $rule -Direction Inbound -Action Allow -Protocol TCP -LocalPort 9001 -RemoteAddress 192.168.0.223 | Out-Null
|
||
|
|
$listener.Start()
|
||
|
|
$serial.Open()
|
||
|
|
$serial.WriteLine('wget -q -O /tmp/deploy-replacement-default-port.sh http://192.168.0.100:9001/deploy.sh && sh /tmp/deploy-replacement-default-port.sh')
|
||
|
|
$deadline = [DateTime]::UtcNow.AddSeconds(360)
|
||
|
|
$output = ''
|
||
|
|
$pending = $listener.GetContextAsync()
|
||
|
|
while ([DateTime]::UtcNow -lt $deadline) {
|
||
|
|
if ($pending.IsCompleted) {
|
||
|
|
$context = $pending.GetAwaiter().GetResult()
|
||
|
|
if ($context.Request.RemoteEndPoint.Address.ToString() -ne '192.168.0.223') {
|
||
|
|
$context.Response.StatusCode = 403
|
||
|
|
$context.Response.Close()
|
||
|
|
} else {
|
||
|
|
$bytes = $null
|
||
|
|
$route = $context.Request.Url.AbsolutePath
|
||
|
|
if ($route -eq '/deploy.sh') { $bytes = [Text.Encoding]::UTF8.GetBytes($script) }
|
||
|
|
elseif ($assets.ContainsKey($route)) { $bytes = [IO.File]::ReadAllBytes($assets[$route]) }
|
||
|
|
else { $context.Response.StatusCode = 404 }
|
||
|
|
if ($null -ne $bytes) {
|
||
|
|
$context.Response.ContentLength64 = $bytes.Length
|
||
|
|
$context.Response.OutputStream.Write($bytes, 0, $bytes.Length)
|
||
|
|
}
|
||
|
|
$context.Response.Close()
|
||
|
|
}
|
||
|
|
$pending = $listener.GetContextAsync()
|
||
|
|
}
|
||
|
|
$chunk = $serial.ReadExisting()
|
||
|
|
if ($chunk) { $output += $chunk; Write-Host -NoNewline $chunk }
|
||
|
|
if ($output.Contains('REPLACEMENT_DEFAULT_PORT_ROLLED_BACK')) { throw 'Readiness failed; old pair restored.' }
|
||
|
|
if ($output.Contains('REPLACEMENT_DEFAULT_PORT_DEPLOY_OK')) { break }
|
||
|
|
Start-Sleep -Milliseconds 100
|
||
|
|
}
|
||
|
|
if (-not $output.Contains('REPLACEMENT_DEFAULT_PORT_DEPLOY_OK')) { throw 'Deployment did not report success; inspect device console.' }
|
||
|
|
foreach ($hash in $hashes.Values) { if (-not $output.Contains($hash)) { throw 'A deployed hash was not verified.' } }
|
||
|
|
Write-Output 'VERIFIED replacement device deployment on HTTP port 80'
|
||
|
|
} finally {
|
||
|
|
if ($serial.IsOpen) { $serial.Close() }
|
||
|
|
$serial.Dispose()
|
||
|
|
$listener.Close()
|
||
|
|
Remove-NetFirewallRule -DisplayName $rule -ErrorAction SilentlyContinue
|
||
|
|
Stop-Transcript | Out-Null
|
||
|
|
}
|