Files
benadis-rac/internal/rac/service_mode.go
2025-08-04 11:03:25 +03:00

236 lines
7.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package rac
import (
"context"
"fmt"
"strings"
"git.benadis.ru/gitops/benadis-rac/internal/constants"
)
// EnableServiceMode включает сервисный режим
func (c *Client) EnableServiceMode(ctx context.Context, params ServiceModeParams) error {
c.logger.Info(constants.LogMsgEnablingServiceMode, "cluster_uuid", params.ClusterUUID, "infobase_uuid", params.InfobaseUUID)
// Сначала отключаем всех пользователей
if err := c.TerminateAllSessions(ctx, params.ClusterUUID, params.InfobaseUUID); err != nil {
c.logger.Warn(constants.LogMsgFailedToTerminateAllSessions, "error", err)
// Продолжаем выполнение, так как это не критичная ошибка
}
// Получаем учетные данные
clusterUser, clusterPwd := c.config.GetClusterCredentials("")
dbUser, dbPwd := c.config.GetDBCredentials("")
// Включаем сервисный режим
args := []string{
c.config.GetRACAddress(),
"infobase", "update",
"--cluster=" + params.ClusterUUID,
"--infobase=" + params.InfobaseUUID,
"--sessions-deny=" + constants.SERVICE_MODE_ON,
"--scheduled-jobs-deny=" + constants.SERVICE_MODE_ON,
"--denied-message=" + params.DeniedMessage,
"--permission-code=" + params.PermissionCode,
"--cluster-user=" + clusterUser,
"--cluster-pwd=" + clusterPwd,
"--infobase-user=" + dbUser,
"--infobase-pwd=" + dbPwd,
}
_, err := c.ExecuteCommand(ctx, args)
if err != nil {
return fmt.Errorf(constants.ErrEnableServiceMode, err)
}
c.logger.Info(constants.LogMsgServiceModeEnabled)
// Верифицируем результат
return c.VerifyServiceMode(ctx, params.ClusterUUID, params.InfobaseUUID, true)
}
// DisableServiceMode выключает сервисный режим
func (c *Client) DisableServiceMode(ctx context.Context, params ServiceModeParams) error {
c.logger.Info(constants.LogMsgDisablingServiceMode, "cluster_uuid", params.ClusterUUID, "infobase_uuid", params.InfobaseUUID)
// Получаем учетные данные
clusterUser, clusterPwd := c.config.GetClusterCredentials("")
dbUser, dbPwd := c.config.GetDBCredentials("")
args := []string{
c.config.GetRACAddress(),
"infobase", "update",
"--cluster=" + params.ClusterUUID,
"--infobase=" + params.InfobaseUUID,
"--sessions-deny=" + constants.SERVICE_MODE_OFF,
"--scheduled-jobs-deny=" + constants.SERVICE_MODE_OFF,
"--cluster-user=" + clusterUser,
"--cluster-pwd=" + clusterPwd,
"--infobase-user=" + dbUser,
"--infobase-pwd=" + dbPwd,
}
_, err := c.ExecuteCommand(ctx, args)
if err != nil {
return fmt.Errorf(constants.ErrDisableServiceMode, err)
}
c.logger.Info(constants.LogMsgServiceModeDisabled)
// Верифицируем результат
return c.VerifyServiceMode(ctx, params.ClusterUUID, params.InfobaseUUID, false)
}
// TerminateAllSessions принудительно завершает все сессии пользователей
func (c *Client) TerminateAllSessions(ctx context.Context, clusterUUID, infobaseUUID string) error {
c.logger.Info(constants.LogMsgTerminatingAllSessions, "cluster_uuid", clusterUUID, "infobase_uuid", infobaseUUID)
// Получаем список сессий
sessions, err := c.GetSessions(ctx, clusterUUID, infobaseUUID)
if err != nil {
return fmt.Errorf(constants.ErrGetSessions, err)
}
if len(sessions) == 0 {
c.logger.Info(constants.LogMsgNoActiveSessions)
return nil
}
c.logger.Info(constants.LogMsgFoundActiveSessions, "count", len(sessions))
// Завершаем каждую сессию
for _, sessionUUID := range sessions {
if err := c.TerminateSession(ctx, clusterUUID, sessionUUID); err != nil {
c.logger.Warn(constants.LogMsgFailedToTerminateSession, "session_uuid", sessionUUID, "error", err)
// Продолжаем с другими сессиями
} else {
c.logger.Debug(constants.LogMsgSessionTerminated, "session_uuid", sessionUUID)
}
}
c.logger.Info(constants.LogMsgAllSessionsTerminated)
return nil
}
// GetSessions получает список активных сессий
func (c *Client) GetSessions(ctx context.Context, clusterUUID, infobaseUUID string) ([]string, error) {
// Получаем учетные данные кластера
clusterUser, clusterPwd := c.config.GetClusterCredentials("")
args := []string{
c.config.GetRACAddress(),
"session", "list",
"--cluster=" + clusterUUID,
"--infobase=" + infobaseUUID,
"--cluster-user=" + clusterUser,
"--cluster-pwd=" + clusterPwd,
}
output, err := c.ExecuteCommand(ctx, args)
if err != nil {
return nil, fmt.Errorf(constants.ErrGetSessionList, err)
}
var sessions []string
lines := strings.Split(output, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
// Ищем строки вида "session : <uuid>"
if strings.HasPrefix(line, "session") && strings.Contains(line, ":") {
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
sessionUUID := strings.TrimSpace(parts[1])
// Проверяем, что это действительно UUID (36 символов с дефисами)
if len(sessionUUID) == constants.UUIDLength && strings.Count(sessionUUID, "-") == constants.UUIDDashCount {
sessions = append(sessions, sessionUUID)
}
}
}
}
return sessions, nil
}
// TerminateSession завершает конкретную сессию
func (c *Client) TerminateSession(ctx context.Context, clusterUUID, sessionUUID string) error {
// Получаем учетные данные кластера
clusterUser, clusterPwd := c.config.GetClusterCredentials("")
args := []string{
c.config.GetRACAddress(),
"session", "terminate",
"--cluster=" + clusterUUID,
"--session=" + sessionUUID,
"--error-message=" + constants.TechnicalMaintenanceMessage,
"--cluster-user=" + clusterUser,
"--cluster-pwd=" + clusterPwd,
}
_, err := c.ExecuteCommand(ctx, args)
if err != nil {
return fmt.Errorf(constants.ErrTerminateSession, sessionUUID, err)
}
return nil
}
// VerifyServiceMode проверяет состояние сервисного режима
func (c *Client) VerifyServiceMode(ctx context.Context, clusterUUID, infobaseUUID string, expectedEnabled bool) error {
c.logger.Info(constants.LogMsgVerifyingServiceMode, "cluster_uuid", clusterUUID, "infobase_uuid", infobaseUUID, "expected_enabled", expectedEnabled)
// Получаем учетные данные
clusterUser, clusterPwd := c.config.GetClusterCredentials("")
dbUser, dbPwd := c.config.GetDBCredentials("")
args := []string{
c.config.GetRACAddress(),
"infobase", "info",
"--cluster=" + clusterUUID,
"--infobase=" + infobaseUUID,
"--cluster-user=" + clusterUser,
"--cluster-pwd=" + clusterPwd,
"--infobase-user=" + dbUser,
"--infobase-pwd=" + dbPwd,
}
output, err := c.ExecuteCommand(ctx, args)
if err != nil {
return fmt.Errorf(constants.ErrGetInfobaseInfo, err)
}
lines := strings.Split(output, "\n")
var sessionsDeny, scheduledJobsDeny string
for _, line := range lines {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "sessions-deny") {
parts := strings.Split(line, ":")
if len(parts) >= 2 {
sessionsDeny = strings.TrimSpace(parts[1])
}
} else if strings.HasPrefix(line, "scheduled-jobs-deny") {
parts := strings.Split(line, ":")
if len(parts) >= 2 {
scheduledJobsDeny = strings.TrimSpace(parts[1])
}
}
}
expectedState := constants.SERVICE_MODE_OFF
if expectedEnabled {
expectedState = constants.SERVICE_MODE_ON
}
if sessionsDeny != expectedState {
return fmt.Errorf(constants.ErrSessionsDenyVerification, expectedState, sessionsDeny)
}
if scheduledJobsDeny != expectedState {
return fmt.Errorf(constants.ErrScheduledJobsDenyVerification, expectedState, scheduledJobsDeny)
}
c.logger.Info(constants.LogMsgServiceModeVerificationSuccessful, "sessions_deny", sessionsDeny, "scheduled_jobs_deny", scheduledJobsDeny)
return nil
}