-
Notifications
You must be signed in to change notification settings - Fork 648
/
Copy pathstop.go
143 lines (126 loc) · 4.19 KB
/
stop.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package instance
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"time"
hostagentclient "github.com/lima-vm/lima/pkg/hostagent/api/client"
hostagentevents "github.com/lima-vm/lima/pkg/hostagent/events"
"github.com/lima-vm/lima/pkg/limayaml"
"github.com/lima-vm/lima/pkg/osutil"
"github.com/lima-vm/lima/pkg/store"
"github.com/lima-vm/lima/pkg/store/filenames"
"github.com/sirupsen/logrus"
)
func StopGracefully(inst *store.Instance, saveOnStop bool) error {
if inst.Status != store.StatusRunning {
return fmt.Errorf("expected status %q, got %q (maybe use `limactl stop -f`?)", store.StatusRunning, inst.Status)
}
if saveOnStop && inst.Saved {
logrus.Warn("saved VZ machine state is found. It will be overwritten by the new one.")
}
if inst.VMType == limayaml.VZ {
haSock := filepath.Join(inst.Dir, filenames.HostAgentSock)
haClient, err := hostagentclient.NewHostAgentClient(haSock)
if err != nil {
logrus.WithError(err).Error("Failed to create a host agent client")
}
ctx, cancel := context.WithTimeout(context.TODO(), 3*time.Second)
defer cancel()
disableSaveOnStopConfig := struct {
SaveOnStop bool `json:"saveOnStop"`
}{SaveOnStop: saveOnStop}
_, err = haClient.DriverConfig(ctx, disableSaveOnStopConfig)
if err != nil {
return fmt.Errorf("failed to disable saveOnStop: %w", err)
}
} else if saveOnStop {
return fmt.Errorf("save is not supported for %q", inst.VMType)
}
begin := time.Now() // used for logrus propagation
logrus.Infof("Sending SIGINT to hostagent process %d", inst.HostAgentPID)
if err := osutil.SysKill(inst.HostAgentPID, osutil.SigInt); err != nil {
logrus.Error(err)
}
logrus.Info("Waiting for the host agent and the driver processes to shut down")
return waitForHostAgentTermination(context.TODO(), inst, begin)
}
func waitForHostAgentTermination(ctx context.Context, inst *store.Instance, begin time.Time) error {
ctx2, cancel := context.WithTimeout(ctx, 3*time.Minute+10*time.Second)
defer cancel()
var receivedExitingEvent bool
onEvent := func(ev hostagentevents.Event) bool {
if len(ev.Status.Errors) > 0 {
logrus.Errorf("%+v", ev.Status.Errors)
}
if ev.Status.Exiting {
receivedExitingEvent = true
return true
}
return false
}
haStdoutPath := filepath.Join(inst.Dir, filenames.HostAgentStdoutLog)
haStderrPath := filepath.Join(inst.Dir, filenames.HostAgentStderrLog)
if err := hostagentevents.Watch(ctx2, haStdoutPath, haStderrPath, begin, onEvent); err != nil {
return err
}
if !receivedExitingEvent {
return errors.New("did not receive an event with the \"exiting\" status")
}
return nil
}
func StopForcibly(inst *store.Instance) {
if inst.DriverPID > 0 {
logrus.Infof("Sending SIGKILL to the %s driver process %d", inst.VMType, inst.DriverPID)
if err := osutil.SysKill(inst.DriverPID, osutil.SigKill); err != nil {
logrus.Error(err)
}
} else {
logrus.Infof("The %s driver process seems already stopped", inst.VMType)
}
for _, d := range inst.AdditionalDisks {
diskName := d.Name
disk, err := store.InspectDisk(diskName)
if err != nil {
logrus.Warnf("Disk %q does not exist", diskName)
continue
}
if err := disk.Unlock(); err != nil {
logrus.Warnf("Failed to unlock disk %q. To use, run `limactl disk unlock %v`", diskName, diskName)
}
}
if inst.HostAgentPID > 0 {
logrus.Infof("Sending SIGKILL to the host agent process %d", inst.HostAgentPID)
if err := osutil.SysKill(inst.HostAgentPID, osutil.SigKill); err != nil {
logrus.Error(err)
}
} else {
logrus.Info("The host agent process seems already stopped")
}
suffixesToBeRemoved := []string{".pid", ".sock", ".tmp"}
globPatterns := strings.ReplaceAll(strings.Join(suffixesToBeRemoved, " "), ".", "*.")
logrus.Infof("Removing %s under %q", globPatterns, inst.Dir)
fi, err := os.ReadDir(inst.Dir)
if err != nil {
logrus.Error(err)
return
}
for _, f := range fi {
path := filepath.Join(inst.Dir, f.Name())
for _, suffix := range suffixesToBeRemoved {
if strings.HasSuffix(path, suffix) {
logrus.Infof("Removing %q", path)
if err := os.Remove(path); err != nil {
if errors.Is(err, os.ErrNotExist) {
logrus.Debug(err.Error())
} else {
logrus.Error(err)
}
}
}
}
}
}