split ffi from executor server

This commit is contained in:
criyle 2020-05-19 16:14:03 -04:00
parent 84dc8cfe29
commit 411d74a087
17 changed files with 187 additions and 143 deletions

View File

@ -23,8 +23,13 @@ jobs:
GOARCH: ${{ matrix.GOARCH }}
run: |
go build -o executorserver ./cmd/executorserver
- name: Build shared objects
env:
GOOS: linux
GOARCH: ${{ matrix.GOARCH }}
run: |
go build -o cinit ./cmd/cinit
go build -buildmode=c-shared -o executorserver.so ./cmd/executorserver
go build -buildmode=c-shared -o executorserver.so ./cmd/ffi
- name: Upload executorserver
uses: actions/upload-artifact@master
with:
@ -54,7 +59,7 @@ jobs:
- name: Build on Windows
run: |
go build -o executorserver.exe ./cmd/executorserver
go build -buildmode=c-shared -o executorserver.dll ./cmd/executorserver
go build -buildmode=c-shared -o executorserver.dll ./cmd/ffi
- name: Upload executorserver.exe on Windows
uses: actions/upload-artifact@master
with:
@ -66,7 +71,7 @@ jobs:
name: ExecutorServer.dll
path: executorserver.dll
build-macos:
name: Build
name: Build macOS
runs-on: macos-latest
steps:
- name: Set up Go 1.14
@ -79,7 +84,7 @@ jobs:
- name: Build on MacOS
run: |
go build -o executorserver ./cmd/executorserver
go build -buildmode=c-shared -o executorserver.dylib ./cmd/executorserver
go build -buildmode=c-shared -o executorserver.dylib ./cmd/ffi
- name: Upload executorserver
uses: actions/upload-artifact@master
with:

View File

@ -13,7 +13,7 @@ COPY ./ /go/judge
RUN go build -o executorserver ./cmd/executorserver && \
go build -o cinit ./cmd/cinit && \
go build -buildmode=c-shared -o executor_server.so ./cmd/executorserver/
go build -buildmode=c-shared -o executor_server.so ./cmd/ffi/
FROM alpine:latest

View File

@ -8,7 +8,9 @@ RUN go mod download
COPY ./ /go/judge
RUN go build -o executorserver ./cmd/executorserver
RUN go build -o executorserver ./cmd/executorserver \
go build -o cinit ./cmd/cinit && \
go build -buildmode=c-shared -o executor_server.so ./cmd/ffi/
FROM debian:latest

View File

