ИШ обновляется через сервер лицензий вместе с bj; наглядный ход установки ИШ
- Дистрибутив ИШ — компонент выпуска igate-dist (версия = версия ИШ). В выпуск попадает только одобренный архив: deploy/release/igate-approved (версия и sha256), сборка сверяет контрольную сумму. Клиент получает его обновлением; bj-server после обновления (и при запуске) сам обновляет ИШ, если на сервере он старее; итог — событие в «Новостях». Настройки, каналы и база ИШ сохраняются, прежняя версия — в /var/backups. - Установка «с сервера» берёт самый новый проверенный дистрибутив: с образа или из обновления. С сайта НРД — только в режиме разработки. - Большие файлы: одна прежняя копия вместо пяти; предел скачивания — по размеру. - Ход установки ИШ — этапами: пройденные, текущий («идёт 0:41 · обычно до 1:30», дольше обычного — предупреждение), журнал под раскрытием; кнопка на время установки выключена. - Установщик: уникальные этапы; igate-cli и сессия ключницы с принудительным завершением (timeout -k); зависшая установка (ход не менялся 15 минут) снимается повторным запуском; служба установки — не дольше 40 минут. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
+81
-13
@@ -5,6 +5,8 @@ package lkgateway
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
@@ -153,13 +155,14 @@ func registerIgateAdmin(mux *http.ServeMux, rc *RuntimeConfig) {
|
||||
return
|
||||
}
|
||||
params["file"] = dst
|
||||
} else if r.FormValue("bundled") == "1" {
|
||||
if igateBundledVersion() == "" {
|
||||
jsonOut(w, map[string]any{"ok": false, "error": "в образе нет дистрибутива ИШ — скачайте с сайта НРД или загрузите файл"})
|
||||
} else if r.FormValue("bundled") == "1" { // проверенный дистрибутив на сервере (образ или обновление bj)
|
||||
file, _ := igateDistFile()
|
||||
if file == "" {
|
||||
jsonOut(w, map[string]any{"ok": false, "error": "дистрибутива ИШ на сервере нет — он приходит с обновлением bj"})
|
||||
return
|
||||
}
|
||||
params["bundled"] = "1"
|
||||
} else if v := strings.TrimSpace(r.FormValue("version")); igateVersionRe.MatchString(v) {
|
||||
params["file"] = file
|
||||
} else if v := strings.TrimSpace(r.FormValue("version")); igateVersionRe.MatchString(v) && devMode(rc) { // с сайта НРД — только разработчикам
|
||||
params["version"] = v
|
||||
} else {
|
||||
jsonOut(w, map[string]any{"ok": false, "error": "загрузите архив ИШ или укажите версию вида 107.0.930"})
|
||||
@@ -170,15 +173,22 @@ 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/install-status", func(w http.ResponseWriter, r *http.Request) {
|
||||
raw, err := os.ReadFile("/var/lib/bj/igate-install-status.json")
|
||||
if err != nil {
|
||||
raw, err := os.ReadFile(igateInstallStatusPath)
|
||||
out := map[string]any{}
|
||||
if err != nil || json.Unmarshal(raw, &out) != nil {
|
||||
jsonOut(w, map[string]any{})
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
_, _ = w.Write(raw)
|
||||
if fi, err := os.Stat(igateInstallStatusPath); err == nil {
|
||||
out["elapsed"] = int(time.Since(fi.ModTime()).Seconds())
|
||||
}
|
||||
st := igateInstallStatus()
|
||||
if st.Stage == "error" && out["stage"] != "error" { // молчит 20 минут — прервалась
|
||||
out["stage"], out["msg"] = "error", st.Msg
|
||||
}
|
||||
jsonOut(w, out)
|
||||
})
|
||||
// канал контура в ИШ (адрес, отпечаток УЦ, папка обмена); ключ — мастером установки ключа
|
||||
mux.HandleFunc("/admin/setup/igate/contour", func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -361,13 +371,71 @@ func igateInstallStatus() igateInstallState {
|
||||
}
|
||||
|
||||
func igateBundledVersion() string {
|
||||
_, v := igateDistFile()
|
||||
return v
|
||||
}
|
||||
|
||||
// igateDistFile — самый новый дистрибутив ИШ на сервере (файл и версия): с образа (igate-<версия>-amd64.zip)
|
||||
// или из обновления bj (компонент igate-dist, версия — в списке установленных компонентов). Это версии,
|
||||
// проверенные ZETIT; другой ИШ клиенту не ставится.
|
||||
func igateDistFile() (string, string) {
|
||||
best, file := "", ""
|
||||
m, _ := filepath.Glob("/var/lib/bj/igate-dist/igate-*-amd64.zip")
|
||||
best := ""
|
||||
for _, f := range m {
|
||||
v := strings.ReplaceAll(strings.TrimSuffix(strings.TrimPrefix(filepath.Base(f), "igate-"), "-amd64.zip"), "-", ".")
|
||||
if igateVersionRe.MatchString(v) && (best == "" || release.IsNewer(v, best)) {
|
||||
best = v
|
||||
best, file = v, f
|
||||
}
|
||||
}
|
||||
if c, ok := release.ComponentByName("igate-dist"); ok {
|
||||
if inst, ok := release.LoadInstalled(release.InstalledFile)[c.Name]; ok && igateVersionRe.MatchString(inst.Version) {
|
||||
if _, err := os.Stat(c.Path); err == nil && (best == "" || release.IsNewer(inst.Version, best)) {
|
||||
best, file = inst.Version, c.Path
|
||||
}
|
||||
}
|
||||
}
|
||||
return file, best
|
||||
}
|
||||
|
||||
// igateInstallDist — поставить (или обновить) ИШ из самого нового дистрибутива на сервере.
|
||||
func igateInstallDist(ctx context.Context) error {
|
||||
file, _ := igateDistFile()
|
||||
if file == "" {
|
||||
return errors.New("дистрибутива ИШ на сервере нет — он приходит с обновлением bj")
|
||||
}
|
||||
extra, _ := json.Marshal(map[string]string{"file": file})
|
||||
res, err := runKeymediaOp(ctx, "igate-install", map[string]string{"extra": string(extra)})
|
||||
if err == nil {
|
||||
if ok, _ := res["ok"].(bool); !ok {
|
||||
err = fmt.Errorf("%v", res["error"])
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// igateAutoUpgrade — ИШ на сервере старее дистрибутива, пришедшего с обновлением bj: обновить (настройки,
|
||||
// каналы и база ИШ сохраняются; прежняя версия копируется в /var/backups). Вызывается после обновления bj
|
||||
// и при запуске bj-server (обновление ядра перезапускает его до того, как успел бы сработать первый вызов).
|
||||
func igateAutoUpgrade(ctx context.Context, rc *RuntimeConfig) {
|
||||
cur := ishInstalledVersion()
|
||||
_, dist := igateDistFile()
|
||||
if !igateInstalled() || cur == "" || dist == "" || !release.IsNewer(dist, cur) || igateInstallStatus().Busy {
|
||||
return
|
||||
}
|
||||
log.Printf("lk-gateway: ИШ %s старее проверенного дистрибутива %s — обновляю", cur, dist)
|
||||
if err := igateInstallDist(ctx); err != nil {
|
||||
raiseSystemAlert(rc, "ИШ не обновлён до "+dist, "Пришёл дистрибутив ИШ "+dist+", но обновление не запустилось: "+err.Error()+". Повторить — мастер, шаг «Шлюз НРД».")
|
||||
return
|
||||
}
|
||||
for ctx.Err() == nil {
|
||||
time.Sleep(5 * time.Second)
|
||||
if st := igateInstallStatus(); !st.Busy {
|
||||
if st.Stage == "done" {
|
||||
raiseSystemAlert(rc, "ИШ обновлён до "+dist, "Интеграционный шлюз НРД обновлён с "+cur+" до "+dist+" (версия, проверенная ZETIT). Настройки и каналы сохранены.")
|
||||
} else {
|
||||
raiseSystemAlert(rc, "ИШ не обновлён до "+dist, "Обновление ИШ с "+cur+" до "+dist+" не прошло: "+st.Msg+". Прежняя версия сохранена в /var/backups; повторить — мастер, шаг «Шлюз НРД».")
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
return best
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user