174 lines
4.0 KiB
Go
Executable File
174 lines
4.0 KiB
Go
Executable File
package state
|
|
|
|
import (
|
|
"encoding/json"
|
|
"log"
|
|
"os"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
/* --------------------------------------------------------------------------
|
|
CONFIG STRUCT
|
|
----------------------------------------------------------------------------*/
|
|
|
|
type Config struct {
|
|
VMID int `json:"vmid"`
|
|
Game string `json:"game"`
|
|
Variant string `json:"variant"`
|
|
Version string `json:"version"`
|
|
World string `json:"world"`
|
|
Ports []int `json:"ports"`
|
|
ArtifactPath string `json:"artifact_path"`
|
|
JavaPath string `json:"java_path"`
|
|
MemoryMB int `json:"memory_mb"`
|
|
|
|
// Steam + admin credentials
|
|
SteamUser string `json:"steam_user,omitempty"`
|
|
SteamPass string `json:"steam_pass,omitempty"`
|
|
SteamAuth string `json:"steam_auth,omitempty"`
|
|
|
|
AdminUser string `json:"admin_user,omitempty"`
|
|
AdminPass string `json:"admin_pass,omitempty"`
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------
|
|
AGENT STATE ENUM
|
|
----------------------------------------------------------------------------*/
|
|
|
|
type AgentState string
|
|
|
|
const (
|
|
StateIdle AgentState = "idle"
|
|
StateInstalling AgentState = "installing"
|
|
StateStarting AgentState = "starting"
|
|
StateRunning AgentState = "running"
|
|
StateStopping AgentState = "stopping"
|
|
StateCrashed AgentState = "crashed"
|
|
StateError AgentState = "error"
|
|
)
|
|
|
|
/* --------------------------------------------------------------------------
|
|
GLOBAL STATE STRUCT
|
|
----------------------------------------------------------------------------*/
|
|
|
|
type agentStatus struct {
|
|
mu sync.Mutex
|
|
state AgentState
|
|
lastChange time.Time
|
|
installStep string
|
|
lastError error
|
|
crashCount int
|
|
lastCrash time.Time
|
|
}
|
|
|
|
var global = &agentStatus{
|
|
state: StateIdle,
|
|
lastChange: time.Now(),
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------
|
|
STATE GETTERS
|
|
----------------------------------------------------------------------------*/
|
|
|
|
func GetState() AgentState {
|
|
global.mu.Lock()
|
|
defer global.mu.Unlock()
|
|
return global.state
|
|
}
|
|
|
|
func GetInstallStep() string {
|
|
global.mu.Lock()
|
|
defer global.mu.Unlock()
|
|
return global.installStep
|
|
}
|
|
|
|
func GetError() error {
|
|
global.mu.Lock()
|
|
defer global.mu.Unlock()
|
|
return global.lastError
|
|
}
|
|
|
|
func GetCrashCount() int {
|
|
global.mu.Lock()
|
|
defer global.mu.Unlock()
|
|
return global.crashCount
|
|
}
|
|
|
|
func GetLastChange() time.Time {
|
|
global.mu.Lock()
|
|
defer global.mu.Unlock()
|
|
return global.lastChange
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------
|
|
STATE SETTERS — unified with logging
|
|
----------------------------------------------------------------------------*/
|
|
|
|
func SetState(s AgentState) {
|
|
global.mu.Lock()
|
|
defer global.mu.Unlock()
|
|
|
|
if global.state != s {
|
|
log.Printf("[state] %s → %s\n", global.state, s)
|
|
global.state = s
|
|
global.lastChange = time.Now()
|
|
}
|
|
}
|
|
|
|
func SetInstallStep(step string) {
|
|
global.mu.Lock()
|
|
defer global.mu.Unlock()
|
|
global.installStep = step
|
|
}
|
|
|
|
func SetError(err error) {
|
|
global.mu.Lock()
|
|
defer global.mu.Unlock()
|
|
global.lastError = err
|
|
}
|
|
|
|
func RecordCrash(err error) {
|
|
global.mu.Lock()
|
|
defer global.mu.Unlock()
|
|
|
|
log.Printf("[state] crash detected: %v", err)
|
|
|
|
global.state = StateCrashed
|
|
global.lastError = err
|
|
global.crashCount++
|
|
global.lastCrash = time.Now()
|
|
}
|
|
|
|
/* --------------------------------------------------------------------------
|
|
CONFIG SAVE / LOAD
|
|
----------------------------------------------------------------------------*/
|
|
|
|
const configPath = "/opt/zlh-agent/config/payload.json"
|
|
|
|
func SaveConfig(cfg *Config) error {
|
|
if err := os.MkdirAll("/opt/zlh-agent/config", 0o755); err != nil {
|
|
return err
|
|
}
|
|
|
|
b, err := json.MarshalIndent(cfg, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.WriteFile(configPath, b, 0o644)
|
|
}
|
|
|
|
func LoadConfig() (*Config, error) {
|
|
b, err := os.ReadFile(configPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var cfg Config
|
|
if err := json.Unmarshal(b, &cfg); err != nil {
|
|
return nil, err
|
|
}
|
|
return &cfg, nil
|
|
}
|