-
Notifications
You must be signed in to change notification settings - Fork 124
/
distro.go
176 lines (159 loc) · 5.63 KB
/
distro.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package data
import (
"context"
"fmt"
"net/http"
"github.com/evergreen-ci/evergreen"
"github.com/evergreen-ci/evergreen/model"
"github.com/evergreen-ci/evergreen/model/distro"
"github.com/evergreen-ci/evergreen/model/event"
"github.com/evergreen-ci/evergreen/model/host"
"github.com/evergreen-ci/evergreen/model/user"
"github.com/evergreen-ci/evergreen/validator"
"github.com/evergreen-ci/gimlet"
"github.com/pkg/errors"
)
// UpdateDistro updates the given distro.Distro.
func UpdateDistro(ctx context.Context, old, new *distro.Distro) error {
if old.Id != new.Id {
return gimlet.ErrorResponse{
StatusCode: http.StatusInternalServerError,
Message: fmt.Sprintf("old distro '%s' and new distro '%s' have mismatched IDs", new.Id, old.Id),
}
}
if old.DispatcherSettings.Version == evergreen.DispatcherVersionRevisedWithDependencies && new.DispatcherSettings.Version != evergreen.DispatcherVersionRevisedWithDependencies {
if err := model.RemoveTaskQueues(new.Id); err != nil {
return gimlet.ErrorResponse{
StatusCode: http.StatusInternalServerError,
Message: errors.Wrapf(err, "removing task queues for distro '%s'", new.Id).Error(),
}
}
}
if !old.Disabled && new.Disabled {
if err := model.ClearTaskQueue(new.Id); err != nil {
return gimlet.ErrorResponse{
StatusCode: http.StatusInternalServerError,
Message: errors.Wrapf(err, "clearing task queues for distro '%s'", new.Id).Error(),
}
}
}
if err := new.ReplaceOne(ctx); err != nil {
return gimlet.ErrorResponse{
StatusCode: http.StatusInternalServerError,
Message: errors.Wrapf(err, "updating distro '%s'", new.Id).Error(),
}
}
return nil
}
// DeleteDistroById removes a given distro from the database based on its id.
func DeleteDistroById(ctx context.Context, u *user.DBUser, distroId string) error {
d, err := distro.FindOneId(ctx, distroId)
if err != nil {
return gimlet.ErrorResponse{
StatusCode: http.StatusInternalServerError,
Message: errors.Wrapf(err, "finding distro '%s'", distroId).Error(),
}
}
if d == nil {
return gimlet.ErrorResponse{
StatusCode: http.StatusBadRequest,
Message: fmt.Sprintf("distro '%s' not found", distroId),
}
}
if err = host.MarkInactiveStaticHosts(ctx, []string{}, d); err != nil {
return gimlet.ErrorResponse{
StatusCode: http.StatusInternalServerError,
Message: errors.Wrapf(err, "terminating inactive static hosts in distro '%s'", distroId).Error(),
}
}
if err = distro.Remove(ctx, distroId); err != nil {
return gimlet.ErrorResponse{
StatusCode: http.StatusInternalServerError,
Message: errors.Wrapf(err, "deleting distro '%s'", distroId).Error(),
}
}
if err = model.ClearTaskQueue(distroId); err != nil {
return gimlet.ErrorResponse{
StatusCode: http.StatusInternalServerError,
Message: errors.Wrapf(err, "clearing task queue for distro '%s'", distroId).Error(),
}
}
event.LogDistroRemoved(d.Id, u.Username(), d.DistroData())
return nil
}
// CopyDistroOpts is input for the CopyDistro function. It includes the ID of the distro to be copied and the new distro's ID.
type CopyDistroOpts struct {
DistroIdToCopy string
NewDistroId string
}
// CopyDistro duplicates a given distro in the database given options specifying the existing and new distro ID.
// It returns an error if one is encountered.
func CopyDistro(ctx context.Context, u *user.DBUser, opts CopyDistroOpts) error {
if opts.DistroIdToCopy == opts.NewDistroId {
return gimlet.ErrorResponse{
StatusCode: http.StatusBadRequest,
Message: "new and existing distro IDs are identical",
}
}
distroToCopy, err := distro.FindOneId(ctx, opts.DistroIdToCopy)
if err != nil {
return errors.Wrapf(err, "finding distro '%s'", opts.DistroIdToCopy)
}
if distroToCopy == nil {
return gimlet.ErrorResponse{
StatusCode: http.StatusNotFound,
Message: fmt.Sprintf("distro '%s' not found", opts.DistroIdToCopy),
}
}
distroToCopy.Id = opts.NewDistroId
return newDistro(ctx, distroToCopy, u)
}
// CreateDistro creates a new distro with the provided ID using the default settings specified here.
// It returns an error if one is encountered.
func CreateDistro(ctx context.Context, u *user.DBUser, newDistroId string) error {
defaultDistro := &distro.Distro{
Id: newDistroId,
Arch: evergreen.ArchLinuxAmd64,
BootstrapSettings: distro.BootstrapSettings{
Method: distro.BootstrapMethodLegacySSH,
Communication: distro.CommunicationMethodLegacySSH,
},
DispatcherSettings: distro.DispatcherSettings{
Version: evergreen.DispatcherVersionRevisedWithDependencies,
},
FinderSettings: distro.FinderSettings{
Version: evergreen.FinderVersionLegacy,
},
HostAllocatorSettings: distro.HostAllocatorSettings{
Version: evergreen.HostAllocatorUtilization,
},
PlannerSettings: distro.PlannerSettings{
Version: evergreen.PlannerVersionTunable,
},
Provider: evergreen.ProviderNameStatic,
WorkDir: "/data/mci",
User: "ubuntu",
}
return newDistro(ctx, defaultDistro, u)
}
func newDistro(ctx context.Context, d *distro.Distro, u *user.DBUser) error {
settings, err := evergreen.GetConfig(ctx)
if err != nil {
return errors.Wrap(err, "getting admin settings")
}
vErrs, err := validator.CheckDistro(ctx, d, settings, true)
if err != nil {
return errors.Wrapf(err, "validating distro '%s'", d.Id)
}
if len(vErrs) != 0 {
return errors.Errorf("validator encountered errors: '%s'", vErrs.String())
}
if err = d.Add(ctx, u); err != nil {
return gimlet.ErrorResponse{
StatusCode: http.StatusInternalServerError,
Message: errors.Wrapf(err, "inserting distro '%s'", d.Id).Error(),
}
}
event.LogDistroAdded(d.Id, u.Username(), d.DistroData())
return nil
}