«Подготовка модулей» между ключом продукта и мастером: bj узнаёт состав лицензии, ставит модули, которые в неё входят (из комплекта образа, если там тот же выпуск, — без скачивания), запускает их службы и открывает мастер; после активации ключа и при изменении состава лицензии модули ставятся сразу, а не при следующем запуске bj

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
zuevav
2026-10-05 19:25:17 +03:00
parent 64eb63efc2
commit 0dd38bbae4
8 changed files with 413 additions and 9 deletions
+39 -1
View File
@@ -14,6 +14,7 @@ import (
"errors"
"fmt"
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/hwid"
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/license"
"io"
"log"
"net/http"
@@ -167,6 +168,7 @@ func LicenseActivate(ctx context.Context, rc *RuntimeConfig, code string) error
return err
}
log.Printf("lk-gateway: лицензия активирована на сервере лицензий: %s, лицензия %s", r.Tenant, r.LicenseID)
afterLicenseChange(rc)
return nil
}
@@ -196,10 +198,46 @@ func LicenseRenew(ctx context.Context, rc *RuntimeConfig) error {
if err := licenseAccept(rc, r.Token, "продлена"); err != nil {
return err
}
enforceModuleLicenseAsync(rc) // состав лицензии мог измениться — службы модулей в соответствие
if nl, err := verifyLicenseToken(r.Token); err == nil && licenseScopeChanged(lic, nl) {
afterLicenseChange(rc) // в лицензию добавили модуль или план — поставить, не дожидаясь перезапуска bj
} else {
enforceModuleLicenseAsync(rc) // состав лицензии мог измениться — службы модулей в соответствие
}
return nil
}
// licenseScopeChanged — изменился ли состав лицензии: план или признаки модулей.
func licenseScopeChanged(a, b *license.License) bool {
if a == nil || b == nil {
return a != b
}
if a.Plan != b.Plan || len(a.Features) != len(b.Features) {
return true
}
for _, f := range b.Features {
if !a.HasFeature(f) {
return true
}
}
return false
}
// afterLicenseChange — лицензию активировали или изменили её состав: службы модулей — в соответствие
// лицензии, а модули, которые в неё входят, но ещё не стоят, ставятся сразу. На сервере с образа ключ
// вводят уже после установки, и без этого модули (служба подписи и др.) встали бы только после
// перезапуска bj.
func afterLicenseChange(rc *RuntimeConfig) {
go func() {
ctx, cancel := context.WithTimeout(context.Background(), 12*time.Minute)
defer cancel()
enforceModuleLicense(ctx, rc)
if _, err := os.Stat(keymediaReqDir); err != nil {
return // нет root-службы (разработка, тесты)
}
_, _ = NewUpdater(rc).ensureSplitModules(ctx)
}()
}
// licenseNeedsRenew — онлайн-ключ и 15 минут без продления: так режим разработки, включённый или
// выключенный на сервере лицензий, доходит до установки быстро. После неудачи — не чаще раза в час.
func licenseNeedsRenew(rc *RuntimeConfig) bool {