diff --git a/hive/daemon/daemon.go b/hive/daemon/daemon.go index afc892592..3cc374019 100644 --- a/hive/daemon/daemon.go +++ b/hive/daemon/daemon.go @@ -1109,6 +1109,34 @@ func (d *Daemon) handleEC2Events(msg *nats.Msg) { } + // If a stop command, clean up resources but keep instance state + if command.Attributes.StopInstance && command.QMPCommand.Execute == "system_powerdown" { + slog.Info("Stopping instance", "id", command.ID) + + // Update status to stopping + d.Instances.Mu.Lock() + instance.Status = "stopping" + d.Instances.Mu.Unlock() + + // Stop the instance (keep volumes) + stopInstance := make(map[string]*vm.VM) + stopInstance[instance.ID] = instance + err = d.stopInstance(stopInstance, false) + + if err != nil { + slog.Error("Failed to stop instance", "err", err) + return + } + + // Update status to stopped + d.Instances.Mu.Lock() + instance.Status = "stopped" + instance.Attributes = command.Attributes + d.Instances.Mu.Unlock() + + slog.Info("Instance stopped", "id", command.ID) + } + // If a terminate command, clean up resources if command.Attributes.TerminateInstance { slog.Info("Terminating instance", "id", command.ID) diff --git a/hive/gateway/ec2/instance/StopInstances.go b/hive/gateway/ec2/instance/StopInstances.go index bac5669ec..799db7643 100644 --- a/hive/gateway/ec2/instance/StopInstances.go +++ b/hive/gateway/ec2/instance/StopInstances.go @@ -12,7 +12,7 @@ import ( ) // StopInstances sends stop commands to specified instances via NATS -// Uses system_powerdown without stop_instance attribute to allow restart +// Uses system_powerdown with stop_instance attribute to prevent auto-restart on daemon boot func StopInstances(input *ec2.StopInstancesInput, natsConn *nats.Conn) (*ec2.StopInstancesOutput, error) { if len(input.InstanceIds) == 0 { return nil, fmt.Errorf("no instance IDs provided") @@ -30,7 +30,7 @@ func StopInstances(input *ec2.StopInstancesInput, natsConn *nats.Conn) (*ec2.Sto instanceID := *instanceIDPtr // Build the QMP command to stop the instance - // Note: system_powerdown without stop_instance allows restart + // Note: system_powerdown with stop_instance=true prevents auto-restart on daemon boot command := qmp.Command{ ID: instanceID, QMPCommand: qmp.QMPCommand{ @@ -38,7 +38,7 @@ func StopInstances(input *ec2.StopInstancesInput, natsConn *nats.Conn) (*ec2.Sto Arguments: map[string]any{}, }, Attributes: qmp.Attributes{ - StopInstance: false, // Allow restart on daemon/node restart + StopInstance: true, // Don't auto-restart on daemon boot TerminateInstance: false, }, }