1
0
out-of-tree/daemon/process.go

174 lines
3.5 KiB
Go
Raw Normal View History

2024-02-20 13:25:31 +00:00
package daemon
import (
"database/sql"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"code.dumpstack.io/tools/out-of-tree/api"
"code.dumpstack.io/tools/out-of-tree/artifact"
"code.dumpstack.io/tools/out-of-tree/config/dotfiles"
"code.dumpstack.io/tools/out-of-tree/daemon/db"
"code.dumpstack.io/tools/out-of-tree/distro"
"code.dumpstack.io/tools/out-of-tree/qemu"
)
2024-02-25 18:04:02 +00:00
type jobProcessor struct {
2024-02-20 13:25:31 +00:00
job api.Job
log zerolog.Logger
db *sql.DB
}
2024-02-25 18:04:02 +00:00
func newJobProcessor(job api.Job, db *sql.DB) (pj jobProcessor) {
2024-02-20 13:25:31 +00:00
pj.job = job
pj.db = db
2024-02-26 08:55:27 +00:00
pj.log = log.With().
Str("uuid", job.UUID).
Str("group", job.Group).
Logger()
2024-02-20 13:25:31 +00:00
return
}
2024-02-25 18:04:02 +00:00
func (pj jobProcessor) Update() (err error) {
2024-02-26 08:55:27 +00:00
err = db.UpdateJob(pj.db, &pj.job)
2024-02-20 13:25:31 +00:00
if err != nil {
pj.log.Error().Err(err).Msgf("update job %v", pj.job)
}
return
}
2024-02-25 18:04:02 +00:00
func (pj jobProcessor) SetStatus(status api.Status) (err error) {
2024-02-20 13:25:31 +00:00
pj.log.Info().Msgf(`%v -> %v`, pj.job.Status, status)
pj.job.Status = status
err = pj.Update()
return
}
2024-02-25 18:04:02 +00:00
func (pj *jobProcessor) Process(res *Resources) (err error) {
if pj.job.Status != api.StatusWaiting {
err = errors.New("job is not available to process")
2024-02-20 13:25:31 +00:00
return
2024-02-25 18:04:02 +00:00
}
if pj.job.Artifact.Qemu.Cpus == 0 {
pj.job.Artifact.Qemu.Cpus = qemu.DefaultCPUs
}
if pj.job.Artifact.Qemu.Memory == 0 {
pj.job.Artifact.Qemu.Memory = qemu.DefaultMemory
}
err = res.Allocate(pj.job)
if err != nil {
return
}
defer func() {
res.Release(pj.job)
}()
log.Info().Msgf("process job %v", pj.job.UUID)
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
pj.SetStatus(api.StatusRunning)
defer func() {
2024-02-20 13:25:31 +00:00
if err != nil {
2024-02-25 18:04:02 +00:00
pj.SetStatus(api.StatusFailure)
} else {
pj.SetStatus(api.StatusSuccess)
2024-02-20 13:25:31 +00:00
}
2024-02-25 18:04:02 +00:00
}()
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
var tmp string
tmp, err = os.MkdirTemp(dotfiles.Dir("tmp"), "")
if err != nil {
pj.log.Error().Err(err).Msg("mktemp")
return
}
defer os.RemoveAll(tmp)
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
tmprepo := filepath.Join(tmp, "repo")
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
pj.log.Debug().Msgf("temp repo: %v", tmprepo)
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
remote := fmt.Sprintf("git://localhost:9418/%s", pj.job.RepoName)
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
pj.log.Debug().Msgf("remote: %v", remote)
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
var raw []byte
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
cmd := exec.Command("git", "clone", remote, tmprepo)
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
raw, err = cmd.CombinedOutput()
pj.log.Trace().Msgf("%v\n%v", cmd, string(raw))
if err != nil {
pj.log.Error().Msgf("%v\n%v", cmd, string(raw))
return
}
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
cmd = exec.Command("git", "checkout", pj.job.Commit)
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
cmd.Dir = tmprepo
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
raw, err = cmd.CombinedOutput()
pj.log.Trace().Msgf("%v\n%v", cmd, string(raw))
if err != nil {
pj.log.Error().Msgf("%v\n%v", cmd, string(raw))
return
}
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
pj.job.Artifact.SourcePath = tmprepo
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
var result *artifact.Result
var dq *qemu.System
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
pj.job.Artifact.Process(pj.log, pj.job.Target, false, "", "", 0,
func(q *qemu.System, ka artifact.Artifact, ki distro.KernelInfo,
res *artifact.Result) {
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
result = res
dq = q
},
)
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
logdir := dotfiles.Dir("daemon/logs", pj.job.UUID)
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
err = os.WriteFile(filepath.Join(logdir, "build.log"),
[]byte(result.Build.Output), 0644)
if err != nil {
pj.log.Error().Err(err).Msg("")
}
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
err = os.WriteFile(filepath.Join(logdir, "run.log"),
[]byte(result.Run.Output), 0644)
if err != nil {
pj.log.Error().Err(err).Msg("")
}
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
err = os.WriteFile(filepath.Join(logdir, "test.log"),
[]byte(result.Test.Output), 0644)
if err != nil {
pj.log.Error().Err(err).Msg("")
}
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
err = os.WriteFile(filepath.Join(logdir, "qemu.log"),
[]byte(dq.Stdout), 0644)
if err != nil {
pj.log.Error().Err(err).Msg("")
}
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
pj.log.Info().Msgf("build %v, run %v, test %v",
result.Build.Ok, result.Run.Ok, result.Test.Ok)
2024-02-20 13:25:31 +00:00
2024-02-25 18:04:02 +00:00
if !result.Test.Ok {
err = errors.New("tests failed")
2024-02-20 13:25:31 +00:00
}
2024-02-25 18:04:02 +00:00
2024-02-20 13:25:31 +00:00
return
}