// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: AGPL-3.0 package lsf import ( "bytes" "encoding/json" "fmt" "os" "os/exec" "strings" "git.arvados.org/arvados.git/sdk/go/arvados" "github.com/sirupsen/logrus" ) type bjobsEntry struct { ID string `json:"JOBID"` Name string `json:"JOB_NAME"` Stat string `json:"STAT"` PendReason string `json:"PEND_REASON"` } type lsfcli struct { logger logrus.FieldLogger // (for testing) if non-nil, call stubCommand() instead of // exec.Command() when running lsf command line programs. stubCommand func(string, ...string) *exec.Cmd } func (cli lsfcli) command(prog string, args ...string) *exec.Cmd { if f := cli.stubCommand; f != nil { return f(prog, args...) } else { return exec.Command(prog, args...) } } func (cli lsfcli) Bsub(script []byte, args []string, arv *arvados.Client) error { cli.logger.Infof("bsub command %q script %q", args, script) cmd := cli.command(args[0], args[1:]...) cmd.Env = append([]string(nil), os.Environ()...) cmd.Env = append(cmd.Env, "ARVADOS_API_HOST="+arv.APIHost) cmd.Env = append(cmd.Env, "ARVADOS_API_TOKEN="+arv.AuthToken) if arv.Insecure { cmd.Env = append(cmd.Env, "ARVADOS_API_HOST_INSECURE=1") } cmd.Stdin = bytes.NewReader(script) out, err := cmd.Output() cli.logger.WithField("stdout", string(out)).Infof("bsub finished") return errWithStderr(err) } func (cli lsfcli) Bjobs() ([]bjobsEntry, error) { cli.logger.Debugf("Bjobs()") cmd := cli.command("bjobs", "-u", "all", "-o", "jobid stat job_name pend_reason", "-json") buf, err := cmd.Output() if err != nil { return nil, errWithStderr(err) } var resp struct { Records []bjobsEntry `json:"RECORDS"` } err = json.Unmarshal(buf, &resp) return resp.Records, err } func (cli lsfcli) Bkill(id string) error { cli.logger.Infof("Bkill(%s)", id) cmd := cli.command("bkill", id) buf, err := cmd.CombinedOutput() if err == nil || strings.Index(string(buf), "already finished") >= 0 { return nil } else { return fmt.Errorf("%s (%q)", err, buf) } } func errWithStderr(err error) error { if err, ok := err.(*exec.ExitError); ok { return fmt.Errorf("%s (%q)", err, err.Stderr) } return err }