Files
acc-server-manager/local/service/system_service.go
2026-03-31 18:33:49 +02:00

116 lines
3.1 KiB
Go

package service
import (
"acc-server-manager/local/model"
"acc-server-manager/local/platform"
"acc-server-manager/local/repository"
"acc-server-manager/local/utl/env"
"acc-server-manager/local/utl/logging"
"context"
"fmt"
"io"
"github.com/docker/docker/api/types/container"
dockerimage "github.com/docker/docker/api/types/image"
dockerclient "github.com/docker/docker/client"
)
type SystemService struct {
dockerClient *dockerclient.Client
repo *repository.ServerRepository
runtime platform.ServerRuntime
serverService *ServerService
}
func NewSystemService(
dockerClient *dockerclient.Client,
repo *repository.ServerRepository,
runtime platform.ServerRuntime,
serverService *ServerService,
) *SystemService {
return &SystemService{
dockerClient: dockerClient,
repo: repo,
runtime: runtime,
serverService: serverService,
}
}
func (s *SystemService) MigrateImage(ctx context.Context, stopRunning bool) (*model.MigrationResult, error) {
image := env.GetACCImage()
reader, err := s.dockerClient.ImagePull(ctx, image, dockerimage.PullOptions{})
if err != nil {
return nil, fmt.Errorf("failed to pull image %s: %v", image, err)
}
if _, err := io.Copy(io.Discard, reader); err != nil {
logging.Warn("Error draining image pull response for %s: %v", image, err)
}
reader.Close()
logging.Info("Pulled image %s", image)
servers, err := s.repo.GetAll(ctx, &model.ServerFilter{})
if err != nil {
return nil, fmt.Errorf("failed to list servers: %v", err)
}
result := &model.MigrationResult{Image: image}
for _, server := range *servers {
statusStr, _ := s.runtime.Status(ctx, server.ID)
isRunning := statusStr == model.StatusRunning.String()
if isRunning && !stopRunning {
result.Skipped = append(result.Skipped, model.ServerMigrationEntry{
ID: server.ID.String(),
Name: server.Name,
WasRunning: true,
})
continue
}
entry := model.ServerMigrationEntry{
ID: server.ID.String(),
Name: server.Name,
WasRunning: isRunning,
}
if isRunning {
if _, err := s.runtime.Stop(ctx, server.ID); err != nil {
result.Failed = append(result.Failed, model.ServerMigrationError{
ID: server.ID.String(),
Name: server.Name,
Error: fmt.Sprintf("stop failed: %v", err),
})
continue
}
}
if server.ContainerID != "" {
if err := s.dockerClient.ContainerRemove(ctx, server.ContainerID, container.RemoveOptions{Force: true}); err != nil {
logging.Warn("Failed to remove container %s for server %s: %v", server.ContainerID, server.ID, err)
}
}
server.ContainerID = ""
if err := s.repo.Update(ctx, &server); err != nil {
logging.Warn("Failed to clear ContainerID for server %s: %v", server.ID, err)
}
if isRunning {
if _, err := s.runtime.Start(ctx, server.ID); err != nil {
result.Failed = append(result.Failed, model.ServerMigrationError{
ID: server.ID.String(),
Name: server.Name,
Error: fmt.Sprintf("restart failed: %v", err),
})
continue
}
s.serverService.StartAccServerRuntime(&server)
}
result.Migrated = append(result.Migrated, entry)
}
return result, nil
}