This commit is contained in:
2025-08-04 11:03:25 +03:00
commit b1bde827de
20 changed files with 3579 additions and 0 deletions

View File

@@ -0,0 +1,235 @@
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
}