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 : " 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 }