@ -48,7 +48,7 @@ Build container init `cinit`:
Build `executor_server.so`:
`go build -buildmode=c-shared -o executor_server.so ./cmd/executorserver/`
`go build -buildmode=c-shared -o executor_server.so ./cmd/ffi/`
For example, in JavaScript, run with `ffi-napi` (seems node 14 is not supported yet):
@ -96,7 +96,7 @@ const result = JSON.parse(executor_server.Exec(JSON.stringify({
})));
console.log(result);
// Async
// Async
executor_server.Exec.async(JSON.stringify({
"cmd": [{
"args": ["/bin/cat", "test.txt"],
@ -201,7 +201,7 @@ Build `executorserver` by:
Build `executor_server.dll`: (need to install `gcc` as well)
`go build -buildmode=c-shared -o executor_server.so ./cmd/executorserver/`
`go build -buildmode=c-shared -o executor_server.so ./cmd/ffi/`
Run: `./executorserver`
@ -219,7 +219,7 @@ Build `executorserver` by:
Build `executor_server.dylib`: (need to install `XCode`)
`go build -buildmode=c-shared -o executor_server.dylib ./cmd/executorserver/`
`go build -buildmode=c-shared -o executor_server.dylib ./cmd/ffi/`
Run: `./executorserver`

View File

@ -7,7 +7,9 @@ import (
"log"
"os"
"github.com/criyle/go-judge/env"
"github.com/criyle/go-judge/filestore"
"github.com/criyle/go-judge/pkg/pool"
"github.com/criyle/go-judge/worker"
"github.com/gin-gonic/gin"
)
@ -46,7 +48,11 @@ func main() {
}
fs := newFilsStore(*dir)
envPool := newEnvPool()
b, err := env.NewBuilder(*cinitPath, *mountConf, *tmpFsParam, *netShare, printLog)
if err != nil {
log.Fatalln("create environment builder failed", err)
}
envPool := pool.NewPool(b)
work = worker.New(fs, envPool, *parallism, *dir)
work.Start()
printLog("Starting worker with parallism", *parallism)

View File

@ -1,23 +0,0 @@
package main
import (
"github.com/criyle/go-judge/pkg/envexec"
"github.com/criyle/go-judge/pkg/macsandbox"
"github.com/criyle/go-judge/pkg/pool"
)
var defaultRead = []string{
"/",
}
var defaultWrite = []string{
"/tmp",
"/dev/null",
"/var/tmp",
}
func newEnvPool() envexec.EnvironmentPool {
b := macsandbox.NewBuilder("", defaultRead, defaultWrite, *netShare)
printLog("created mac sandbox at", "")
return pool.NewPool(b)
}

View File

@ -1,80 +1,9 @@
package main
import (
"io/ioutil"
"log"
"os"
"sync/atomic"
"syscall"
"github.com/criyle/go-judge/pkg/envexec"
"github.com/criyle/go-judge/pkg/pool"
"github.com/criyle/go-sandbox/container"
"github.com/criyle/go-sandbox/pkg/cgroup"
"github.com/criyle/go-sandbox/pkg/forkexec"
)
func init() {
container.Init()
}
func newEnvPool() envexec.EnvironmentPool {
root, err := ioutil.TempDir("", "executorserver")
if err != nil {
log.Fatalln(err)
}
printLog("Created tmp dir for container root at:", root)
mb, err := parseMountConfig(*mountConf)
if err != nil {
if !os.IsNotExist(err) {
log.Fatalln(err)
}
printLog("Use the default container mount")
mb = getDefaultMount()
}
m, err := mb.Build(true)
if err != nil {
log.Fatalln(err)
}
printLog("Created container mount at:", mb)
unshareFlags := uintptr(forkexec.UnshareFlags)
if *netShare {
unshareFlags ^= syscall.CLONE_NEWNET
}
b := &container.Builder{
Root: root,
Mounts: m,
CredGenerator: newCredGen(),
Stderr: true,
CloneFlags: unshareFlags,
ExecFile: *cinitPath,
}
cgb, err := cgroup.NewBuilder("executorserver").WithCPUAcct().WithMemory().WithPids().FilterByEnv()
if err != nil {
log.Fatalln(err)
}
printLog("Created cgroup builder with:", cgb)
cgroupPool := pool.NewFakeCgroupPool(cgb)
builder := pool.NewEnvBuilder(b, cgroupPool)
return pool.NewPool(builder)
}
type credGen struct {
cur uint32
}
func newCredGen() *credGen {
return &credGen{cur: 10000}
}
func (c *credGen) Get() syscall.Credential {
n := atomic.AddUint32(&c.cur, 1)
return syscall.Credential{
Uid: n,
Gid: n,
}
}

View File

@ -1,9 +0,0 @@
// +build !windows,!linux,!darwin
package main
import "github.com/criyle/go-judge/pkg/envexec"
func newEnvPool() envexec.EnvironmentPool {
return nil
}

View File

@ -1,18 +0,0 @@
package main
import (
"log"
"github.com/criyle/go-judge/pkg/envexec"
"github.com/criyle/go-judge/pkg/pool"
"github.com/criyle/go-judge/pkg/winc"
)
func newEnvPool() envexec.EnvironmentPool {
b, err := winc.NewBuilder("")
if err != nil {
log.Fatalln("init container", err)
}
printLog("created winc builder")
return pool.NewPool(b)
}

View File

@ -5,8 +5,12 @@ import "C"
import (
"bytes"
"encoding/json"
"log"
"os"
"github.com/criyle/go-judge/env"
"github.com/criyle/go-judge/filestore"
"github.com/criyle/go-judge/pkg/pool"
"github.com/criyle/go-judge/worker"
)
@ -19,7 +23,21 @@ type initParameter struct {
MountConf string `json:"mountConf"`
}
var fs filestore.FileStore
var (
fs filestore.FileStore
work *worker.Worker
)
func newFilsStore(dir string) filestore.FileStore {
var fs filestore.FileStore
if dir == "" {
fs = filestore.NewFileMemoryStore()
} else {
os.MkdirAll(dir, 0755)
fs = filestore.NewFileLocalStore(dir)
}
return fs
}
// Init initialize the sandbox environment
//export Init
@ -33,23 +51,24 @@ func Init(i *C.char) C.int {
if ip.Parallism == 0 {
ip.Parallism = 4
}
parallism = &ip.Parallism
if ip.TmpFsParam == "" {
ip.TmpFsParam = "size=16m,nr_inodes=4k"
}
tmpFsParam = &ip.TmpFsParam
if ip.MountConf == "" {
ip.MountConf = "mount.yaml"
}
fs = newFilsStore(ip.Dir)
cinitPath = &ip.CInitPath
printLog = func(v ...interface{}) {}
envPool := newEnvPool()
work = worker.New(fs, envPool, *parallism, *dir)
printLog := func(v ...interface{}) {}
b, err := env.NewBuilder(ip.CInitPath, ip.MountConf, ip.TmpFsParam, ip.NetShare, printLog)
if err != nil {
log.Fatalln("create environment builder failed", err)
}
envPool := pool.NewPool(b)
work = worker.New(fs, envPool, ip.Parallism, ip.Dir)
work.Start()
return 0

4
cmd/ffi/main.go Normal file
View File

@ -0,0 +1,4 @@
package main
func main() {
}

2
env/doc.go vendored Normal file
View File

@ -0,0 +1,2 @@
// Package env provides a unified method to create environment for envexec
package env

23
env/env_darwin.go vendored Normal file
View File

@ -0,0 +1,23 @@
package env
import (
"github.com/criyle/go-judge/pkg/macsandbox"
"github.com/criyle/go-judge/pkg/pool"
)
var defaultRead = []string{
"/",
}
var defaultWrite = []string{
"/tmp",
"/dev/null",
"/var/tmp",
}
// NewBuilder build a environment builder
func NewBuilder(cinitPath, mountConf, tmpFsConf string, netShare bool, printLog func(v ...interface{})) (pool.EnvBuilder, error) {
b := macsandbox.NewBuilder("", defaultRead, defaultWrite, netShare)
printLog("created mac sandbox at", "")
return b, nil
}

74
env/env_linux.go vendored Normal file
View File

@ -0,0 +1,74 @@
package env
import (
"io/ioutil"
"os"
"sync/atomic"
"syscall"
"github.com/criyle/go-judge/pkg/pool"
"github.com/criyle/go-sandbox/container"
"github.com/criyle/go-sandbox/pkg/cgroup"
"github.com/criyle/go-sandbox/pkg/forkexec"
)
// NewBuilder build a environment builder
func NewBuilder(cinitPath, mountConf, tmpFsConf string, netShare bool, printLog func(v ...interface{})) (pool.EnvBuilder, error) {
root, err := ioutil.TempDir("", "executorserver")
if err != nil {
return nil, err
}
printLog("Created tmp dir for container root at:", root)
mb, err := parseMountConfig(mountConf)
if err != nil {
if !os.IsNotExist(err) {
return nil, err
}
printLog("Use the default container mount")
mb = getDefaultMount(tmpFsConf)
}
m, err := mb.Build(true)
if err != nil {
return nil, err
}
printLog("Created container mount at:", mb)
unshareFlags := uintptr(forkexec.UnshareFlags)
if netShare {
unshareFlags ^= syscall.CLONE_NEWNET
}
b := &container.Builder{
Root: root,
Mounts: m,
CredGenerator: newCredGen(),
Stderr: true,
CloneFlags: unshareFlags,
ExecFile: cinitPath,
}
cgb, err := cgroup.NewBuilder("executorserver").WithCPUAcct().WithMemory().WithPids().FilterByEnv()
if err != nil {
return nil, err
}
printLog("Created cgroup builder with:", cgb)
cgroupPool := pool.NewFakeCgroupPool(cgb)
return pool.NewEnvBuilder(b, cgroupPool), nil
}
type credGen struct {
cur uint32
}
func newCredGen() *credGen {
return &credGen{cur: 10000}
}
func (c *credGen) Get() syscall.Credential {
n := atomic.AddUint32(&c.cur, 1)
return syscall.Credential{
Uid: n,
Gid: n,
}
}

14
env/env_others.go vendored Normal file
View File

@ -0,0 +1,14 @@
// +build !windows,!linux,!darwin
package env
import (
"errors"
"runtime"
"github.com/criyle/go-judge/pkg/pool"
)
func NewBuilder(cinitPath, mountConf, tmpFsConf string, netShare bool, printLog func(v ...interface{})) (pool.EnvBuilder, error) {
return nil, errors.New("environment is not support on this platform" + runtime.GOOS)
}

16
env/env_windows.go vendored Normal file
View File

@ -0,0 +1,16 @@
package env
import (
"github.com/criyle/go-judge/pkg/pool"
"github.com/criyle/go-judge/pkg/winc"
)
// NewBuilder build a environment builder
func NewBuilder(cinitPath, mountConf, tmpFsConf string, netShare bool, printLog func(v ...interface{})) (pool.EnvBuilder, error) {
b, err := winc.NewBuilder("")
if err != nil {
return nil, err
}
printLog("created winc builder")
return b, nil
}

View File

@ -1,4 +1,4 @@
package main
package env
import (
"fmt"
@ -55,7 +55,7 @@ func parseMountConfig(p string) (*mount.Builder, error) {
return b, nil
}
func getDefaultMount() *mount.Builder {
func getDefaultMount(tmpFsConf string) *mount.Builder {
return mount.NewBuilder().
// basic exec and lib
WithBind("/bin", "bin", true).
@ -78,7 +78,7 @@ func getDefaultMount() *mount.Builder {
// javaScript wants /dev/urandom
WithBind("/dev/urandom", "dev/urandom", true).
// work dir
WithTmpfs("w", *tmpFsParam).
WithTmpfs("w", tmpFsConf).
// tmp dir
WithTmpfs("tmp", *tmpFsParam)
WithTmpfs("tmp", tmpFsConf)
}