diff --git a/examples/docker.yml b/examples/docker.yml index 2c40cd124..ecfd9ec20 100644 --- a/examples/docker.yml +++ b/examples/docker.yml @@ -15,6 +15,8 @@ onboot: capabilities: - CAP_SYS_ADMIN readonly: true + - name: sysfs + image: mobylinux/sysfs:6c1d06f28ddd9681799d3950cddf044b930b221c - name: binfmt image: "mobylinux/binfmt:bdb754f25a5d851b4f5f8d185a43dfcbb3c22d01" binds: diff --git a/pkg/sysfs/.gitignore b/pkg/sysfs/.gitignore new file mode 100644 index 000000000..db2b4ca32 --- /dev/null +++ b/pkg/sysfs/.gitignore @@ -0,0 +1,4 @@ +dev +proc +sys +usr diff --git a/pkg/sysfs/Dockerfile b/pkg/sysfs/Dockerfile new file mode 100644 index 000000000..fa7e5a86f --- /dev/null +++ b/pkg/sysfs/Dockerfile @@ -0,0 +1,3 @@ +FROM scratch +COPY . ./ +CMD ["/usr/bin/sysfs"] diff --git a/pkg/sysfs/Makefile b/pkg/sysfs/Makefile new file mode 100644 index 000000000..d3f3d804f --- /dev/null +++ b/pkg/sysfs/Makefile @@ -0,0 +1,44 @@ +GO_COMPILE=mobylinux/go-compile:3afebc59c5cde31024493c3f91e6102d584a30b9@sha256:e0786141ea7df8ba5735b63f2a24b4ade9eae5a02b0e04c4fca33b425ec69b0a + +SHA_IMAGE=alpine:3.5@sha256:dfbd4a3a8ebca874ebd2474f044a0b33600d4523d03b0df76e5c5986cb02d7e8 + +SYSFS_BINARY=usr/bin/sysfs + +IMAGE=sysfs + +.PHONY: tag push clean container +default: push + +$(SYSFS_BINARY): main.go + mkdir -p $(dir $@) + tar cf - $^ | docker run --rm --net=none --log-driver=none -i $(GO_COMPILE) -o $@ | tar xf - + +DIRS=dev proc sys +$(DIRS): + mkdir -p $@ + +DEPS=$(DIRS) $(SYSFS_BINARY) etc/sysfs.d/00-moby.conf + +container: Dockerfile $(DEPS) + tar cf - $^ | docker build --no-cache -t $(IMAGE):build - + +hash: Dockerfile $(DEPS) + find $^ -type f | xargs cat | docker run --rm -i $(SHA_IMAGE) sha1sum - | sed 's/ .*//' > hash + +push: hash container + docker pull mobylinux/$(IMAGE):$(shell cat hash) || \ + (docker tag $(IMAGE):build mobylinux/$(IMAGE):$(shell cat hash) && \ + docker push mobylinux/$(IMAGE):$(shell cat hash)) + docker rmi $(IMAGE):build + rm -f hash + +tag: hash container + docker pull mobylinux/$(IMAGE):$(shell cat hash) || \ + docker tag $(IMAGE):build mobylinux/$(IMAGE):$(shell cat hash) + docker rmi $(IMAGE):build + rm -f hash + +clean: + rm -rf hash $(DIRS) usr + +.DELETE_ON_ERROR: diff --git a/pkg/sysfs/etc/sysfs.d/00-moby.conf b/pkg/sysfs/etc/sysfs.d/00-moby.conf new file mode 100644 index 000000000..92aeded2b --- /dev/null +++ b/pkg/sysfs/etc/sysfs.d/00-moby.conf @@ -0,0 +1,2 @@ +kernel/mm/transparent_hugepage/enabled = madvise +kernel/mm/transparent_hugepage/defrag = madvise diff --git a/pkg/sysfs/main.go b/pkg/sysfs/main.go new file mode 100644 index 000000000..63eef3065 --- /dev/null +++ b/pkg/sysfs/main.go @@ -0,0 +1,72 @@ +package main + +import ( + "bytes" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" +) + +var ( + configDir string + sysfsDir string +) + +func init() { + flag.StringVar(&configDir, "configDir", "/etc/sysfs.d", "directory with config files") + flag.StringVar(&sysfsDir, "sysfsDir", "/sys", "mount point for sysfs") +} + +func sysfs(line []byte) error { + // parse line into a string of expected form X/Y/Z=VALUE + sysfsLineKV := strings.Split(string(line[:]), "=") + if len(sysfsLineKV) != 2 { + if len(sysfsLineKV) >= 1 && len(sysfsLineKV[0]) >= 1 && strings.Trim(sysfsLineKV[0], " ")[:1] == "#" { + return nil + } + return fmt.Errorf("Cannot parse %s", string(line)) + } + // trim any extra whitespace + sysfsSetting, sysfsValue := strings.Trim(sysfsLineKV[0], " "), strings.Trim(sysfsLineKV[1], " ") + sysfsFile := filepath.Join(sysfsDir, sysfsSetting) + file, err := os.OpenFile(sysfsFile, os.O_WRONLY, 0) + if err != nil { + return fmt.Errorf("Cannot open %s: %s", sysfsFile, err) + } + defer file.Close() + _, err = file.Write([]byte(sysfsValue)) + if err != nil { + return fmt.Errorf("Cannot write to %s: %s", sysfsFile, err) + } + return nil +} + +func main() { + flag.Parse() + + files, err := ioutil.ReadDir(configDir) + if err != nil { + log.Fatalf("Cannot read directory %s: %s", configDir, err) + } + + for _, file := range files { + contents, err := ioutil.ReadFile(filepath.Join(configDir, file.Name())) + if err != nil { + log.Fatalf("Cannot read file %s: %s", file.Name(), err) + } + lines := bytes.Split(contents, []byte("\n")) + for _, line := range lines { + if len(line) == 0 { + continue + } + err = sysfs(line) + if err != nil { + log.Fatal(err) + } + } + } +}