Compare commits
No commits in common. "7070d597a8f46e2f8d23b6481ec96c043da3df8c" and "20cd32243d817f854ad63c3eedb94b1d14731f83" have entirely different histories.
7070d597a8
...
20cd32243d
2
.github/workflows/ubuntu.yml
vendored
2
.github/workflows/ubuntu.yml
vendored
@ -203,7 +203,7 @@ jobs:
|
|||||||
|
|
||||||
cp ../examples/kernel-module/{module.c,Makefile,test.sh} .
|
cp ../examples/kernel-module/{module.c,Makefile,test.sh} .
|
||||||
|
|
||||||
../out-of-tree --log-level=debug kernel list-remote --distro-id=${{ matrix.os.distro }} --distro-release=${{ matrix.os.release }}
|
../out-of-tree --log-level=debug kernel list-remote --distro=${{ matrix.os.distro }} --ver=${{ matrix.os.release }}
|
||||||
../out-of-tree --log-level=debug kernel autogen --max=1 --shuffle
|
../out-of-tree --log-level=debug kernel autogen --max=1 --shuffle
|
||||||
../out-of-tree --log-level=debug pew --qemu-timeout=20m --include-internal-errors
|
../out-of-tree --log-level=debug pew --qemu-timeout=20m --include-internal-errors
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/naoina/toml"
|
"github.com/naoina/toml"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"code.dumpstack.io/tools/out-of-tree/config/dotfiles"
|
"code.dumpstack.io/tools/out-of-tree/config/dotfiles"
|
||||||
"code.dumpstack.io/tools/out-of-tree/distro"
|
"code.dumpstack.io/tools/out-of-tree/distro"
|
||||||
@ -240,9 +241,8 @@ func (ka Artifact) Supported(ki distro.KernelInfo) (supported bool, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO too many parameters
|
|
||||||
func (ka Artifact) Process(slog zerolog.Logger, ki distro.KernelInfo,
|
func (ka Artifact) Process(slog zerolog.Logger, ki distro.KernelInfo,
|
||||||
outputOnSuccess, realtimeOutput, endless bool, cBinary,
|
endless bool, cBinary,
|
||||||
cEndlessStress string, cEndlessTimeout time.Duration,
|
cEndlessStress string, cEndlessTimeout time.Duration,
|
||||||
dump func(q *qemu.System, ka Artifact, ki distro.KernelInfo,
|
dump func(q *qemu.System, ka Artifact, ki distro.KernelInfo,
|
||||||
result *Result)) {
|
result *Result)) {
|
||||||
@ -338,14 +338,8 @@ func (ka Artifact) Process(slog zerolog.Logger, ki distro.KernelInfo,
|
|||||||
slog.Debug().Str("duration", time.Since(start).String()).
|
slog.Debug().Str("duration", time.Since(start).String()).
|
||||||
Msg("build done")
|
Msg("build done")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error().Err(err).Msgf("build failure\n%v\n", result.Build.Output)
|
log.Error().Err(err).Msg("build")
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
if outputOnSuccess && !realtimeOutput {
|
|
||||||
slog.Info().Msgf("build success\n%v\n", result.Build.Output)
|
|
||||||
} else {
|
|
||||||
slog.Info().Msg("build success")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result.Build.Ok = true
|
result.Build.Ok = true
|
||||||
} else {
|
} else {
|
||||||
@ -403,39 +397,11 @@ func (ka Artifact) Process(slog zerolog.Logger, ki distro.KernelInfo,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var qemuTestOutput string
|
|
||||||
q.SetQemuOutputHandler(func(s string) {
|
|
||||||
if realtimeOutput {
|
|
||||||
fmt.Printf("kmsg: %s\n", s)
|
|
||||||
} else {
|
|
||||||
qemuTestOutput += s + "\n"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if realtimeOutput {
|
|
||||||
q.SetCommandsOutputHandler(func(s string) {
|
|
||||||
fmt.Printf("test: %s\n", s)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
copyArtifactAndTest(slog, q, ka, &result, remoteTest, outputOnSuccess, realtimeOutput)
|
copyArtifactAndTest(slog, q, ka, &result, remoteTest)
|
||||||
slog.Debug().Str("duration", time.Since(start).String()).
|
slog.Debug().Str("duration", time.Since(start).String()).
|
||||||
Msgf("test completed (success: %v)", result.Test.Ok)
|
Msgf("test completed (success: %v)", result.Test.Ok)
|
||||||
|
|
||||||
if result.Build.Ok {
|
|
||||||
if !result.Run.Ok || !result.Test.Ok {
|
|
||||||
slog.Error().Msgf("qemu output\n%v\n", qemuTestOutput)
|
|
||||||
} else if outputOnSuccess && !realtimeOutput {
|
|
||||||
slog.Info().Msgf("qemu output\n%v\n", qemuTestOutput)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if realtimeOutput {
|
|
||||||
q.CloseCommandsOutputHandler()
|
|
||||||
}
|
|
||||||
q.CloseQemuOutputHandler()
|
|
||||||
|
|
||||||
if !endless {
|
if !endless {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -157,15 +157,9 @@ func Build(flog zerolog.Logger, tmp string, ka Artifact,
|
|||||||
|
|
||||||
c.Args = append(c.Args, "--network", "none")
|
c.Args = append(c.Args, "--network", "none")
|
||||||
|
|
||||||
c.SetCommandsOutputHandler(func(s string) {
|
|
||||||
fmt.Printf("%s\n", s)
|
|
||||||
})
|
|
||||||
|
|
||||||
output, err = c.Run(outdir, []string{
|
output, err = c.Run(outdir, []string{
|
||||||
buildCommand + " && chmod -R 777 /work",
|
buildCommand + " && chmod -R 777 /work",
|
||||||
})
|
})
|
||||||
|
|
||||||
c.CloseCommandsOutputHandler()
|
|
||||||
} else {
|
} else {
|
||||||
cmd := exec.Command("bash", "-c", "cd "+outdir+" && "+
|
cmd := exec.Command("bash", "-c", "cd "+outdir+" && "+
|
||||||
buildCommand)
|
buildCommand)
|
||||||
@ -287,7 +281,7 @@ func CopyFile(sourcePath, destinationPath string) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func copyArtifactAndTest(slog zerolog.Logger, q *qemu.System, ka Artifact,
|
func copyArtifactAndTest(slog zerolog.Logger, q *qemu.System, ka Artifact,
|
||||||
res *Result, remoteTest string, outputOnSuccess, realtimeOutput bool) (err error) {
|
res *Result, remoteTest string) (err error) {
|
||||||
|
|
||||||
// Copy all test files to the remote machine
|
// Copy all test files to the remote machine
|
||||||
for _, f := range ka.TestFiles {
|
for _, f := range ka.TestFiles {
|
||||||
@ -319,7 +313,8 @@ func copyArtifactAndTest(slog zerolog.Logger, q *qemu.System, ka Artifact,
|
|||||||
|
|
||||||
res.Test.Output, err = testKernelModule(q, ka, remoteTest)
|
res.Test.Output, err = testKernelModule(q, ka, remoteTest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
slog.Error().Err(err).Msg(res.Test.Output)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
res.Test.Ok = true
|
res.Test.Ok = true
|
||||||
case KernelExploit:
|
case KernelExploit:
|
||||||
@ -332,14 +327,16 @@ func copyArtifactAndTest(slog zerolog.Logger, q *qemu.System, ka Artifact,
|
|||||||
res.Test.Output, err = testKernelExploit(q, ka, remoteTest,
|
res.Test.Output, err = testKernelExploit(q, ka, remoteTest,
|
||||||
remoteExploit)
|
remoteExploit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
slog.Error().Err(err).Msg(res.Test.Output)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
res.Run.Ok = true // does not really used
|
res.Run.Ok = true // does not really used
|
||||||
res.Test.Ok = true
|
res.Test.Ok = true
|
||||||
case Script:
|
case Script:
|
||||||
res.Test.Output, err = runScript(q, remoteTest)
|
res.Test.Output, err = runScript(q, remoteTest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
slog.Error().Err(err).Msg(res.Test.Output)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
res.Run.Ok = true
|
res.Run.Ok = true
|
||||||
res.Test.Ok = true
|
res.Test.Ok = true
|
||||||
@ -347,16 +344,7 @@ func copyArtifactAndTest(slog zerolog.Logger, q *qemu.System, ka Artifact,
|
|||||||
slog.Fatal().Msg("Unsupported artifact type")
|
slog.Fatal().Msg("Unsupported artifact type")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil || !res.Test.Ok {
|
slog.Info().Msgf("\n%v\n", res.Test.Output)
|
||||||
slog.Error().Err(err).Msgf("test error\n%v\n", res.Test.Output)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if outputOnSuccess && !realtimeOutput {
|
|
||||||
slog.Info().Msgf("test success\n%v\n", res.Test.Output)
|
|
||||||
} else {
|
|
||||||
slog.Info().Msg("test success")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = q.Command("root", "echo")
|
_, err = q.Command("root", "echo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -24,15 +24,6 @@ type ContainerCmd struct {
|
|||||||
Update ContainerUpdateCmd `cmd:"" help:"update containers"`
|
Update ContainerUpdateCmd `cmd:"" help:"update containers"`
|
||||||
Save ContainerSaveCmd `cmd:"" help:"save containers"`
|
Save ContainerSaveCmd `cmd:"" help:"save containers"`
|
||||||
Cleanup ContainerCleanupCmd `cmd:"" help:"cleanup containers"`
|
Cleanup ContainerCleanupCmd `cmd:"" help:"cleanup containers"`
|
||||||
|
|
||||||
RealtimeOutput RealtimeContainerOutputFlag `help:"show realtime output"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RealtimeContainerOutputFlag bool
|
|
||||||
|
|
||||||
func (f RealtimeContainerOutputFlag) AfterApply() (err error) {
|
|
||||||
container.Stdout = bool(f)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd ContainerCmd) Containers() (diis []container.Image, err error) {
|
func (cmd ContainerCmd) Containers() (diis []container.Image, err error) {
|
||||||
|
@ -39,8 +39,6 @@ type KernelCmd struct {
|
|||||||
|
|
||||||
ContainerTimeout time.Duration `help:"container timeout"`
|
ContainerTimeout time.Duration `help:"container timeout"`
|
||||||
|
|
||||||
RealtimeOutput RealtimeContainerOutputFlag `help:"show realtime output"`
|
|
||||||
|
|
||||||
List KernelListCmd `cmd:"" help:"list kernels"`
|
List KernelListCmd `cmd:"" help:"list kernels"`
|
||||||
ListRemote KernelListRemoteCmd `cmd:"" help:"list remote kernels"`
|
ListRemote KernelListRemoteCmd `cmd:"" help:"list remote kernels"`
|
||||||
Autogen KernelAutogenCmd `cmd:"" help:"generate kernels based on the current config"`
|
Autogen KernelAutogenCmd `cmd:"" help:"generate kernels based on the current config"`
|
||||||
@ -267,8 +265,8 @@ func (cmd *KernelListCmd) Run(g *Globals) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type KernelListRemoteCmd struct {
|
type KernelListRemoteCmd struct {
|
||||||
DistroID string `required:"" help:"distribution"`
|
Distro string `required:"" help:"distribution"`
|
||||||
DistroRelease string `help:"distro version"`
|
Ver string `help:"distro version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *KernelListRemoteCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
|
func (cmd *KernelListRemoteCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
|
||||||
@ -281,13 +279,13 @@ func (cmd *KernelListRemoteCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error
|
|||||||
|
|
||||||
container.UsePrebuilt = kernelCmd.PrebuiltContainers
|
container.UsePrebuilt = kernelCmd.PrebuiltContainers
|
||||||
|
|
||||||
distroType, err := distro.NewID(cmd.DistroID)
|
distroType, err := distro.NewID(cmd.Distro)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
km := artifact.Target{
|
km := artifact.Target{
|
||||||
Distro: distro.Distro{ID: distroType, Release: cmd.DistroRelease},
|
Distro: distro.Distro{ID: distroType, Release: cmd.Ver},
|
||||||
Kernel: artifact.Kernel{Regex: ".*"},
|
Kernel: artifact.Kernel{Regex: ".*"},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,12 +336,12 @@ func (cmd *KernelAutogenCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type KernelGenallCmd struct {
|
type KernelGenallCmd struct {
|
||||||
DistroID string `help:"distribution"`
|
Distro string `help:"distribution"`
|
||||||
DistroRelease string `help:"distro version"`
|
Ver string `help:"distro version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *KernelGenallCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
|
func (cmd *KernelGenallCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
|
||||||
distroType, err := distro.NewID(cmd.DistroID)
|
distroType, err := distro.NewID(cmd.Distro)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -359,7 +357,7 @@ func (cmd *KernelGenallCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.DistroRelease != "" && dist.Release != cmd.DistroRelease {
|
if cmd.Ver != "" && dist.Release != cmd.Ver {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,13 +376,13 @@ func (cmd *KernelGenallCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type KernelInstallCmd struct {
|
type KernelInstallCmd struct {
|
||||||
DistroID string `required:"" help:"distribution"`
|
Distro string `required:"" help:"distribution"`
|
||||||
DistroRelease string `required:"" help:"distro version"`
|
Ver string `required:"" help:"distro version"`
|
||||||
KernelRegex string `required:"" help:"kernel release mask"`
|
Kernel string `required:"" help:"kernel release mask"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *KernelInstallCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
|
func (cmd *KernelInstallCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
|
||||||
distroType, err := distro.NewID(cmd.DistroID)
|
distroType, err := distro.NewID(cmd.Distro)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -392,8 +390,8 @@ func (cmd *KernelInstallCmd) Run(kernelCmd *KernelCmd, g *Globals) (err error) {
|
|||||||
kernel.SetSigintHandler(&kernelCmd.shutdown)
|
kernel.SetSigintHandler(&kernelCmd.shutdown)
|
||||||
|
|
||||||
km := artifact.Target{
|
km := artifact.Target{
|
||||||
Distro: distro.Distro{ID: distroType, Release: cmd.DistroRelease},
|
Distro: distro.Distro{ID: distroType, Release: cmd.Ver},
|
||||||
Kernel: artifact.Kernel{Regex: cmd.KernelRegex},
|
Kernel: artifact.Kernel{Regex: cmd.Kernel},
|
||||||
}
|
}
|
||||||
err = kernelCmd.Generate(g, km)
|
err = kernelCmd.Generate(g, km)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -87,9 +87,6 @@ type PewCmd struct {
|
|||||||
Threshold float64 `help:"reliablity threshold for exit code" default:"1.00"`
|
Threshold float64 `help:"reliablity threshold for exit code" default:"1.00"`
|
||||||
IncludeInternalErrors bool `help:"count internal errors as part of the success rate"`
|
IncludeInternalErrors bool `help:"count internal errors as part of the success rate"`
|
||||||
|
|
||||||
OutputOnSuccess bool `help:"show output on success"`
|
|
||||||
RealtimeOutput bool `help:"show realtime output"`
|
|
||||||
|
|
||||||
Endless bool `help:"endless tests"`
|
Endless bool `help:"endless tests"`
|
||||||
EndlessTimeout time.Duration `help:"timeout between tests" default:"1m"`
|
EndlessTimeout time.Duration `help:"timeout between tests" default:"1m"`
|
||||||
EndlessStress string `help:"endless stress script" type:"existingfile"`
|
EndlessStress string `help:"endless stress script" type:"existingfile"`
|
||||||
@ -448,7 +445,7 @@ func (cmd PewCmd) testArtifact(swg *sizedwaitgroup.SizedWaitGroup,
|
|||||||
Str("kernel", ki.KernelRelease).
|
Str("kernel", ki.KernelRelease).
|
||||||
Logger()
|
Logger()
|
||||||
|
|
||||||
ka.Process(slog, ki, cmd.OutputOnSuccess, cmd.RealtimeOutput,
|
ka.Process(slog, ki,
|
||||||
cmd.Endless, cmd.Binary, cmd.EndlessStress, cmd.EndlessTimeout,
|
cmd.Endless, cmd.Binary, cmd.EndlessStress, cmd.EndlessTimeout,
|
||||||
func(q *qemu.System, ka artifact.Artifact, ki distro.KernelInfo, result *artifact.Result) {
|
func(q *qemu.System, ka artifact.Artifact, ki distro.KernelInfo, result *artifact.Result) {
|
||||||
dumpResult(q, ka, ki, result, cmd.Dist, cmd.Tag, cmd.Binary, cmd.DB)
|
dumpResult(q, ka, ki, result, cmd.Dist, cmd.Tag, cmd.Binary, cmd.DB)
|
||||||
|
@ -14,7 +14,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cavaliergopher/grab/v3"
|
"github.com/cavaliergopher/grab/v3"
|
||||||
@ -46,8 +45,6 @@ var UsePrebuilt = true
|
|||||||
|
|
||||||
var Prune = true
|
var Prune = true
|
||||||
|
|
||||||
var Stdout = false
|
|
||||||
|
|
||||||
type Image struct {
|
type Image struct {
|
||||||
Name string
|
Name string
|
||||||
Distro distro.Distro
|
Distro distro.Distro
|
||||||
@ -179,11 +176,6 @@ type Container struct {
|
|||||||
Args []string
|
Args []string
|
||||||
|
|
||||||
Log zerolog.Logger
|
Log zerolog.Logger
|
||||||
|
|
||||||
commandsOutput struct {
|
|
||||||
listener chan string
|
|
||||||
mu sync.Mutex
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(dist distro.Distro) (c Container, err error) {
|
func New(dist distro.Distro) (c Container, err error) {
|
||||||
@ -242,43 +234,6 @@ func NewFromKernelInfo(ki distro.KernelInfo) (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// c.SetCommandsOutputHandler(func(s string) { fmt.Println(s) })
|
|
||||||
// defer c.CloseCommandsOutputHandler()
|
|
||||||
func (c *Container) SetCommandsOutputHandler(handler func(s string)) {
|
|
||||||
c.commandsOutput.mu.Lock()
|
|
||||||
defer c.commandsOutput.mu.Unlock()
|
|
||||||
|
|
||||||
c.commandsOutput.listener = make(chan string)
|
|
||||||
|
|
||||||
go func(l chan string) {
|
|
||||||
for m := range l {
|
|
||||||
if m != "" {
|
|
||||||
handler(m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}(c.commandsOutput.listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Container) CloseCommandsOutputHandler() {
|
|
||||||
c.commandsOutput.mu.Lock()
|
|
||||||
defer c.commandsOutput.mu.Unlock()
|
|
||||||
|
|
||||||
close(c.commandsOutput.listener)
|
|
||||||
c.commandsOutput.listener = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Container) handleCommandsOutput(m string) {
|
|
||||||
if c.commandsOutput.listener == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.commandsOutput.mu.Lock()
|
|
||||||
defer c.commandsOutput.mu.Unlock()
|
|
||||||
|
|
||||||
if c.commandsOutput.listener != nil {
|
|
||||||
c.commandsOutput.listener <- m
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c Container) Name() string {
|
func (c Container) Name() string {
|
||||||
return c.name
|
return c.name
|
||||||
}
|
}
|
||||||
@ -453,10 +408,6 @@ func (c Container) build(imagePath string) (output string, err error) {
|
|||||||
scanner := bufio.NewScanner(stdout)
|
scanner := bufio.NewScanner(stdout)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
m := scanner.Text()
|
m := scanner.Text()
|
||||||
if Stdout {
|
|
||||||
fmt.Println(m)
|
|
||||||
}
|
|
||||||
c.handleCommandsOutput(m)
|
|
||||||
output += m + "\n"
|
output += m + "\n"
|
||||||
flog.Trace().Str("stdout", m).Msg("")
|
flog.Trace().Str("stdout", m).Msg("")
|
||||||
}
|
}
|
||||||
@ -530,10 +481,6 @@ func (c Container) Run(workdir string, cmds []string) (out string, err error) {
|
|||||||
scanner := bufio.NewScanner(stdout)
|
scanner := bufio.NewScanner(stdout)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
m := scanner.Text()
|
m := scanner.Text()
|
||||||
if Stdout {
|
|
||||||
fmt.Println(m)
|
|
||||||
}
|
|
||||||
c.handleCommandsOutput(m)
|
|
||||||
out += m + "\n"
|
out += m + "\n"
|
||||||
flog.Trace().Str("stdout", m).Msg("")
|
flog.Trace().Str("stdout", m).Msg("")
|
||||||
}
|
}
|
||||||
@ -541,6 +488,9 @@ func (c Container) Run(workdir string, cmds []string) (out string, err error) {
|
|||||||
|
|
||||||
err = cmd.Wait()
|
err = cmd.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
e := fmt.Sprintf("error `%v` for cmd `%v` with output `%v`",
|
||||||
|
err, cmds, out)
|
||||||
|
err = errors.New(e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ func (pj *jobProcessor) Process(res *Resources) (err error) {
|
|||||||
var result *artifact.Result
|
var result *artifact.Result
|
||||||
var dq *qemu.System
|
var dq *qemu.System
|
||||||
|
|
||||||
pj.job.Artifact.Process(pj.log, pj.job.Target, false, false, false, "", "", 0,
|
pj.job.Artifact.Process(pj.log, pj.job.Target, false, "", "", 0,
|
||||||
func(q *qemu.System, ka artifact.Artifact, ki distro.KernelInfo,
|
func(q *qemu.System, ka artifact.Artifact, ki distro.KernelInfo,
|
||||||
res *artifact.Result) {
|
res *artifact.Result) {
|
||||||
|
|
||||||
|
@ -101,16 +101,6 @@ type System struct {
|
|||||||
|
|
||||||
Stdout, Stderr string
|
Stdout, Stderr string
|
||||||
|
|
||||||
qemuOutput struct {
|
|
||||||
listener chan string
|
|
||||||
mu sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
commandsOutput struct {
|
|
||||||
listener chan string
|
|
||||||
mu sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// accessible after qemu is closed
|
// accessible after qemu is closed
|
||||||
exitErr error
|
exitErr error
|
||||||
|
|
||||||
@ -148,80 +138,6 @@ func NewSystem(arch arch, kernel Kernel, drivePath string) (q *System, err error
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// q.SetQemuOutputHandler(func(s string) { fmt.Println(s) })
|
|
||||||
// defer q.CloseQemuOutputHandler()
|
|
||||||
func (q *System) SetQemuOutputHandler(handler func(s string)) {
|
|
||||||
q.qemuOutput.mu.Lock()
|
|
||||||
defer q.qemuOutput.mu.Unlock()
|
|
||||||
|
|
||||||
q.qemuOutput.listener = make(chan string)
|
|
||||||
|
|
||||||
go func(l chan string) {
|
|
||||||
for m := range l {
|
|
||||||
if m != "" {
|
|
||||||
handler(m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}(q.qemuOutput.listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *System) CloseQemuOutputHandler() {
|
|
||||||
q.qemuOutput.mu.Lock()
|
|
||||||
defer q.qemuOutput.mu.Unlock()
|
|
||||||
|
|
||||||
close(q.qemuOutput.listener)
|
|
||||||
q.qemuOutput.listener = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *System) handleQemuOutput(m string) {
|
|
||||||
if q.qemuOutput.listener == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
q.qemuOutput.mu.Lock()
|
|
||||||
defer q.qemuOutput.mu.Unlock()
|
|
||||||
|
|
||||||
if q.qemuOutput.listener != nil {
|
|
||||||
q.qemuOutput.listener <- m
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// q.SetCommandsOutputHandler(func(s string) { fmt.Println(s) })
|
|
||||||
// defer q.CloseCommandsOutputHandler()
|
|
||||||
func (q *System) SetCommandsOutputHandler(handler func(s string)) {
|
|
||||||
q.commandsOutput.mu.Lock()
|
|
||||||
defer q.commandsOutput.mu.Unlock()
|
|
||||||
|
|
||||||
q.commandsOutput.listener = make(chan string)
|
|
||||||
|
|
||||||
go func(l chan string) {
|
|
||||||
for m := range l {
|
|
||||||
if m != "" {
|
|
||||||
handler(m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}(q.commandsOutput.listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *System) CloseCommandsOutputHandler() {
|
|
||||||
q.commandsOutput.mu.Lock()
|
|
||||||
defer q.commandsOutput.mu.Unlock()
|
|
||||||
|
|
||||||
close(q.commandsOutput.listener)
|
|
||||||
q.commandsOutput.listener = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *System) handleCommandsOutput(m string) {
|
|
||||||
if q.commandsOutput.listener == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
q.commandsOutput.mu.Lock()
|
|
||||||
defer q.commandsOutput.mu.Unlock()
|
|
||||||
|
|
||||||
if q.commandsOutput.listener != nil {
|
|
||||||
q.commandsOutput.listener <- m
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *System) SetSSHAddrPort(addr string, port int) (err error) {
|
func (q *System) SetSSHAddrPort(addr string, port int) (err error) {
|
||||||
// TODO validate
|
// TODO validate
|
||||||
q.SSH.AddrPort = fmt.Sprintf("%s:%d", addr, port)
|
q.SSH.AddrPort = fmt.Sprintf("%s:%d", addr, port)
|
||||||
@ -397,7 +313,6 @@ func (q *System) Start() (err error) {
|
|||||||
scanner := bufio.NewScanner(q.pipe.stdout)
|
scanner := bufio.NewScanner(q.pipe.stdout)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
m := scanner.Text()
|
m := scanner.Text()
|
||||||
q.handleQemuOutput(m)
|
|
||||||
q.Stdout += m + "\n"
|
q.Stdout += m + "\n"
|
||||||
q.Log.Trace().Str("stdout", m).Msg("qemu")
|
q.Log.Trace().Str("stdout", m).Msg("qemu")
|
||||||
go q.checkOopsPanic(m)
|
go q.checkOopsPanic(m)
|
||||||
@ -408,7 +323,6 @@ func (q *System) Start() (err error) {
|
|||||||
scanner := bufio.NewScanner(q.pipe.stderr)
|
scanner := bufio.NewScanner(q.pipe.stderr)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
m := scanner.Text()
|
m := scanner.Text()
|
||||||
q.handleQemuOutput(m)
|
|
||||||
q.Stderr += m + "\n"
|
q.Stderr += m + "\n"
|
||||||
q.Log.Trace().Str("stderr", m).Msg("qemu")
|
q.Log.Trace().Str("stderr", m).Msg("qemu")
|
||||||
}
|
}
|
||||||
@ -561,7 +475,6 @@ func (q System) Command(user, cmd string) (output string, err error) {
|
|||||||
scanner := bufio.NewScanner(stdout)
|
scanner := bufio.NewScanner(stdout)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
m := scanner.Text()
|
m := scanner.Text()
|
||||||
q.handleCommandsOutput(m)
|
|
||||||
output += m + "\n"
|
output += m + "\n"
|
||||||
flog.Trace().Str("stdout", m).Msg("qemu command")
|
flog.Trace().Str("stdout", m).Msg("qemu command")
|
||||||
}
|
}
|
||||||
@ -575,7 +488,6 @@ func (q System) Command(user, cmd string) (output string, err error) {
|
|||||||
scanner := bufio.NewScanner(stderr)
|
scanner := bufio.NewScanner(stderr)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
m := scanner.Text()
|
m := scanner.Text()
|
||||||
q.handleCommandsOutput(m)
|
|
||||||
output += m + "\n"
|
output += m + "\n"
|
||||||
// Note: it prints stderr as stdout
|
// Note: it prints stderr as stdout
|
||||||
flog.Trace().Str("stdout", m).Msg("qemu command")
|
flog.Trace().Str("stdout", m).Msg("qemu command")
|
||||||
|
Loading…
Reference in New Issue
Block a user