diff --git a/deploy/linux/sbin/bj-igate-admin b/deploy/linux/sbin/bj-igate-admin index 945010e..cb82816 100755 --- a/deploy/linux/sbin/bj-igate-admin +++ b/deploy/linux/sbin/bj-igate-admin @@ -86,7 +86,9 @@ case "$cmd" in 'deponent',(select value from parameters p where p.chanel_id=c.id and p.name='repositoryCode'), 'dir',(select value from parameters p where p.chanel_id=c.id and p.name='dir')) order by c.id),'[]') from channels c" 2>/dev/null || echo "[]") fi - echo "{\"ok\":true,\"installed\":$inst,\"version\":$(q "$(igate_version)"),\"service\":$(q "$svc"),\"engine\":$(q "$st"),\"channels\":${chans:-[]}}" ;; + rb=""; BK=$(cat /var/backups/ish-last-backup.txt 2>/dev/null) + [ -n "$BK" ] && [ -s "$BK/version" ] && [ -s "$BK/opt-nsd-igate.tar.gz" ] && [ -s "$BK/igate-db.dump" ] && [ -s "$BK/var-lib-igate.tar.gz" ] && rb=$(cat "$BK/version") + echo "{\"ok\":true,\"installed\":$inst,\"version\":$(q "$(igate_version)"),\"service\":$(q "$svc"),\"engine\":$(q "$st"),\"rollback\":$(q "$rb"),\"channels\":${chans:-[]}}" ;; install) if pgrep -f "bj-igate-admin install-now" >/dev/null; then @@ -173,7 +175,11 @@ PY BK=/var/backups/ish-$(date +%Y%m%d-%H%M%S); mkdir -p "$BK" tar czf "$BK/opt-nsd-igate.tar.gz" -C "$(dirname "$IGATE_DIR")" "$(basename "$IGATE_DIR")" 2>/dev/null runuser -u postgres -- pg_dump -Fc "$DB" > "$BK/igate-db.dump" 2>/dev/null - echo "$BK" > /var/backups/ish-last-backup.txt; echo "резервная копия прежнего ИШ: $BK" + # для отката: данные ИШ (без флешки с ключом и кэша), юнит, обёртка запуска, версия + tar czf "$BK/var-lib-igate.tar.gz" --exclude="${HOME_DIR#/}/keymedia" --exclude="${HOME_DIR#/}/.cache" -C / "${HOME_DIR#/}" 2>/dev/null + cp -a "$UNIT" "$BK/" 2>/dev/null; cp -a "$UNIT.d" "$BK/" 2>/dev/null; cp -a "$WRAPPER" "$BK/" 2>/dev/null + igate_version > "$BK/version" + echo "$BK" > /var/backups/ish-last-backup.txt; echo "резервная копия прежнего ИШ $(cat "$BK/version"): $BK" fi echo "igate igate/service boolean false" | debconf-set-selections echo "igate igate/shortcut boolean false" | debconf-set-selections @@ -253,6 +259,49 @@ SQL case "$(j file)" in /var/lib/bj/igate-upload/*) rm -f "$(j file)" ;; esac # загруженный архив больше не нужен (с образа — остаётся) st done "ИШ $(igate_version) установлен и работает; дальше — канал контура (TEST3 или боевой)" ;; + rollback) + pgrep -f "bj-igate-admin (install|rollback)-now" >/dev/null && err "установка или откат ИШ уже идёт" + BK=$(cat /var/backups/ish-last-backup.txt 2>/dev/null) + [ -n "$BK" ] && [ -s "$BK/version" ] && [ -s "$BK/var-lib-igate.tar.gz" ] || err "нет полной резервной копии прежнего ИШ — откатить нельзя" + echo '{"stage":"queued","msg":"откат запущен"}' > "$STATUS"; chown bj:bj "$STATUS" 2>/dev/null + systemd-run --unit="bj-igate-rollback-$(date +%s)" --collect -p RuntimeMaxSec=1800 /usr/local/sbin/bj-igate-admin rollback-now >/dev/null 2>&1 || err "не удалось запустить откат" + ok "откат ИШ к $(cat "$BK/version") запущен" ;; + + rollback-now) + LOG=/var/log/bj-igate-install.log; : > "$LOG" + st() { python3 - "$STATUS" "$1" "$2" "$LOG" <<'PY' +import json,sys,datetime +tail=open(sys.argv[4],errors='replace').read()[-1500:] +json.dump({"at":datetime.datetime.now().astimezone().isoformat(timespec="seconds"),"stage":sys.argv[2],"msg":sys.argv[3],"log":tail},open(sys.argv[1],"w"),ensure_ascii=False) +PY + chown bj:bj "$STATUS" 2>/dev/null; echo "== $2" >> "$LOG"; } + die() { st error "$1"; exit 1; } + exec >>"$LOG" 2>&1 + BK=$(cat /var/backups/ish-last-backup.txt 2>/dev/null); old=$(cat "$BK/version" 2>/dev/null); cur=$(igate_version) + [ -n "$old" ] || die "нет резервной копии прежнего ИШ" + st stop "остановка ИШ $cur" + systemctl stop igate >/dev/null 2>&1 || true + pkill -9 -u "$SVC_USER" -f igate-svc 2>/dev/null; pkill -9 -u "$SVC_USER" -f Xvfb 2>/dev/null; rm -f /tmp/CoreFxPipe_NSD.IGate.* + st files "возврат программы и данных ИШ $old" + rm -rf "$IGATE_DIR" && tar xzf "$BK/opt-nsd-igate.tar.gz" -C "$(dirname "$IGATE_DIR")" || die "не распаковалась программа ИШ из $BK" + find "$HOME_DIR" -mindepth 1 -maxdepth 1 ! -name keymedia ! -name .cache -exec rm -rf {} + 2>/dev/null + tar xzf "$BK/var-lib-igate.tar.gz" -C / || die "не распаковались данные ИШ из $BK" + [ -f "$BK/$(basename "$UNIT")" ] && cp -a "$BK/$(basename "$UNIT")" "$UNIT" + [ -d "$BK/$(basename "$UNIT").d" ] && { rm -rf "$UNIT.d"; cp -a "$BK/$(basename "$UNIT").d" "$UNIT.d"; } + [ -f "$BK/$(basename "$WRAPPER")" ] && cp -a "$BK/$(basename "$WRAPPER")" "$WRAPPER" + st db "возврат базы ИШ" + runuser -u postgres -- dropdb --if-exists "$DB" && runuser -u postgres -- createdb -O "$SVC_USER" "$DB" || die "не пересоздана база ИШ" + runuser -u postgres -- pg_restore -d "$DB" "$BK/igate-db.dump" || true + psqlq -c "select to_regclass('public.parameters') is not null" | grep -q t || die "база ИШ не восстановилась из $BK/igate-db.dump" + # пришедший с обновлением дистрибутив больше не ставить сам (иначе bj вернёт версию сразу); новая версия — снова автоматически + dv=$(python3 -c "import json;print(json.load(open('/var/lib/bj/.bj/components.json')).get('igate-dist',{}).get('version',''))" 2>/dev/null) + [ -n "$dv" ] && { printf '%s +' "$dv" > /var/lib/bj/igate-autoupgrade-skip; chown bj:bj /var/lib/bj/igate-autoupgrade-skip 2>/dev/null; } + st start "запуск ИШ $old" + systemctl daemon-reload; systemctl restart igate || die "служба igate не запустилась" + wait_engine 120 || die "ИШ $old запущен, но движок не перешёл в Running за 2 минуты. Журнал ИШ: $DATA_DIR/logs-svc/log.txt" + st done "ИШ откатан с $cur к $old и работает" ;; + contour) contour=$(j contour); crypto=$(j crypto); dep=$(j deponent); prof=$(j profile) crypto=${crypto:-gost} diff --git a/deploy/linux/sbin/bj-keymedia-worker b/deploy/linux/sbin/bj-keymedia-worker index 337eed1..6d07c76 100755 --- a/deploy/linux/sbin/bj-keymedia-worker +++ b/deploy/linux/sbin/bj-keymedia-worker @@ -12,7 +12,7 @@ process_one(){ quikexport-*) out=$(BJ_EXTRA="$extra" /usr/local/sbin/bj-quikexport-admin "${action#quikexport-}" "$staging" 2>&1) ;; component-install) out=$(/usr/local/sbin/bj-component-install "$staging" 2>&1) ;; # интеграционный шлюз НРД: состояние, установка, канал контура (TEST3 | боевой); параметры — JSON в extra - igate-status|igate-install|igate-contour|igate-share) out=$(BJ_EXTRA="$extra" /usr/local/sbin/bj-igate-admin "${action#igate-}" 2>&1) ;; + igate-status|igate-install|igate-contour|igate-share|igate-rollback) out=$(BJ_EXTRA="$extra" /usr/local/sbin/bj-igate-admin "${action#igate-}" 2>&1) ;; # датчик случайных чисел Валидаты: проверка и сеанс «двигайте мышью» (движения — из мастера bj) rng-status|rng-start|rng-cancel) out=$(/usr/local/sbin/bj-validata-rng "${action#rng-}" 2>&1) ;; # системные настройки сервера: серверы времени (NTP) diff --git a/deploy/release/component-versions.json b/deploy/release/component-versions.json index f519e2f..39252a6 100644 --- a/deploy/release/component-versions.json +++ b/deploy/release/component-versions.json @@ -20,8 +20,8 @@ "version": "2026.10.21.6" }, "bj-server": { - "fingerprint": "98167dc3f6c196784867f7eb88e091c693b160277f09735971e44e2c18f21a61", - "version": "2026.10.21.15" + "fingerprint": "5617c24adb2d2392aecdfe6711bff54e8936688c249408c22042174511f258ba", + "version": "2026.10.21.16" }, "crypto-service.jar": { "fingerprint": "2c4fd536bc9b1c20c69a70e8dcd374a61847b263aeb2e474c45debb01fbd8233", diff --git a/deploy/release/igate-approved b/deploy/release/igate-approved index 0f09558..ffdff61 100644 --- a/deploy/release/igate-approved +++ b/deploy/release/igate-approved @@ -1 +1 @@ -107.0.930 996bcf9f8f0001dc0e73b9582a5ebc0fa05bda264bc8e8b1785d069ed07f13c3 +110.0.997 430934886e1ce1b10edba285615a0e65551514a6229f8439446344f9a6278b78 diff --git a/internal/lkgateway/igate.go b/internal/lkgateway/igate.go index 1637934..38c2f3f 100644 --- a/internal/lkgateway/igate.go +++ b/internal/lkgateway/igate.go @@ -215,6 +215,16 @@ func registerIgateAdmin(mux *http.ServeMux, rc *RuntimeConfig) { defer cancel() jsonOut(w, opResult(runKeymediaOp(ctx, "igate-install", map[string]string{"extra": string(extra)}))) }) + // откат ИШ к версии из последней резервной копии (её делает каждая установка/обновление) + mux.HandleFunc("/admin/setup/igate/rollback", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "method", http.StatusMethodNotAllowed) + return + } + ctx, cancel := context.WithTimeout(r.Context(), time.Minute) + defer cancel() + jsonOut(w, opResult(runKeymediaOp(ctx, "igate-rollback", nil))) + }) // ход установки: этап, сообщение, журнал и сколько секунд идёт текущий этап (по времени записи файла) mux.HandleFunc("/admin/setup/igate/install-status", func(w http.ResponseWriter, r *http.Request) { raw, err := os.ReadFile(igateInstallStatusPath) @@ -461,12 +471,19 @@ func igateInstallDist(ctx context.Context) error { // igateAutoUpgrade — ИШ на сервере старее дистрибутива, пришедшего с обновлением bj: обновить (настройки, // каналы и база ИШ сохраняются; прежняя версия копируется в /var/backups). Вызывается после обновления bj // и при запуске bj-server (обновление ядра перезапускает его до того, как успел бы сработать первый вызов). +// igateAutoUpgradeSkipPath — версия дистрибутива, с которой ИШ откатили (её автоматически не ставим). +var igateAutoUpgradeSkipPath = "/var/lib/bj/igate-autoupgrade-skip" + func igateAutoUpgrade(ctx context.Context, rc *RuntimeConfig) { cur := ishInstalledVersion() _, dist := igateDistFile() if !igateInstalled() || cur == "" || dist == "" || !release.IsNewer(dist, cur) || igateInstallStatus().Busy { return } + // ИШ откатили с этой версии вручную — сам не ставим, пока не придёт следующая + if b, err := os.ReadFile(igateAutoUpgradeSkipPath); err == nil && strings.TrimSpace(string(b)) == dist { + return + } log.Printf("lk-gateway: ИШ %s старее проверенного дистрибутива %s — обновляю", cur, dist) if err := igateInstallDist(ctx); err != nil { raiseSystemAlert(rc, "ИШ не обновлён до "+dist, "Пришёл дистрибутив ИШ "+dist+", но обновление не запустилось: "+err.Error()+". Повторить — мастер, шаг «Шлюз НРД».") diff --git a/internal/lkgateway/web/templates/part_igate.html b/internal/lkgateway/web/templates/part_igate.html index b553dff..051d457 100644 --- a/internal/lkgateway/web/templates/part_igate.html +++ b/internal/lkgateway/web/templates/part_igate.html @@ -52,6 +52,7 @@
Версию ИШ проверяет ZETIT; новые приходят с обновлением bj.
+