Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/ws-daemon/pkg/cgroup/cgroup.go
2499 views
1
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package cgroup
6
7
import (
8
"context"
9
"errors"
10
11
"github.com/gitpod-io/gitpod/common-go/cgroups"
12
"github.com/gitpod-io/gitpod/common-go/log"
13
"github.com/gitpod-io/gitpod/ws-daemon/pkg/dispatch"
14
"github.com/prometheus/client_golang/prometheus"
15
"golang.org/x/xerrors"
16
)
17
18
func NewPluginHost(cgroupBasePath string, plugins ...Plugin) (*PluginHost, error) {
19
var version Version
20
unified, err := cgroups.IsUnifiedCgroupSetup()
21
if err != nil {
22
return nil, xerrors.Errorf("could not determine cgroup setup: %w", err)
23
}
24
if unified {
25
version = Version2
26
} else {
27
version = Version1
28
}
29
30
return &PluginHost{
31
CGroupBasePath: cgroupBasePath,
32
CGroupVersion: version,
33
Plugins: plugins,
34
35
pluginActivationTotalVec: prometheus.NewCounterVec(prometheus.CounterOpts{
36
Name: "cgroup_plugin_activation_total",
37
Help: "counts the total activation of cgroup plugins",
38
}, []string{"plugin", "success"}),
39
}, nil
40
}
41
42
type PluginHost struct {
43
CGroupBasePath string
44
CGroupVersion Version
45
Plugins []Plugin
46
47
pluginActivationTotalVec *prometheus.CounterVec
48
}
49
50
var _ dispatch.Listener = &PluginHost{}
51
var _ prometheus.Collector = &PluginHost{}
52
53
func (host *PluginHost) Describe(c chan<- *prometheus.Desc) {
54
host.pluginActivationTotalVec.Describe(c)
55
for _, p := range host.Plugins {
56
col, ok := p.(prometheus.Collector)
57
if !ok {
58
continue
59
}
60
61
col.Describe(c)
62
}
63
}
64
65
func (host *PluginHost) Collect(c chan<- prometheus.Metric) {
66
host.pluginActivationTotalVec.Collect(c)
67
for _, p := range host.Plugins {
68
col, ok := p.(prometheus.Collector)
69
if !ok {
70
continue
71
}
72
73
col.Collect(c)
74
}
75
}
76
77
func (host *PluginHost) WorkspaceAdded(ctx context.Context, ws *dispatch.Workspace) (err error) {
78
disp := dispatch.GetFromContext(ctx)
79
if disp == nil {
80
return xerrors.Errorf("no dispatch available")
81
}
82
83
cgroupPath, err := disp.Runtime.ContainerCGroupPath(ctx, ws.ContainerID)
84
if err != nil {
85
if errors.Is(err, context.Canceled) {
86
return nil
87
}
88
return xerrors.Errorf("cannot get cgroup path for container %s: %w", ws.ContainerID, err)
89
}
90
91
opts := &PluginOptions{
92
BasePath: host.CGroupBasePath,
93
CgroupPath: cgroupPath,
94
InstanceId: ws.InstanceID,
95
Annotations: ws.Pod.Annotations,
96
}
97
98
for _, plg := range host.Plugins {
99
if plg.Type() != host.CGroupVersion {
100
continue
101
}
102
dispatch.GetDispatchWaitGroup(ctx).Add(1)
103
104
go func(plg Plugin) {
105
defer dispatch.GetDispatchWaitGroup(ctx).Done()
106
107
err := plg.Apply(ctx, opts)
108
if err == context.Canceled || err == context.DeadlineExceeded {
109
err = nil
110
}
111
if err != nil {
112
log.WithError(err).WithFields(ws.OWI()).WithField("plugin", plg.Name()).Error("cgroup plugin failure")
113
host.pluginActivationTotalVec.WithLabelValues(plg.Name(), "false").Inc()
114
} else {
115
host.pluginActivationTotalVec.WithLabelValues(plg.Name(), "true").Inc()
116
}
117
}(plg)
118
}
119
120
return nil
121
}
122
123
type Plugin interface {
124
Name() string
125
Type() Version
126
Apply(ctx context.Context, options *PluginOptions) error
127
}
128
129
type Version int
130
131
const (
132
Version1 Version = iota
133
Version2
134
)
135
136
type PluginOptions struct {
137
BasePath string
138
CgroupPath string
139
InstanceId string
140
Annotations map[string]string
141
}
142
143