feat(guanghu-os): add JD resident master supervisor
This commit is contained in:
parent
f0549e6ef8
commit
44bd44aeec
4 changed files with 329 additions and 0 deletions
|
|
@ -0,0 +1,209 @@
|
|||
#!/bin/bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
# Guanghu OS resident supervisor for JD-FD-PRIMARY. The Linux kernel remains
|
||||
# the hardware-compatibility substrate; Ubuntu's init/systemd is not started.
|
||||
|
||||
readonly NODE_ID=JD-FD-PRIMARY
|
||||
readonly INSTANCE_ID=f3d4b730-7f02-452f-975b-7091a4800431
|
||||
readonly ROOT_UUID=9e4550a0-452b-4f28-b5a5-d5364aa450f6
|
||||
readonly LINUX_RESCUE_ENTRY=gnulinux-simple-9e4550a0-452b-4f28-b5a5-d5364aa450f6
|
||||
readonly RELEASE_ID=guanghu-master-20260816.1
|
||||
readonly STATE_ROOT=/run/guanghu/master
|
||||
readonly RECEIPT_ROOT=/guanghu/recovery/JD-FD-PRIMARY-master-20260816
|
||||
readonly HLCC=/opt/guanghu/architecture-releases/3d11ac75bea8cf08b5f223fed86ab3cd999ad2fd/server-tools/hololake-code-channel/jd-candidate/hlcc-bootstrap.py
|
||||
readonly APP_HUB=/opt/guanghu/architecture-releases/333cd222c53d7d162218543cd167bdda4f8efb22/server-tools/jd-app-hub/server.js
|
||||
readonly AI_DISCOVERY=/opt/guanghu/ai-discovery/server.js
|
||||
|
||||
declare -a CHILDREN=()
|
||||
RECOVERY_ARMED=0
|
||||
|
||||
log() {
|
||||
printf '%s %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$*" | tee -a "${STATE_ROOT}/supervisor.log"
|
||||
}
|
||||
|
||||
json_state() {
|
||||
local stage=$1 result=$2
|
||||
local tmp=${STATE_ROOT}/state.json.tmp.$$
|
||||
printf '%s\n' "{\"schema\":\"guanghu.master-runtime/v1\",\"node_id\":\"${NODE_ID}\",\"instance_id\":\"${INSTANCE_ID}\",\"release_id\":\"${RELEASE_ID}\",\"boot_id\":\"$(cat /proc/sys/kernel/random/boot_id)\",\"control\":\"GUANGHU_OS_MASTER\",\"pid1\":\"GUANGHU_SUPERVISOR\",\"linux_kernel_role\":\"HARDWARE_COMPATIBILITY_SUBSTRATE\",\"full_linux_userspace\":\"DORMANT\",\"linux_repository_bridge\":\"BOUNDED_SUBCONTROL\",\"linux_rescue\":\"${LINUX_RESCUE_ENTRY}\",\"stage\":\"${stage}\",\"result\":\"${result}\"}" >"${tmp}"
|
||||
chmod 0600 "${tmp}"
|
||||
mv "${tmp}" "${STATE_ROOT}/state.json"
|
||||
}
|
||||
|
||||
arm_linux_rescue() {
|
||||
(( RECOVERY_ARMED == 0 )) || return 0
|
||||
RECOVERY_ARMED=1
|
||||
/usr/bin/grub-editenv /boot/grub/grubenv set next_entry="${LINUX_RESCUE_ENTRY}" || true
|
||||
mkdir -p "${RECEIPT_ROOT}"
|
||||
cp "${STATE_ROOT}/state.json" "${RECEIPT_ROOT}/FAILED-BOOT-STATE.json" 2>/dev/null || true
|
||||
sync
|
||||
}
|
||||
|
||||
fatal() {
|
||||
local message=$1
|
||||
log "FAIL_0 ${message}"
|
||||
json_state FAILED "${message//\"/}"
|
||||
arm_linux_rescue
|
||||
/bin/systemctl --force --force reboot || /bin/bash -c 'echo b >/proc/sysrq-trigger'
|
||||
while :; do sleep 60; done
|
||||
}
|
||||
|
||||
require_file() {
|
||||
[[ -f $1 && ! -L $1 ]] || fatal "required_file_unavailable:$1"
|
||||
}
|
||||
|
||||
listen_ready() {
|
||||
local port=$1
|
||||
timeout 2 bash -c "</dev/tcp/127.0.0.1/${port}" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
wait_http() {
|
||||
local name=$1 url=$2 expected=${3:-200} attempts=${4:-90}
|
||||
local code
|
||||
for ((i=0; i<attempts; i++)); do
|
||||
code=$(/usr/bin/curl -sS -o /dev/null -w '%{http_code}' --max-time 2 "${url}" 2>/dev/null || true)
|
||||
[[ $code == "$expected" ]] && { log "READY ${name} http=${code}"; return 0; }
|
||||
sleep 1
|
||||
done
|
||||
fatal "service_not_ready:${name}:last_http_${code:-none}"
|
||||
}
|
||||
|
||||
start_root() {
|
||||
local name=$1; shift
|
||||
log "START ${name}"
|
||||
"$@" >>"${STATE_ROOT}/${name}.log" 2>&1 &
|
||||
CHILDREN+=("$!:$name")
|
||||
}
|
||||
|
||||
start_guanghu() {
|
||||
local name=$1; shift
|
||||
log "START ${name} owner=guanghu"
|
||||
/usr/bin/setpriv --reuid=998 --regid=998 --init-groups --inh-caps=-all --reset-env \
|
||||
/usr/bin/env HOME=/var/lib/guanghu USER=guanghu LOGNAME=guanghu \
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin "$@" \
|
||||
>>"${STATE_ROOT}/${name}.log" 2>&1 &
|
||||
CHILDREN+=("$!:$name")
|
||||
}
|
||||
|
||||
verify_identity() {
|
||||
local observed cmdline root_source
|
||||
observed=$(tr A-F a-f </sys/class/dmi/id/product_uuid | tr -d '\r\n')
|
||||
[[ $observed == "$INSTANCE_ID" ]] || fatal "instance_identity_mismatch"
|
||||
cmdline=$(</proc/cmdline)
|
||||
[[ " $cmdline " == *' guanghu.master=1 '* ]] || fatal "master_marker_missing"
|
||||
[[ " $cmdline " == *" root=UUID=${ROOT_UUID} "* ]] || fatal "root_binding_missing"
|
||||
root_source=$(findmnt -n -o SOURCE /)
|
||||
[[ $root_source == /dev/vda1 || $root_source == UUID="$ROOT_UUID" ]] || fatal "root_device_mismatch:${root_source}"
|
||||
grep -Fq "$LINUX_RESCUE_ENTRY" /boot/grub/grub.cfg || fatal "linux_rescue_missing"
|
||||
[[ $$ -eq 1 ]] || fatal "supervisor_is_not_pid1"
|
||||
}
|
||||
|
||||
prepare_runtime() {
|
||||
mount -o remount,rw /
|
||||
mkdir -p "$STATE_ROOT" "$RECEIPT_ROOT" /run/sshd /run/systemd/resolve
|
||||
chmod 0700 "$STATE_ROOT" "$RECEIPT_ROOT"
|
||||
chmod 1777 /tmp
|
||||
mountpoint -q /proc || mount -t proc proc /proc
|
||||
mountpoint -q /sys || mount -t sysfs sysfs /sys
|
||||
mountpoint -q /run || mount -t tmpfs -o mode=0755,nosuid,nodev tmpfs /run
|
||||
printf 'nameserver 183.60.83.19\nnameserver 223.5.5.5\noptions timeout:2 attempts:2\n' >/run/systemd/resolve/stub-resolv.conf
|
||||
hostname jd-fd-primary
|
||||
/usr/sbin/ip link set lo up
|
||||
/usr/sbin/ip link set eth0 up
|
||||
/usr/sbin/ip addr flush dev eth0
|
||||
/usr/sbin/ip addr add 172.16.0.6/16 dev eth0
|
||||
/usr/sbin/ip route replace default via 172.16.0.1 dev eth0
|
||||
}
|
||||
|
||||
start_bridge() {
|
||||
require_file "$HLCC"
|
||||
require_file "$APP_HUB"
|
||||
require_file "$AI_DISCOVERY"
|
||||
|
||||
start_root sshd /usr/sbin/sshd -D -e \
|
||||
-o UsePAM=no -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no \
|
||||
-o PermitRootLogin=prohibit-password -o AllowTcpForwarding=yes \
|
||||
-o GatewayPorts=no -o X11Forwarding=no -o PrintMotd=no
|
||||
sleep 1
|
||||
listen_ready 22 || fatal "sshd_not_listening"
|
||||
|
||||
start_guanghu repository-bridge /usr/bin/python3 "$HLCC"
|
||||
wait_http repository-bridge http://127.0.0.1:3341/health 200 120
|
||||
wait_http repository-service http://127.0.0.1:3340/api/healthz 200 30
|
||||
|
||||
start_guanghu app-hub /usr/bin/env NODE_ENV=production HUB_HOST=127.0.0.1 \
|
||||
HUB_PORT=8088 GUANGHU_NODE_ID="$NODE_ID" CODE_CHANNEL_HOST=127.0.0.1 \
|
||||
CODE_CHANNEL_PORT=3340 CODE_RATE_LIMIT_MAX=600 CODE_BROWSE_RATE_LIMIT_MAX=120 \
|
||||
/usr/bin/node "$APP_HUB"
|
||||
wait_http app-hub http://127.0.0.1:8088/api/status 200 30
|
||||
wait_http code-projection http://127.0.0.1:8088/code/ 303 30
|
||||
|
||||
start_guanghu navigation-bridge /usr/bin/env GUANGHU_AI_HOST=127.0.0.1 \
|
||||
GUANGHU_AI_PORT=3922 GUANGHU_REPOSITORY_MAP=/opt/guanghu/ai-discovery/repository-route-map.json \
|
||||
GUANGHU_NODE_MAP=/opt/guanghu/ai-discovery/server-node-map.json \
|
||||
GUANGHU_SUBJECT_REGISTRY=/opt/guanghu/ai-discovery/fifth-domain-subject-registry.json \
|
||||
GUANGHU_SUBJECT_ALIAS_MAP=/opt/guanghu/ai-discovery/subject-id-alias-map.json \
|
||||
GUANGHU_NAVIGATION_MAP=/opt/guanghu/ai-discovery/ai-machine-navigation-map.json \
|
||||
GUANGHU_NAVIGATION_ANCHOR=/opt/guanghu/ai-discovery/public-navigation-anchor.json \
|
||||
GUANGHU_LIGHTHOUSE_PATHS=/opt/guanghu/ai-discovery/lighthouse-path-registry.json \
|
||||
GUANGHU_HOST_SKILLS=/opt/guanghu/ai-discovery/host-skill-navigation-map.json \
|
||||
GUANGHU_IDENTITY_AUTHORITY=/opt/guanghu/ai-discovery/guanghu-identity-authority-map.json \
|
||||
GUANGHU_TCS_MOTHER_BRAIN=/opt/guanghu/ai-discovery/tcs-mother-brain-runtime-map.json \
|
||||
GUANGHU_REPOSITORY_GIT_DIR=/var/lib/guanghu/personas/guanghu/hlcc-v16.0.1/data/repositories/bingshuo/guanghu-ice-heart.git \
|
||||
/usr/bin/node "$AI_DISCOVERY"
|
||||
wait_http navigation-bridge http://127.0.0.1:3922/v1/anchor 200 30
|
||||
}
|
||||
|
||||
runtime_watch() {
|
||||
json_state READY PASS_100
|
||||
cp "$STATE_ROOT/state.json" "$RECEIPT_ROOT/CURRENT-PHYSICAL-STATE.json"
|
||||
sha256sum "$RECEIPT_ROOT/CURRENT-PHYSICAL-STATE.json" >"$RECEIPT_ROOT/CURRENT-PHYSICAL-STATE.json.sha256"
|
||||
log 'GUANGHU_OS_MASTER_READY linux_userspace=DORMANT repository_bridge=READY linux_rescue=PRESERVED'
|
||||
sync
|
||||
while :; do
|
||||
sleep 10
|
||||
for item in "${CHILDREN[@]}"; do
|
||||
pid=${item%%:*}; name=${item#*:}
|
||||
kill -0 "$pid" 2>/dev/null || fatal "runtime_process_exited:${name}"
|
||||
done
|
||||
listen_ready 22 || fatal "runtime_sshd_lost"
|
||||
listen_ready 3340 || fatal "runtime_repository_lost"
|
||||
listen_ready 8088 || fatal "runtime_projection_lost"
|
||||
listen_ready 3922 || fatal "runtime_navigation_lost"
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
mkdir -p "$STATE_ROOT"
|
||||
json_state STARTING PENDING
|
||||
verify_identity
|
||||
prepare_runtime
|
||||
json_state STARTING_IDENTITY_VERIFIED PENDING
|
||||
start_bridge
|
||||
runtime_watch
|
||||
}
|
||||
|
||||
preflight() {
|
||||
[[ $(tr A-F a-f </sys/class/dmi/id/product_uuid | tr -d '\r\n') == "$INSTANCE_ID" ]]
|
||||
[[ $(findmnt -n -o SOURCE /) == /dev/vda1 ]]
|
||||
grep -Fq "$LINUX_RESCUE_ENTRY" /boot/grub/grub.cfg
|
||||
getent passwd guanghu | grep -q '^guanghu:x:998:998:'
|
||||
for path in "$HLCC" "$APP_HUB" "$AI_DISCOVERY" /usr/sbin/sshd \
|
||||
/usr/bin/node /usr/bin/python3 /usr/bin/setpriv /usr/bin/grub-editenv; do
|
||||
[[ -e $path && ! -L $path || $path == /usr/bin/python3 ]]
|
||||
done
|
||||
printf 'GUANGHU_MASTER_PREFLIGHT_OK node=%s release=%s linux_rescue=%s\n' \
|
||||
"$NODE_ID" "$RELEASE_ID" "$LINUX_RESCUE_ENTRY"
|
||||
}
|
||||
|
||||
case ${1:-run} in
|
||||
preflight) preflight ;;
|
||||
run)
|
||||
if [[ $$ -ne 1 ]]; then
|
||||
echo 'GUANGHU_MASTER_REFUSED: run mode requires PID 1' >&2
|
||||
exit 1
|
||||
fi
|
||||
main
|
||||
;;
|
||||
*) echo 'usage: guanghu-master-init.sh [run|preflight]' >&2; exit 64 ;;
|
||||
esac
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
[[ $# == 2 ]] || { echo 'usage: install-jd-guanghu-master-candidate.sh <supervisor-source> <source-commit>' >&2; exit 64; }
|
||||
|
||||
source_file=$(readlink -f "$1")
|
||||
source_commit=$2
|
||||
readonly node_id=JD-FD-PRIMARY
|
||||
readonly instance_id=f3d4b730-7f02-452f-975b-7091a4800431
|
||||
readonly root_uuid=9e4550a0-452b-4f28-b5a5-d5364aa450f6
|
||||
readonly linux_entry=gnulinux-simple-9e4550a0-452b-4f28-b5a5-d5364aa450f6
|
||||
readonly master_entry=guanghu-jd-master-20260816
|
||||
readonly install_path=/usr/local/libexec/guanghu/guanghu-master-init
|
||||
readonly grub_source=/etc/grub.d/42_guanghu_master
|
||||
readonly receipt_root=/guanghu/recovery/JD-FD-PRIMARY-master-20260816
|
||||
|
||||
[[ $source_commit =~ ^[0-9a-f]{40}$ ]]
|
||||
[[ -f $source_file && ! -L $source_file ]]
|
||||
bash -n "$source_file"
|
||||
[[ $(tr A-F a-f </sys/class/dmi/id/product_uuid | tr -d '\r\n') == "$instance_id" ]]
|
||||
[[ $(findmnt -n -o SOURCE /) == /dev/vda1 ]]
|
||||
[[ $(grub-probe --target=fs_uuid /) == "$root_uuid" ]]
|
||||
grep -Fq "$linux_entry" /boot/grub/grub.cfg
|
||||
grep -Eq "^GRUB_DEFAULT=${linux_entry}$" /etc/default/grub
|
||||
[[ -f /boot/vmlinuz-5.15.0-60-generic && -f /boot/initrd.img-5.15.0-60-generic ]]
|
||||
|
||||
mkdir -p "$(dirname "$install_path")" "$receipt_root/rollback"
|
||||
chmod 0700 "$receipt_root" "$receipt_root/rollback"
|
||||
cp -a /etc/default/grub "$receipt_root/rollback/grub.default.before"
|
||||
[[ ! -e $grub_source ]] || cp -a "$grub_source" "$receipt_root/rollback/42_guanghu_master.before"
|
||||
install -o root -g root -m 0755 "$source_file" "$install_path"
|
||||
|
||||
cat >"$grub_source" <<EOF
|
||||
#!/bin/sh
|
||||
exec tail -n +3 \$0
|
||||
menuentry 'Guanghu OS master · JD repository bridge' --class guanghu --class os --id '${master_entry}' {
|
||||
recordfail
|
||||
insmod gzio
|
||||
insmod part_msdos
|
||||
insmod ext2
|
||||
search --no-floppy --fs-uuid --set=root ${root_uuid}
|
||||
linux /boot/vmlinuz-5.15.0-60-generic root=UUID=${root_uuid} ro net.ifnames=0 biosdevname=0 selinux=0 console=tty0 console=ttyS0,115200n8 guanghu.master=1 init=${install_path} panic=10
|
||||
initrd /boot/initrd.img-5.15.0-60-generic
|
||||
}
|
||||
EOF
|
||||
chmod 0755 "$grub_source"
|
||||
update-grub >/dev/null
|
||||
|
||||
grep -Fq "'${master_entry}'" /boot/grub/grub.cfg
|
||||
grep -Fq "guanghu.master=1 init=${install_path}" /boot/grub/grub.cfg
|
||||
grep -Eq "^GRUB_DEFAULT=${linux_entry}$" /etc/default/grub
|
||||
"$install_path" preflight
|
||||
|
||||
installed_sha=$(sha256sum "$install_path" | awk '{print $1}')
|
||||
source_sha=$(sha256sum "$source_file" | awk '{print $1}')
|
||||
[[ $installed_sha == "$source_sha" ]]
|
||||
boot_id=$(cat /proc/sys/kernel/random/boot_id)
|
||||
cat >"$receipt_root/CANDIDATE-INSTALL-RECEIPT.hldp" <<EOF
|
||||
[hldp]
|
||||
schema=guanghu.jd-master-candidate-install/v1
|
||||
node_id=${node_id}
|
||||
instance_id=${instance_id}
|
||||
source_commit=${source_commit}
|
||||
source_sha256=${source_sha}
|
||||
installed_sha256=${installed_sha}
|
||||
master_entry=${master_entry}
|
||||
unattended_default=${linux_entry}
|
||||
boot_id=${boot_id}
|
||||
control_candidate=GUANGHU_OS_MASTER
|
||||
linux_kernel_role=HARDWARE_COMPATIBILITY_SUBSTRATE
|
||||
full_linux_userspace=DORMANT_IN_CANDIDATE
|
||||
linux_repository_bridge=BOUNDED_SUBCONTROL
|
||||
linux_rescue=PRESERVED
|
||||
result=PASS_100
|
||||
EOF
|
||||
chmod 0600 "$receipt_root/CANDIDATE-INSTALL-RECEIPT.hldp"
|
||||
sha256sum "$receipt_root/CANDIDATE-INSTALL-RECEIPT.hldp" >"$receipt_root/CANDIDATE-INSTALL-RECEIPT.hldp.sha256"
|
||||
sync
|
||||
printf 'GUANGHU_MASTER_CANDIDATE_INSTALLED entry=%s sha256=%s default=%s\n' "$master_entry" "$installed_sha" "$linux_entry"
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
source_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
subject=${source_root}/scripts/guanghu-master-init.sh
|
||||
|
||||
bash -n "$subject"
|
||||
grep -Fq 'readonly NODE_ID=JD-FD-PRIMARY' "$subject"
|
||||
grep -Fq 'readonly INSTANCE_ID=f3d4b730-7f02-452f-975b-7091a4800431' "$subject"
|
||||
grep -Fq '[[ $$ -eq 1 ]]' "$subject"
|
||||
grep -Fq "if [[ \$\$ -ne 1 ]]" "$subject"
|
||||
grep -Fq "GUANGHU_MASTER_REFUSED: run mode requires PID 1" "$subject"
|
||||
grep -Fq '\"control\":\"GUANGHU_OS_MASTER\"' "$subject"
|
||||
grep -Fq '\"full_linux_userspace\":\"DORMANT\"' "$subject"
|
||||
grep -Fq '/usr/bin/grub-editenv /boot/grub/grubenv set next_entry=' "$subject"
|
||||
grep -Fq 'start_root sshd /usr/sbin/sshd -D -e' "$subject"
|
||||
grep -Fq 'mount -o remount,rw /' "$subject"
|
||||
grep -Fq 'start_guanghu repository-bridge' "$subject"
|
||||
grep -Fq 'start_guanghu app-hub' "$subject"
|
||||
grep -Fq 'start_guanghu navigation-bridge' "$subject"
|
||||
grep -Fq 'wait_http code-projection http://127.0.0.1:8088/code/ 303' "$subject"
|
||||
grep -Fq 'wait_http navigation-bridge http://127.0.0.1:3922/v1/anchor 200' "$subject"
|
||||
if grep -Eq '(^|[[:space:]])(systemd|/sbin/init)([[:space:]]|$)' "$subject"; then
|
||||
echo 'full Linux init must remain dormant' >&2
|
||||
exit 1
|
||||
fi
|
||||
echo GUANGHU_MASTER_INIT_CONTRACT_OK
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
source_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
subject=${source_root}/scripts/install-jd-guanghu-master-candidate.sh
|
||||
bash -n "$subject"
|
||||
grep -Fq 'readonly node_id=JD-FD-PRIMARY' "$subject"
|
||||
grep -Fq 'grep -Eq "^GRUB_DEFAULT=${linux_entry}$" /etc/default/grub' "$subject"
|
||||
grep -Fq "menuentry 'Guanghu OS master · JD repository bridge'" "$subject"
|
||||
grep -Fq 'guanghu.master=1 init=${install_path} panic=10' "$subject"
|
||||
grep -Fq 'unattended_default=${linux_entry}' "$subject"
|
||||
grep -Fq 'linux_rescue=PRESERVED' "$subject"
|
||||
grep -Fq '"$install_path" preflight' "$subject"
|
||||
echo GUANGHU_MASTER_CANDIDATE_INSTALL_CONTRACT_OK
|
||||
Loading…
Reference in a new issue