Skip to content

Commit 3eb77e1

Browse files
committed
add debian and centos support for the buildkit
Signed-off-by: YangKeao <[email protected]>
1 parent 6fb0aa0 commit 3eb77e1

File tree

10 files changed

+662
-28
lines changed

10 files changed

+662
-28
lines changed

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
### Build Manually
66

7-
Run `make all` to build the kernel module. The `KBUILD_PATH` environment variable should point to the kernel source code. By default, it's `/lib/modules/$(uname -r)/build`.
7+
Run `make all` to build the kernel module. The `KBUILD_PATH` environment variable should point to the kernel source code or kernel headers, which can be installed through `yum install kernel-devel` or `apt install linux-headers-$(uname -r)` according to your distribution. By default, it's `/lib/modules/$(uname -r)/build`.
88

99
## Usage
1010

@@ -52,10 +52,14 @@ Jobs: 16 (f=16): [r(16)][10.8%][r=55.5MiB/s,w=0KiB/s][r=14.2k,w=0 IOPS][eta 01m:
5252

5353
1. multi-queue scheduler registration is only supported on the kernel newer than 4.0, or the rhel kernel released after RHEL 7.6
5454

55-
## Warning
55+
#### Warning
5656

5757
Injecting too much delay on the root device could make your system blocked. Please make sure you have some emergency methods to make the system come back.
5858

59+
### Syscall Injection
60+
61+
WIP. It's too dangerous to inject long delay in an atomic context, so this function is removed temporarily.
62+
5963
## ROADMAP
6064

6165
### Function
@@ -72,7 +76,7 @@ Injecting too much delay on the root device could make your system blocked. Plea
7276
- [x] Linux 4.19 (Debian Buster)
7377
- [x] Linux 4.15 (Ubuntu 18.04)
7478
- [x] Linux 3.10 (CentOS 7.9)
75-
- [ ] Linux 3.10 (CentOS 7.2)
79+
- [x] Linux 3.10 (CentOS 7.6)
7680

7781
#### Function test
7882

buildkit/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Buildkit
2+
3+
The helper container to help users to build and install chaos-driver
4+
5+
## Usage
6+
7+
```bash
8+
# $(pwd)/driver should be the `driver` path under `chaos-driver` source code
9+
docker run -v $(pwd)/driver:/driver -it chaos-driver-buildkit buildkit -t ubuntu-generic -v 170 -k 4.15.0-162-generic
10+
```
11+
12+
- `-b` represents the directory of driver source code. The default value is `/driver`.
13+
- `-t` specifies the distribution. Supported values: `ubuntu-aws`, `ubuntu-generic`, `centos`, `debian`.
14+
- `-v` specifies the kernel version, which is the first number of `uname -v`. If not specified, buildkit will automatically get through `uname -v`.
15+
- `-k` specifies the kernel release version, which can be get through `uname -r`. If not specified, buildkit will automatically get through `uname -r`.
16+
17+
## TODO
18+
19+
- [x] Automatically build for distributions:
20+
- [x] CentOS7
21+
- [x] Debian
22+
- [x] Ubuntu
23+
- [x] Ubuntu AWS
24+
- [ ] Automatically install modules

buildkit/build/centos.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ import (
1111
type CentosBuilder struct {
1212
}
1313

14-
func (b *CentosBuilder) Script(release string, buildDir string) (string, error) {
14+
func (b *CentosBuilder) Script(release string, buildDir string, _ uint16) (string, error) {
1515
kr := kernelrelease.FromString(release)
16-
url, err := getResolvingURL(fetchCentosKernelURLS(kr))
16+
urls, err := getResolvingURLS(fetchCentosKernelURLS(kr))
1717
if err != nil {
1818
return "", err
1919
}
2020

2121
td := centosTemplateData{
2222
DriverBuildDir: buildDir,
23-
KernelDownloadURL: url,
23+
KernelDownloadURL: urls[0],
2424
GCCVersion: centosGccVersionFromKernelRelease(kr),
2525
}
2626

buildkit/build/debian.go

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
package build
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"io/ioutil"
7+
"net/http"
8+
"regexp"
9+
"strings"
10+
"text/template"
11+
12+
"github.com/chaos-mesh/chaos-driver/buildkit/build/kernelrelease"
13+
)
14+
15+
func init() {
16+
Targets["debian"] = &debian{}
17+
}
18+
19+
// debian is a driverkit target.
20+
type debian struct {
21+
}
22+
23+
// Script compiles the script to build the kernel module and/or the eBPF probe.
24+
func (v debian) Script(release string, buildDir string, _ uint16) (string, error) {
25+
t := template.New("debian-build-template")
26+
parsed, err := t.Parse(debianTemplate)
27+
if err != nil {
28+
return "", err
29+
}
30+
31+
kr := kernelrelease.FromString(release)
32+
33+
kurls, err := fetchDebianKernelURLS(kr)
34+
if err != nil {
35+
return "", err
36+
}
37+
38+
urls, err := getResolvingURLS(kurls)
39+
if err != nil {
40+
return "", err
41+
}
42+
43+
td := debianTemplateData{
44+
DriverBuildDir: buildDir,
45+
KernelDownloadURLS: urls,
46+
KernelLocalVersion: kr.FullExtraversion,
47+
}
48+
49+
buf := bytes.NewBuffer(nil)
50+
err = parsed.Execute(buf, td)
51+
if err != nil {
52+
return "", err
53+
}
54+
return buf.String(), nil
55+
}
56+
57+
func fetchDebianKernelURLS(kr kernelrelease.KernelRelease) ([]string, error) {
58+
kbuildURL, err := debianKbuildURLFromRelease(kr)
59+
if err != nil {
60+
return nil, err
61+
}
62+
63+
urls, err := debianHeadersURLFromRelease(kr)
64+
if err != nil {
65+
return nil, err
66+
}
67+
urls = append(urls, kbuildURL)
68+
69+
return urls, nil
70+
}
71+
72+
type debianTemplateData struct {
73+
DriverBuildDir string
74+
KernelDownloadURLS []string
75+
KernelLocalVersion string
76+
}
77+
78+
const debianTemplate = `
79+
#!/bin/bash
80+
set -xeuo pipefail
81+
82+
rm -rf /tmp/debian-build
83+
mkdir /tmp/debian-build
84+
cp -r {{ .DriverBuildDir }}/* /tmp/debian-build/
85+
cd /tmp/debian-build
86+
87+
# Fetch the kernel
88+
mkdir /tmp/kernel-download
89+
cd /tmp/kernel-download
90+
91+
{{ range $url := .KernelDownloadURLS }}
92+
curl --silent -o kernel.deb -SL {{ $url }}
93+
ar x kernel.deb
94+
tar -xvf data.tar.xz
95+
{{ end }}
96+
97+
ls -la /tmp/kernel-download
98+
cd /tmp/kernel-download/
99+
cp -r usr/* /usr
100+
cp -r lib/* /lib
101+
cd /usr/src
102+
sourcedir=$(find . -type d -name "linux-headers-*amd64" | head -n 1 | xargs readlink -f)
103+
ls -la $sourcedir
104+
105+
cd /tmp/debian-build
106+
107+
# Build the kernel module
108+
make KBUILD_PATH=$sourcedir all
109+
cp /tmp/debian-build/chaos_driver.ko {{ .DriverBuildDir }}/chaos_driver.ko
110+
`
111+
112+
func debianHeadersURLFromRelease(kr kernelrelease.KernelRelease) ([]string, error) {
113+
baseURLS := []string{
114+
"http://security-cdn.debian.org/pool/main/l/linux/",
115+
"http://security-cdn.debian.org/pool/updates/main/l/linux/",
116+
"https://mirrors.edge.kernel.org/debian/pool/main/l/linux/",
117+
}
118+
119+
for _, u := range baseURLS {
120+
urls, err := fetchDebianHeadersURLFromRelease(u, kr)
121+
122+
if err == nil {
123+
return urls, err
124+
}
125+
}
126+
127+
return nil, fmt.Errorf("kernel headers not found")
128+
}
129+
130+
func fetchDebianHeadersURLFromRelease(baseURL string, kr kernelrelease.KernelRelease) ([]string, error) {
131+
rmatch := `href="(linux-headers-%s\.%s\.%s-%s-(%s)_.*(amd64|all)\.deb)"`
132+
133+
// match for kernel versions like 4.19.0-6-amd64
134+
extraVersionPartial := strings.TrimSuffix(kr.FullExtraversion, "-amd64")
135+
matchExtraGroup := "amd64"
136+
matchExtraGroupCommon := "common"
137+
138+
// match for kernel versions like 4.19.0-6-cloud-amd64
139+
if strings.Contains(kr.FullExtraversion, "-cloud") {
140+
extraVersionPartial = strings.TrimSuffix(extraVersionPartial, "-cloud")
141+
matchExtraGroup = "cloud-amd64"
142+
}
143+
144+
// download index
145+
resp, err := http.Get(baseURL)
146+
if err != nil {
147+
return nil, err
148+
}
149+
defer resp.Body.Close()
150+
body, err := ioutil.ReadAll(resp.Body)
151+
if err != nil {
152+
return nil, err
153+
}
154+
bodyStr := string(body)
155+
156+
// look for kernel headers
157+
fullregex := fmt.Sprintf(rmatch, kr.Version, kr.PatchLevel, kr.Sublevel, extraVersionPartial, matchExtraGroup)
158+
pattern := regexp.MustCompile(fullregex)
159+
matches := pattern.FindStringSubmatch(bodyStr)
160+
if len(matches) < 1 {
161+
return nil, fmt.Errorf("kernel headers not found")
162+
}
163+
164+
// look for kernel headers common
165+
fullregexCommon := fmt.Sprintf(rmatch, kr.Version, kr.PatchLevel, kr.Sublevel, extraVersionPartial, matchExtraGroupCommon)
166+
patternCommon := regexp.MustCompile(fullregexCommon)
167+
matchesCommon := patternCommon.FindStringSubmatch(bodyStr)
168+
if len(matchesCommon) < 1 {
169+
return nil, fmt.Errorf("kernel headers common not found")
170+
}
171+
172+
foundURLS := []string{fmt.Sprintf("%s%s", baseURL, matches[1])}
173+
foundURLS = append(foundURLS, fmt.Sprintf("%s%s", baseURL, matchesCommon[1]))
174+
175+
return foundURLS, nil
176+
}
177+
178+
func debianKbuildURLFromRelease(kr kernelrelease.KernelRelease) (string, error) {
179+
rmatch := `href="(linux-kbuild-%s\.%s.*amd64\.deb)"`
180+
kbuildPattern := regexp.MustCompile(fmt.Sprintf(rmatch, kr.Version, kr.PatchLevel))
181+
baseURL := "http://mirrors.kernel.org/debian/pool/main/l/linux/"
182+
if kr.Version == "3" {
183+
baseURL = "http://mirrors.kernel.org/debian/pool/main/l/linux-tools/"
184+
}
185+
186+
resp, err := http.Get(baseURL)
187+
if err != nil {
188+
return "", err
189+
}
190+
defer resp.Body.Close()
191+
body, err := ioutil.ReadAll(resp.Body)
192+
if err != nil {
193+
return "", err
194+
}
195+
match := kbuildPattern.FindStringSubmatch(string(body))
196+
197+
if len(match) != 2 {
198+
return "", fmt.Errorf("kbuild not found")
199+
}
200+
201+
return fmt.Sprintf("%s%s", baseURL, match[1]), nil
202+
}

buildkit/build/generic.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ package build
33
var Targets map[string]Script = make(map[string]Script)
44

55
type Script interface {
6-
Script(release string, buildDir string) (string, error)
6+
Script(release string, buildDir string, version uint16) (string, error)
77
}

0 commit comments

Comments
 (0)