@@ -22,6 +22,7 @@ import (
2222 "github.com/kumori-sh/spacetrk/src/core/ports"
2323 geminiadapter "github.com/kumori-sh/spacetrk/src/infrastructure/llm/gemini"
2424 "github.com/kumori-sh/spacetrk/src/infrastructure/vm/firecracker"
25+ s3storage "github.com/kumori-sh/spacetrk/src/infrastructure/storage/s3"
2526 postgresrepo "github.com/kumori-sh/spacetrk/src/repository/postgres"
2627 agentsvc "github.com/kumori-sh/spacetrk/src/service/agent"
2728 authservice "github.com/kumori-sh/spacetrk/src/service/auth"
@@ -60,6 +61,7 @@ func main() {
6061 environmentRepo := postgresrepo .NewEnvironmentRepository (db )
6162 vmRepo := postgresrepo .NewVMRepository (db )
6263 vmMetricsHistoryRepo := postgresrepo .NewVMMetricsHistoryRepository (db )
64+ snapRepo := postgresrepo .NewSnapshotRepository (db )
6365 userRepo := postgresrepo .NewUserRepository (db )
6466 authRepo := postgresrepo .NewAuthRepository (db )
6567
@@ -99,13 +101,36 @@ func main() {
99101 vmBackend = provider
100102 }
101103
102- vmService := vmsvc .NewService (vmRepo , vmMetricsHistoryRepo , vmBackend , environmentRepo , cfg .VM .IdleTimeout )
104+ // ── Snapshot Storage ─────────────────────────────────────────────────────
105+ var snapshotStore ports.SnapshotStore
106+ if cfg .Storage .Endpoint != "" {
107+ ss , err := s3storage .NewStore (context .Background (), s3storage.Config {
108+ Endpoint : cfg .Storage .Endpoint ,
109+ Region : cfg .Storage .Region ,
110+ AccessKey : cfg .Storage .AccessKey ,
111+ SecretKey : cfg .Storage .SecretKey ,
112+ Bucket : cfg .Storage .Bucket ,
113+ UsePathStyle : cfg .Storage .UsePathStyle ,
114+ })
115+ if err != nil {
116+ logger .Warn ("S3 snapshot store unavailable, snapshots will be stored locally" , slog .Any ("error" , err ))
117+ } else {
118+ if err := ss .EnsureBucket (context .Background ()); err != nil {
119+ logger .Warn ("Failed to ensure S3 bucket" , slog .Any ("error" , err ))
120+ }
121+ snapshotStore = ss
122+ logger .Info ("S3 snapshot store configured" , slog .String ("bucket" , cfg .Storage .Bucket ))
123+ }
124+ }
125+
126+ vmService := vmsvc .NewService (vmRepo , vmMetricsHistoryRepo , vmBackend , environmentRepo , snapRepo , snapshotStore , cfg .VM .IdleTimeout , cfg .VM .AutoSnapshot , cfg .VM .ResumeGrace )
103127 orchTools := orchestratorsvc .NewInMemoryToolRegistry (nil )
104128 orchTools .Register (toolsvc .NewVMCommandTool (vmService ))
105129 orchTools .Register (toolsvc .NewVMCreateTool (vmService ))
106130 orchTools .Register (toolsvc .NewVMStartTool (vmService ))
107131 orchTools .Register (toolsvc .NewVMListTool (vmService ))
108132 orchTools .Register (toolsvc .NewVMStopTool (vmService ))
133+ orchTools .Register (toolsvc .NewVMSnapshotTool (vmService ))
109134
110135 var planner ports.ToolPlanner
111136 if cfg .LLM .DefaultProvider == "gemini" && cfg .LLM .Gemini .APIKey != "" {
@@ -139,7 +164,7 @@ func main() {
139164 planner ,
140165 orchTools ,
141166 orchestratorsvc .NewMemoryStateStore (),
142- orchestratorsvc .NewConfig ([]string {"vm.execute_command" , "vm.create" , "vm.start" , "vm.list" , "vm.stop" }, cfg .Security .MaxTaskDuration ),
167+ orchestratorsvc .NewConfig ([]string {"vm.execute_command" , "vm.create" , "vm.start" , "vm.list" , "vm.stop" , "vm.snapshot" }, cfg .Security .MaxTaskDuration ),
143168 )
144169 chatService := chatsvc .New (chatRepo , agentRepo , orchService )
145170
@@ -221,6 +246,18 @@ func (b unavailableBackend) GetMetrics(context.Context, string) (vmdomain.Metric
221246 return vmdomain.Metrics {}, b .err ()
222247}
223248
249+ func (b unavailableBackend ) CreateSnapshot (context.Context , string ) (string , int64 , error ) {
250+ return "" , 0 , b .err ()
251+ }
252+
253+ func (b unavailableBackend ) RestoreFromSnapshot (context.Context , vmdomain.CreateSpec , string ) (string , error ) {
254+ return "" , b .err ()
255+ }
256+
257+ func (b unavailableBackend ) StopPreserving (context.Context , string ) error {
258+ return b .err ()
259+ }
260+
224261func (b unavailableBackend ) err () error {
225262 return fmt .Errorf ("vm backend unavailable: %s" , b .reason )
226263}
0 commit comments