Skip to content

Commit 2f99763

Browse files
committed
feat(api): add stop api
1 parent 7672730 commit 2f99763

File tree

7 files changed

+66
-2
lines changed

7 files changed

+66
-2
lines changed

cmd/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"bauklotze/pkg/machine/define"
1111
"bauklotze/pkg/machine/events"
1212
"context"
13+
"errors"
1314
"fmt"
1415
"os"
1516
"path/filepath"
@@ -84,7 +85,9 @@ func RootCmdExecute() {
8485
err := rootCmd.ExecuteContext(context.Background())
8586
if err != nil {
8687
logrus.Errorf("Exit duto error: %v", err)
87-
events.NotifyError(err)
88+
if errors.Is(err, define.ErrVMAlreadyRunning) {
89+
events.NotifyError(err)
90+
}
8891
registry.NotifyAndExit(1)
8992
} else {
9093
registry.NotifyAndExit(0)

pkg/api/backend/errors.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ import "errors"
88
var (
99
ErrMachineConfigNull = errors.New("machineConfig is null")
1010
ErrStreamNotSupport = errors.New("stream not support")
11+
ErrStopVMFailed = errors.New("stop vm failed")
1112
)

pkg/api/backend/stop.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package backend
2+
3+
import (
4+
"bauklotze/pkg/machine/ssh/service"
5+
"net/http"
6+
7+
"bauklotze/pkg/api/types"
8+
"bauklotze/pkg/api/utils"
9+
"bauklotze/pkg/machine/vmconfig"
10+
)
11+
12+
func StopVM(w http.ResponseWriter, r *http.Request) {
13+
mc := r.Context().Value(types.McKey).(*vmconfig.MachineConfig)
14+
if mc == nil {
15+
utils.Error(w, http.StatusInternalServerError, ErrMachineConfigNull)
16+
return
17+
}
18+
19+
// in busybox init system, reboot cause vCPU 0 received shutdown signal so the
20+
// krunkit will be shutdown after the vm shutdown
21+
err := service.GracefulShutdownVK(mc)
22+
if err != nil {
23+
utils.Error(w, http.StatusInternalServerError, ErrStopVMFailed)
24+
}
25+
}

pkg/api/server/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ func (s *APIServer) Shutdown() error {
138138
func (s *APIServer) setupRouter(r *mux.Router) *mux.Router {
139139
r.Handle("/{name}/info", s.APIHandler(backend.GetInfos)).Methods(http.MethodGet)
140140
r.Handle("/{name}/exec", s.APIHandler(backend.DoExec)).Methods(http.MethodPost)
141+
r.Handle("/{name}/stop", s.APIHandler(backend.StopVM)).Methods(http.MethodPost)
141142
return r
142143
}
143144

pkg/machine/define/errors.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ var (
99
ErrConstructVMFile = errors.New("construct VMFile failed")
1010
ErrCatchSignal = errors.New("catch signal")
1111
ErrPPIDNotRunning = errors.New("PPID exited")
12+
ErrVMMExitNormally = errors.New("hypervisor exited normally")
1213
)

pkg/machine/shim/host.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,10 @@ func Wait(ctx context.Context, mc *vmconfig.MachineConfig) error {
174174
case err := <-errChanGvp:
175175
return fmt.Errorf("network provider exit: %w", err)
176176
case err := <-errChanVmm:
177-
return fmt.Errorf("hypervisor exit: %w", err)
177+
if err != nil {
178+
return fmt.Errorf("hypervisor exit: %w", err)
179+
}
180+
return define.ErrVMMExitNormally
178181
}
179182
}
180183

pkg/machine/ssh/service/service.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"fmt"
99
"time"
1010

11+
"github.com/sirupsen/logrus"
12+
1113
"bauklotze/pkg/machine/vmconfig"
1214
)
1315

@@ -30,3 +32,31 @@ func DoSync(mc *vmconfig.MachineConfig) error {
3032
"sync",
3133
})
3234
}
35+
36+
func GracefulShutdownVK(mc *vmconfig.MachineConfig) error {
37+
logrus.Infoln("stop all containers")
38+
if err := run(mc, "podman", []string{
39+
"stop",
40+
"-a",
41+
"-t",
42+
"3",
43+
}); err != nil {
44+
logrus.Warnf("podman stop failed: %w", err)
45+
}
46+
47+
logrus.Infoln("sync disk")
48+
if err := run(mc, "sync", []string{}); err != nil {
49+
logrus.Warnf("sync disk failed: %v", err)
50+
}
51+
52+
logrus.Infoln("stop vm now")
53+
// poweroff (provided by busybox init system) cause vCPU 0 received shutdown signal,and active power off
54+
// so the krunkit will exit clearly after vm shutdown
55+
// halt (provided by busybox init system) shutdown the kernel, but uninterrupted power supply, so the krunkit
56+
// will continue to run after vm shutdown
57+
if err := run(mc, "poweroff", []string{}); err != nil {
58+
return fmt.Errorf("stop vm failed: %w", err)
59+
}
60+
61+
return nil
62+
}

0 commit comments

Comments
 (0)