diff --git a/.gitignore b/.gitignore index 94fd9c2..5f55502 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ /starter/starter /starter/minrootfs /pkg/go/gen +/gen /runs diff --git a/Makefile b/Makefile index 430014f..e67c5db 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,19 @@ -all: - make init - make mkrootfs - make compile - make generate -init: - git clone https://github.com/alpinelinux/alpine-make-rootfs - rm -rf starter/minrootfs - mv alpine-make-rootfs starter/alpine-make-rootfs -mkrootfs: - starter/create_rootfs.sh -gen: - buf generate -compile: - go build -o ./run - gcc starter/starter.c -o starter/starter -dev: - @make gen - @go run main.go \ No newline at end of file +.PHONY: all clean install uninstall + +PROTOBUF=/usr/include/ +STARTER=starter +GEN=gen +SRCS=$(STARTER)/cgroup_prepare.c $(STARTER)/ns_exec.c $(STARTER)/util.c $(STARTER)/starter.c + +all: proto $(STARTER)/alpine-make-rootfs $(STARTER)/minrootfs $(STARTER)/starter +proto: /usr/include/google/protobuf/empty.proto proto/runner/v1/runner.proto + mkdir -p $(GEN) + protoc --c_out=$(GEN) runner/v1/runner.proto -I proto + protoc --c_out=$(GEN) google/protobuf/empty.proto -I $(PROTOBUF) +$(STARTER)/alpine-make-rootfs: + git clone https://github.com/alpinelinux/alpine-make-rootfs starter/alpine-make-rootfs +$(STARTER)/minrootfs: $(STARTER)/create_rootfs.sh + $(STARTER)/create_rootfs.sh +$(STARTER)/starter: proto $(STARTER)/starter.c $(STARTER)/cgroup_prepare.c $(STARTER)/ns_exec.c Makefile + $(CC) -o $(STARTER)/starter $(SRCS) -g -fsanitize=address -fsanitize=leak -fno-omit-frame-pointer -lrabbitmq -lprotobuf-c -I gen + #$(CC) $(STARTER)/starter.c -o $(STARTER)/starter diff --git a/buf.gen.yaml b/buf.gen.yaml deleted file mode 100644 index 73d0fed..0000000 --- a/buf.gen.yaml +++ /dev/null @@ -1,13 +0,0 @@ -version: v1 -managed: - enabled: true - go_package_prefix: - default: git.sch9.ru/new_gate/ms-runner/pkg/go/gen -plugins: - - name: go - out: pkg/go/gen - opt: paths=source_relative - - name: go-grpc - out: pkg/go/gen - opt: paths=source_relative - diff --git a/buf.yaml b/buf.yaml deleted file mode 100644 index 1a51945..0000000 --- a/buf.yaml +++ /dev/null @@ -1,7 +0,0 @@ -version: v1 -breaking: - use: - - FILE -lint: - use: - - DEFAULT diff --git a/config/config.go b/config/config.go deleted file mode 100644 index 80b3c93..0000000 --- a/config/config.go +++ /dev/null @@ -1,9 +0,0 @@ -package config - -type Config struct { - Env string `env:"ENV" env-default:"prod"` - - RabbitDSN string `env:"RABBIT_DSN" required:"true"` - InstanceName string `env:"INSTANCE_NAME" required:"true"` - TQueueName string `env:"T_QUEUE_NAME" required:"true"` -} diff --git a/go.mod b/go.mod deleted file mode 100644 index cc850d4..0000000 --- a/go.mod +++ /dev/null @@ -1,29 +0,0 @@ -module git.sch9.ru/new_gate/ms-runner - -go 1.21.3 - -toolchain go1.23.0 - -require ( - git.sch9.ru/new_gate/ms-tester v0.0.0 - github.com/containerd/cgroups v1.1.0 - github.com/golang/protobuf v1.5.4 - github.com/ilyakaznacheev/cleanenv v1.5.0 - github.com/rabbitmq/amqp091-go v1.10.0 - google.golang.org/protobuf v1.34.2 -) - -require ( - github.com/BurntSushi/toml v1.2.1 // indirect - github.com/coreos/go-systemd/v22 v22.3.2 // indirect - github.com/docker/go-units v0.4.0 // indirect - github.com/godbus/dbus/v5 v5.0.4 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/joho/godotenv v1.5.1 // indirect - github.com/opencontainers/runtime-spec v1.0.2 // indirect - go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.0 // indirect - golang.org/x/sys v0.22.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index 545359f..0000000 --- a/go.sum +++ /dev/null @@ -1,78 +0,0 @@ -git.sch9.ru/new_gate/ms-tester v0.0.0 h1:ZR5YkHCO9JAY/d1qqEgwu/Dtru6iR1p3sIBqp8tetnA= -git.sch9.ru/new_gate/ms-tester v0.0.0/go.mod h1:gqA96jkobHh1HM/bksygv2AnxM+GkCqVAdgmJyC0rE0= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= -github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2lOrsHHvr4= -github.com/ilyakaznacheev/cleanenv v1.5.0/go.mod h1:a5aDzaJrLCQZsazHol1w8InnDcOX0OColm64SlIi6gk= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw= -github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 h1:slmdOY3vp8a7KQbHkL+FLbvbkgMqmXojpFUO/jENuqQ= -olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3/go.mod h1:oVgVk4OWVDi43qWBEyGhXgYxt7+ED4iYNpTngSLX2Iw= diff --git a/internal/runner/delivery.go b/internal/runner/delivery.go deleted file mode 100644 index 75c10db..0000000 --- a/internal/runner/delivery.go +++ /dev/null @@ -1 +0,0 @@ -package runner diff --git a/internal/runner/delivery/rabbitmq/pubsub.go b/internal/runner/delivery/rabbitmq/pubsub.go deleted file mode 100644 index 2d76641..0000000 --- a/internal/runner/delivery/rabbitmq/pubsub.go +++ /dev/null @@ -1,140 +0,0 @@ -package rabbitmq - -import ( - "fmt" - "git.sch9.ru/new_gate/ms-runner/internal/runner" - "git.sch9.ru/new_gate/ms-runner/internal/runner/usecase" - runnerv1 "git.sch9.ru/new_gate/ms-runner/pkg/go/gen/proto/runner/v1" - "github.com/golang/protobuf/proto" - amqp "github.com/rabbitmq/amqp091-go" -) - -func NewRunnerBuilderConsumer(ch *amqp.Channel, runnerUC runner.RunnerUseCase, queueName string, instanceName string) { - msgs, err := ch.Consume( - queueName, - instanceName, - false, - false, - false, - false, - nil, - ) - if err != nil { - panic(err) - } - - go func() { - for { - runnerUC.Lock() - if !runnerUC.Ready() { - continue - } - runnerUC.Unlock() - - select { - case d := <-msgs: - var msg runnerv1.Instruction - - err = proto.Unmarshal(d.Body, &msg) - if err != nil { - panic(err) - } - - switch msg.Instruction.(type) { - case *runnerv1.Instruction_Build: - err = runnerUC.Process(usecase.BuildInstruction{ - SolutionId: msg.GetBuild().GetSolutionId(), - BindingKey: msg.GetBuild().GetBindingKey(), - Language: msg.GetBuild().GetLanguage(), - Solution: msg.GetBuild().GetSolution(), - }) - if err != nil { - fmt.Println(err) - } else { - err = d.Ack(false) - if err != nil { - panic(err) - } - } - case *runnerv1.Instruction_Run: - err = runnerUC.Process(usecase.RunInstruction{ - SolutionId: msg.GetRun().GetSolutionId(), - TestId: msg.GetRun().GetTestId(), - BindingKey: msg.GetRun().GetBindingKey(), - }) - if err != nil { - fmt.Println(err) - } else { - err = d.Ack(false) - if err != nil { - panic(err) - } - } - default: - fmt.Println("unknown instruction: ", msg.Instruction) - } - } - } - }() -} - -func NewRunnerBuilderProducer(ch *amqp.Channel, runnerUC runner.RunnerUseCase) { - go func() { - for res := range runnerUC.Results() { - var ( - body []byte - err error - bindingKey string - ) - - switch result := res.(type) { - case usecase.BuildResult: - msg := &runnerv1.Result{ - Result: &runnerv1.Result_Build{ - Build: &runnerv1.BuildResult{ - SolutionId: result.SolutionId, - Status: result.Status, - }, - }, - } - body, err = proto.Marshal(msg) - if err != nil { - panic(err) - } - bindingKey = result.BindingKey - case usecase.RunResult: - msg := &runnerv1.Result{ - Result: &runnerv1.Result_Run{ - Run: &runnerv1.RunResult{ - SolutionId: result.SolutionId, - TestId: result.TestId, - Status: result.Status, - }, - }, - } - body, err = proto.Marshal(msg) - if err != nil { - panic(err) - } - bindingKey = result.BindingKey - default: - fmt.Println("unknown result: ", result) - continue - } - - fmt.Println("publishing: ", bindingKey) - err = ch.Publish( - "", - bindingKey, - false, - false, - amqp.Publishing{ - ContentType: "text/plain", - Body: body, - }) - if err != nil { - panic(err) - } - } - }() -} diff --git a/internal/runner/usecase.go b/internal/runner/usecase.go deleted file mode 100644 index 8461d17..0000000 --- a/internal/runner/usecase.go +++ /dev/null @@ -1,9 +0,0 @@ -package runner - -type RunnerUseCase interface { - Process(i interface{}) error - Results() <-chan interface{} - Ready() bool - Lock() - Unlock() -} diff --git a/internal/runner/usecase/usecase.go b/internal/runner/usecase/usecase.go deleted file mode 100644 index 7cac439..0000000 --- a/internal/runner/usecase/usecase.go +++ /dev/null @@ -1,105 +0,0 @@ -package usecase - -import ( - "errors" - "fmt" - "sync" - "time" -) - -type BuildInstruction struct { - SolutionId int32 - BindingKey string - Language int32 - Solution string -} - -type BuildResult struct { - SolutionId int32 - BindingKey string - Status int32 -} - -type RunInstruction struct { - SolutionId int32 - TestId int32 - BindingKey string -} - -type RunResult struct { - SolutionId int32 - TestId int32 - BindingKey string - Status int32 -} - -type RunnerUseCase struct { - freeProcesses int32 - mtx sync.RWMutex - results chan interface{} -} - -func NewRunnerUseCase(limit int32) *RunnerUseCase { - return &RunnerUseCase{ - freeProcesses: limit, - results: make(chan interface{}), - } -} - -func (uc *RunnerUseCase) Process(i interface{}) error { - uc.mtx.Lock() - defer uc.mtx.Unlock() - if uc.freeProcesses == 0 { - return errors.New("no free processes") - } - uc.freeProcesses-- - - go func(i interface{}) { - defer func() { - uc.mtx.Lock() - uc.freeProcesses++ - uc.mtx.Unlock() - }() - - switch instruction := i.(type) { - case RunInstruction: - fmt.Println("running: ", instruction.SolutionId, instruction.TestId) - time.Sleep(time.Second) - uc.results <- RunResult{ - SolutionId: instruction.SolutionId, - TestId: instruction.TestId, - BindingKey: instruction.BindingKey, - Status: 0, - } - case BuildInstruction: - fmt.Println("building:", instruction.Language, instruction.Solution) - time.Sleep(time.Second) - uc.results <- BuildResult{ - SolutionId: instruction.SolutionId, - BindingKey: instruction.BindingKey, - Status: -1, - } - default: - fmt.Println("unknown instruction ignored") - } - }(i) - - return nil -} - -func (uc *RunnerUseCase) Results() <-chan interface{} { - return uc.results -} - -// Ready is not thread safe! -func (uc *RunnerUseCase) Ready() bool { - return uc.freeProcesses > 0 -} - -func (uc *RunnerUseCase) Lock() { - uc.mtx.Lock() -} - -func (uc *RunnerUseCase) Unlock() { - uc.mtx.Unlock() -} diff --git a/main.go b/main.go deleted file mode 100644 index 1a49a5b..0000000 --- a/main.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - "fmt" - "git.sch9.ru/new_gate/ms-runner/config" - runnerPubSub "git.sch9.ru/new_gate/ms-runner/internal/runner/delivery/rabbitmq" - runnerUseCase "git.sch9.ru/new_gate/ms-runner/internal/runner/usecase" - "git.sch9.ru/new_gate/ms-runner/pkg/external/rabbitmq" - "github.com/ilyakaznacheev/cleanenv" - "os" - "os/signal" - "syscall" -) - -func main() { - var cfg config.Config - err := cleanenv.ReadConfig(".env", &cfg) - if err != nil { - panic(fmt.Sprintf("error reading config: %s", err.Error())) - } - - conn, err := rabbitmq.NewRabbitClient(cfg.RabbitDSN) - if err != nil { - panic(err) - } - defer conn.Close() - ch, err := conn.Channel() - if err != nil { - panic(err) - } - defer ch.Close() - err = ch.Qos( - 1, - 0, - true, - ) - if err != nil { - panic(err) - } - - runnerUC := runnerUseCase.NewRunnerUseCase(10) - runnerPubSub.NewRunnerBuilderProducer(ch, runnerUC) - runnerPubSub.NewRunnerBuilderConsumer(ch, runnerUC, cfg.TQueueName, cfg.InstanceName) - - stop := make(chan os.Signal, 1) - signal.Notify(stop, syscall.SIGTERM, syscall.SIGINT) - - <-stop -} diff --git a/pkg/external/rabbitmq/client.go b/pkg/external/rabbitmq/client.go deleted file mode 100644 index 09732fa..0000000 --- a/pkg/external/rabbitmq/client.go +++ /dev/null @@ -1,7 +0,0 @@ -package rabbitmq - -import amqp "github.com/rabbitmq/amqp091-go" - -func NewRabbitClient(dsn string) (*amqp.Connection, error) { - return amqp.Dial(dsn) -} diff --git a/runner/runner.go b/runner/runner.go deleted file mode 100644 index 10e804c..0000000 --- a/runner/runner.go +++ /dev/null @@ -1,183 +0,0 @@ -//go:build wtf -// just use https://github.com/opencontainers/runc please - - -package runner - -import ( - "errors" - "io" - "fmt" - "log" - "os" - "strings" - exec "os/exec" - cgroups "github.com/containerd/cgroups" - rand "math/rand" - "time" - "git.sch9.ru/new_gate/ms-tester/pkg/models" -) - -const runIdLength = 20 - -type Limits struct { - Processes int32 - Core int32 - Memory int32 - Time int32 -} - -const Mib = 1024*1024; -const BuildMemory = 1024*Mib; -const BuildTime = 5000; - -type RunnerService struct { - CoresIsolated []int32 - CoreFreed chan int32 -} - -func genRunId() (runId string) { - for i := 0; i < runIdLength; i++ { - runId += string('a' + byte(rand.Int31n(26))) - } - return -} - -func int32ToString(n int32) string { - return fmt.Sprintf("%d", n) -} - -func copyFile(src string,dst string) error { - srcFile,err := os.Open(src) - if(err!=nil) {return err} - defer srcFile.Close() - dstFile,err := os.Create(dst) - if(err!=nil) {return err} - defer dstFile.Close() - _,err = io.Copy(dstFile,srcFile) - if(err!=nil) {return err} - err = dstFile.Sync() - if(err!=nil) {return err} - return nil -} - -func newRunFolder() (string,error) { - runId := genRunId() - err := os.Mkdir("runs/" + runId, 0777) - if(err!=nil) { return "",err } - err = os.Chmod("runs/" + runId, 0777) - if(err!=nil) { return "",err } - return runId,nil -} - -func extractNumbers(s string) (result []int32) { - lastNumber, isNumber := false,false - var curNumber int32 = 0 - for _, char := range s { - isNumber = (char >= '0' && char <= '9') - if(isNumber) { - curNumber *= 10 - curNumber += int32(char - '0') - } - if(!isNumber && lastNumber) { - result = append(result, curNumber) - curNumber = 0 - } - lastNumber = isNumber - } - if(lastNumber) { - result = append(result, curNumber) - } - return -} - -func NewRunnerService() (*RunnerService, error) { - runnerService := RunnerService{make([]int32,0),make(chan int32)} - rand.Seed(time.Now().UnixNano()) - //croup initialisation: - if cgroups.Mode() == cgroups.Unified { - log.Println("cgroups v2 usage approved") - } else { - return nil,fmt.Errorf("cgroups v2 are not enabled")//TODO: trouble description - } - //isolated cores initialisation: - cmdlineBytes := make([]byte, 400) - cmdlineFile, _ := os.Open("/proc/cmdline"); - countCmdlineBytes, _ := cmdlineFile.Read(cmdlineBytes); - cmdline := string(cmdlineBytes[:countCmdlineBytes]) - kernelParams := strings.Split(cmdline," ") - for _, param := range kernelParams{ - if(len(param) >= 9 && param[:9] == "isolcpus=") { - runnerService.CoresIsolated = append(runnerService.CoresIsolated, extractNumbers(param[9:])...) - } - } - if(len(runnerService.CoresIsolated) == 0) { - return nil,fmt.Errorf("no free cores available")//TODO: trouble description - } - go func() { - for _,core := range runnerService.CoresIsolated { - runnerService.CoreFreed <- core - } - }() - log.Println("running on cores:", runnerService.CoresIsolated) - //runs directory - os.Mkdir("runs",0777) - os.Chmod("runs",0777) - //complete - log.Println("Runner initialisation successful!") - return &runnerService,nil -} - -func (runnerService RunnerService) Build(languageId int32, filename string) { - core := <-runnerService.CoreFreed - runId,err := newRunFolder() - if(err!=nil) {log.Fatal - copyFile(filename,"runs/"+runId+"/src") - runnerService.IsolatedRun(models.Languages[languageId].CompileCmd,"../runs/"+runId,Limits{Processes: 10,Core:core,Memory:BuildMemory,Time:BuildTime}); - copyFile("runs/"+runId+"/executable","executable") - os.RemoveAll("runs/" + runId) - go func() { - runnerService.CoreFreed <- core - }() -} - -func (runnerService RunnerService) RunTest(solutionLanguageId int32, solutionFilename string, inputFilename string, checkerLanguageId int32, checkerFilename string, limits Limits) (models.Result) { - core := <-runnerService.CoreFreed - testRunId,err := newRunFolder() - if(err!=nil) {log.Fatal - copyFile(solutionFilename,"runs/"+testRunId+"/executable") - copyFile(inputFilename,"runs/"+testRunId+"/in") - code,err = runnerService.IsolatedRun(models.Languages[languageId].RunCmd,"../runs/"+testRunId,limits); - defer os.RemoveAll("runs/" + testRunId) - if(err!=nil) {log.Fatal(err);} - if(code!=0) {return models.RuntimeError} - checkRunId,err := newRunFolder() - copyFile("runs/"+testRunId+"/out","runs/"+checkRunId+"/out") - err = runnerService.IsolatedRun(models.Languages[languageId].RunCmd,"../runs/"+checkRunId,Limits{Processes: 10,Core:core,Memory:BuildMemory,Time:BuildTime}); //FIXME add input/output/answer files options - defer os.RemoveAll("runs/" + checkRunId) - if(err!=nil) {log.Fatal(err);} - switch code { - case 0: return models.Accepted //FIXME add model constants - case 1: return models.WrongAnswer - case 2: return models.PresentationError - case 3: return models.SystemFailDuringTesting - } - return models.SystemFailDuringTesting //bad checker result is a system fail - go func() { - runnerService.CoreFreed <- core - }() -} - -func (runnerService RunnerService) IsolatedRun(command []string, sharedFolder string, limits Limits) (int32,error) { - args := []string{int32ToString(limits.Processes),int32ToString(limits.Core), int32ToString(limits.Memory), int32ToString(limits.Time), sharedFolder} - args = append(args, command...) - log.Println("running isolated process with command:",args) - cmd := exec.Command("starter/starter", args...) - err := cmd.Run(); - if errors.Is(err,exec.ExitError) { - return err.ProcessState.ExitCode,nil - } else if(err!=nil) { - return 0,err - } - return 0,nil -} diff --git a/runner/runner_test.go b/runner/runner_test.go deleted file mode 100644 index d0ad0fd..0000000 --- a/runner/runner_test.go +++ /dev/null @@ -1,34 +0,0 @@ -//go:build wtf - -package runner - -import ( - "testing" -) - -type ENTestPair struct { - test string - result []int -} - -var ENTests = []ENTestPair{ - {"123", []int{123}}, - {"abc123abc", []int{123}}, - {"", []int{}}, - {"0", []int{0}}, - {"1a2a3a6", []int{1, 2, 3, 6}}, -} - -func TestExtractNumbers(t *testing.T) { - for _, test := range ENTests { - result := extractNumbers(test.test) - if len(result) != len(test.result) { - t.Error("for", test.test, "expected", test.result, "got", result) - } - for i := 0; i < len(result); i++ { - if result[i] != test.result[i] { - t.Error("for", test.test, "expected", test.result, "got", result) - } - } - } -} diff --git a/starter/cgroup_prepare.c b/starter/cgroup_prepare.c index 18c7bcd..72469c1 100644 --- a/starter/cgroup_prepare.c +++ b/starter/cgroup_prepare.c @@ -1,8 +1,4 @@ -#include -#include -#include -#include -#include +#include "starter.h" #define CGROUP_NAME_SIZE 20 char cgroup_name[CGROUP_NAME_SIZE+1]; @@ -74,3 +70,4 @@ void remove_cgroup() { rmdir(cgroup_name); chdir(cwd); } + diff --git a/starter/create_rootfs.sh b/starter/create_rootfs.sh index e00dca1..b73657b 100755 --- a/starter/create_rootfs.sh +++ b/starter/create_rootfs.sh @@ -13,5 +13,4 @@ rm -rf $SCRIPT_DIR/$NAME $SCRIPT_DIR/alpine-make-rootfs/alpine-make-rootfs --packages 'python3 gcc libc-dev' $SCRIPT_DIR/$NAME #chown -R nobody:nogroup $SCRIPT_DIR/$NAME #rm -r ../$NAME -#mv $NAME ../$NAME diff --git a/starter/ns_exec.c b/starter/ns_exec.c index 08eedc0..5e2008c 100644 --- a/starter/ns_exec.c +++ b/starter/ns_exec.c @@ -1,8 +1,6 @@ -#include -#include -#include +#include "starter.h" -static void procfs_prepare() +void procfs_prepare() { if (mkdir("/proc", 0555) && errno != EEXIST) die("Failed to mkdir /proc: %m\n"); if (mount("proc", "/proc", "proc", 0, "")) die("Failed to mount proc: %m\n"); @@ -43,7 +41,7 @@ void await_setup(int pipe) { // wait for signal from parent if (read(pipe, buf, 2) != 2) die("Failed to read from pipe: %m\n"); } -static int nsrun(void* arg) { +int nsrun(void* arg) { //die when parent dies if (prctl(PR_SET_PDEATHSIG, SIGKILL)) die("cannot PR_SET_PDEATHSIG for child process: %m\n"); struct params *params = (struct params*) arg; diff --git a/starter/starter.c b/starter/starter.c index 6b022b7..7d70fb7 100644 --- a/starter/starter.c +++ b/starter/starter.c @@ -1,43 +1,4 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util.h" - -struct params { - char* shared_folder; - int fd[2]; - int out_fd; - char **argv; -}; - -struct limits { - size_t memory; - int core; - int time; - int processes; -}; - -struct killparams{ - int time; - int pid; -}; - -#include "ns_exec.c" -#include "cgroup_prepare.c" +#include "starter.h" uint64_t time_start; @@ -107,8 +68,8 @@ static void prepare_userns(int pid) { write_file(path, line); } -static void get_real_path(char* path) { - if (realpath (argv[0], path) == 0) die("unable to resolve real path: %m");// get absolute path to executable +static void get_real_path(char* path, char* call_str) { + if (realpath (call_str, path) == 0) die("unable to resolve real path: %m");// get absolute path to executable for(int i = strlen(path); i > 0 && path[i] != '/';i--) path[i]=0;// cut filename to get directory name } @@ -117,7 +78,7 @@ int main(int argc,char** argv) { if(setgid(0)) die("must be run as root"); // get binary path char real_path[PATH_MAX]; - get_real_path(real_path); + get_real_path(real_path, argv[0]); if(chdir(real_path)) die("unable to chdir to binary path: %m"); // set random seed srand(time(NULL)); diff --git a/starter/starter.h b/starter/starter.h new file mode 100644 index 0000000..953d613 --- /dev/null +++ b/starter/starter.h @@ -0,0 +1,53 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define die(...) {fprintf(stderr,"file %s,line %d\n",__FILE__,__LINE__);die_func(__VA_ARGS__);exit(1);} +void remove_cgroup(); + +struct params { + char* shared_folder; + int fd[2]; + int out_fd; + char **argv; +}; + +struct limits { + size_t memory; + int core; + int time; + int processes; +}; + +struct killparams{ + int time; + int pid; +}; + +extern void prepare_cgroup(struct limits* limits); +extern void add_to_cgroup(int pid); +extern int check_mem(); +extern void remove_cgroup(); +extern void procfs_prepare(); +extern void await_setup(int pipe); +extern int nsrun(void* arg); +extern void die_func(const char *fmt, ...); +extern void write_file(char* path, char* line); diff --git a/starter/util.h b/starter/util.c similarity index 63% rename from starter/util.h rename to starter/util.c index 835656c..824ae43 100644 --- a/starter/util.h +++ b/starter/util.c @@ -1,18 +1,17 @@ -#define die(...) {fprintf(stderr,"file %s,line %d\n",__FILE__,__LINE__);die_func(__VA_ARGS__);} -void remove_cgroup(); +#include "starter.h" -static void die_func(const char *fmt, ...) +void die_func(const char *fmt, ...) { va_list params; va_start(params, fmt); vfprintf(stderr, fmt, params); puts("\n"); va_end(params); - remove_cgroup(); + //remove_cgroup(); exit(1); } -static void write_file(char* path, char* line) +void write_file(char* path, char* line) { FILE *f = fopen(path, "w"); if (f == NULL) {die("Failed to open file %s: %m\n", path);}