feat(guanghu-os): finalize JD master and Linux subcontrol
This commit is contained in:
parent
8c2e11201e
commit
527e0cb05d
2 changed files with 111 additions and 0 deletions
|
|
@ -0,0 +1,97 @@
|
|||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
[[ $# == 1 && $1 =~ ^[0-9a-f]{40}$ ]] || { echo 'usage: set-jd-guanghu-master-default.sh <source-commit>' >&2; exit 64; }
|
||||
source_commit=$1
|
||||
readonly instance_id=f3d4b730-7f02-452f-975b-7091a4800431
|
||||
readonly linux_entry=gnulinux-simple-9e4550a0-452b-4f28-b5a5-d5364aa450f6
|
||||
readonly master_entry=guanghu-jd-master-20260816
|
||||
readonly receipt_root=/guanghu/recovery/JD-FD-PRIMARY-master-20260816
|
||||
readonly subcontrol=/usr/local/sbin/guanghu-linux-subcontrol
|
||||
|
||||
[[ $(tr A-F a-f </sys/class/dmi/id/product_uuid | tr -d '\r\n') == "$instance_id" ]]
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
state = json.load(open('/run/guanghu/master/state.json'))
|
||||
assert state['control'] == 'GUANGHU_OS_MASTER'
|
||||
assert state['pid1'] == 'GUANGHU_SUPERVISOR'
|
||||
assert state['full_linux_userspace'] == 'DORMANT'
|
||||
assert state['result'] == 'PASS_100'
|
||||
PY
|
||||
[[ $(tr '\0' ' ' </proc/1/cmdline) == *guanghu-master-init* ]]
|
||||
grep -Fq "'${master_entry}'" /boot/grub/grub.cfg
|
||||
grep -Fq "$linux_entry" /boot/grub/grub.cfg
|
||||
[[ $(curl -sS -o /dev/null -w '%{http_code}' --max-time 5 http://127.0.0.1:3340/api/healthz) == 200 ]]
|
||||
[[ $(curl -sS -o /dev/null -w '%{http_code}' --max-time 5 http://127.0.0.1:3922/v1/anchor) == 200 ]]
|
||||
|
||||
mkdir -p "$receipt_root/rollback"
|
||||
cp -a /etc/default/grub "$receipt_root/rollback/grub.default.before-final-cutover"
|
||||
python3 - <<PY
|
||||
from pathlib import Path
|
||||
path = Path('/etc/default/grub')
|
||||
text = path.read_text()
|
||||
lines = text.splitlines()
|
||||
matches = [index for index, line in enumerate(lines) if line.startswith('GRUB_DEFAULT=')]
|
||||
assert len(matches) == 1
|
||||
lines[matches[0]] = 'GRUB_DEFAULT=${master_entry}'
|
||||
temporary = path.with_name('grub.codex-guanghu-master.tmp')
|
||||
temporary.write_text('\n'.join(lines) + '\n')
|
||||
temporary.chmod(0o644)
|
||||
temporary.replace(path)
|
||||
PY
|
||||
|
||||
cat >"$subcontrol" <<'EOF'
|
||||
#!/bin/bash
|
||||
set -Eeuo pipefail
|
||||
readonly linux_entry=gnulinux-simple-9e4550a0-452b-4f28-b5a5-d5364aa450f6
|
||||
readonly master_entry=guanghu-jd-master-20260816
|
||||
readonly receipt_root=/guanghu/recovery/JD-FD-PRIMARY-master-20260816
|
||||
case ${1:-status} in
|
||||
status)
|
||||
printf 'pid1=%s\n' "$(tr '\0' ' ' </proc/1/cmdline)"
|
||||
grep '^GRUB_DEFAULT=' /etc/default/grub
|
||||
grub-editenv /boot/grub/grubenv list
|
||||
;;
|
||||
enter-once)
|
||||
[[ $(tr '\0' ' ' </proc/1/cmdline) == *guanghu-master-init* ]]
|
||||
grub-editenv /boot/grub/grubenv set next_entry="$linux_entry"
|
||||
printf '[hldp]\nschema=guanghu.linux-subcontrol-request/v1\nrequested_from=GUANGHU_OS_MASTER\nmode=ONE_TIME_LINUX_SUBCONTROL\nreturn_default=%s\nresult=ARMED\n' "$master_entry" >"$receipt_root/LINUX-SUBCONTROL-REQUEST.hldp"
|
||||
chmod 0600 "$receipt_root/LINUX-SUBCONTROL-REQUEST.hldp"
|
||||
sync
|
||||
systemctl --force --force reboot
|
||||
;;
|
||||
return-to-master)
|
||||
[[ $(tr '\0' ' ' </proc/1/cmdline) == *'/sbin/init'* || $(tr '\0' ' ' </proc/1/cmdline) == *systemd* ]]
|
||||
grub-editenv /boot/grub/grubenv unset next_entry
|
||||
sync
|
||||
systemctl reboot
|
||||
;;
|
||||
*) echo 'usage: guanghu-linux-subcontrol [status|enter-once|return-to-master]' >&2; exit 64 ;;
|
||||
esac
|
||||
EOF
|
||||
chmod 0755 "$subcontrol"
|
||||
|
||||
update-grub >/dev/null
|
||||
grub-editenv /boot/grub/grubenv unset next_entry
|
||||
grep -Eq "^GRUB_DEFAULT=${master_entry}$" /etc/default/grub
|
||||
grep -Fq "'${master_entry}'" /boot/grub/grub.cfg
|
||||
grep -Fq "$linux_entry" /boot/grub/grub.cfg
|
||||
"$subcontrol" status
|
||||
|
||||
cat >"$receipt_root/DEFAULT-CUTOVER-ARMED-RECEIPT.hldp" <<EOF
|
||||
[hldp]
|
||||
schema=guanghu.jd-master-default-cutover/v1
|
||||
node_id=JD-FD-PRIMARY
|
||||
instance_id=${instance_id}
|
||||
source_commit=${source_commit}
|
||||
master_default=${master_entry}
|
||||
linux_subcontrol=ONE_TIME_ON_DEMAND
|
||||
linux_rescue=${linux_entry}
|
||||
pre_cutover_physical_boot_id=$(cat /proc/sys/kernel/random/boot_id)
|
||||
pre_cutover_physical_state=PASS_100
|
||||
result=ARMED_FOR_DEFAULT_BOOT_PROOF
|
||||
EOF
|
||||
chmod 0600 "$receipt_root/DEFAULT-CUTOVER-ARMED-RECEIPT.hldp"
|
||||
sha256sum "$receipt_root/DEFAULT-CUTOVER-ARMED-RECEIPT.hldp" >"$receipt_root/DEFAULT-CUTOVER-ARMED-RECEIPT.hldp.sha256"
|
||||
sync
|
||||
echo GUANGHU_MASTER_DEFAULT_ARMED linux_subcontrol=ONE_TIME linux_rescue=PRESERVED
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
source_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
subject=${source_root}/scripts/set-jd-guanghu-master-default.sh
|
||||
bash -n "$subject"
|
||||
grep -Fq "state['control'] == 'GUANGHU_OS_MASTER'" "$subject"
|
||||
grep -Fq "state['full_linux_userspace'] == 'DORMANT'" "$subject"
|
||||
grep -Fq "lines[matches[0]] = 'GRUB_DEFAULT=\${master_entry}'" "$subject"
|
||||
grep -Fq 'enter-once)' "$subject"
|
||||
grep -Fq 'next_entry="$linux_entry"' "$subject"
|
||||
grep -Fq 'return_default=%s' "$subject"
|
||||
grep -Fq 'linux_rescue=${linux_entry}' "$subject"
|
||||
grep -Fq 'result=ARMED_FOR_DEFAULT_BOOT_PROOF' "$subject"
|
||||
echo GUANGHU_MASTER_DEFAULT_CUTOVER_CONTRACT_OK
|
||||
Loading…
Reference in a new issue