-
Notifications
You must be signed in to change notification settings - Fork 110
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wip: mocked LSF-driver as local queue
Broken WIP with LSF-commands translating into local driverr. driver.submit when mocked bsub does not return before the entire job is done
- Loading branch information
Showing
10 changed files
with
221 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#!/usr/bin/env bash | ||
exec "${PYTHON:-$(which python3)}" "$(dirname $0)/bjobs.py" "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import argparse | ||
import os | ||
import subprocess | ||
from datetime import datetime | ||
from enum import Enum | ||
from pathlib import Path | ||
from typing import List, Literal, Mapping, Optional | ||
|
||
from pydantic import BaseModel | ||
|
||
|
||
class LsfState(str, Enum): | ||
EXIT = ("EXIT",) | ||
DONE = ("DONE",) | ||
PEND = ("PEND",) | ||
RUN = ("RUN",) | ||
|
||
|
||
class Job(BaseModel): | ||
job_id: str | ||
name: str | ||
job_state: LsfState | ||
user_name: str = "username" | ||
queue: str = "normal" | ||
from_host: str = "localhost" | ||
exec_host: str = "localhost" | ||
submit_time: int = 0 | ||
|
||
|
||
class SQueueOutput(BaseModel): | ||
jobs: List[Job] | ||
|
||
|
||
def get_parser() -> argparse.ArgumentParser: | ||
parser = argparse.ArgumentParser(description="Get slurm jobs in LSF way") | ||
parser.add_argument("jobids", type=str, nargs="*") | ||
return parser | ||
|
||
|
||
def lsf_formatter(jobstats: List[Job]) -> str: | ||
string = "JOBID USER STAT QUEUE FROM_HOST EXEC_HOST JOB_NAME SUBMIT_TIME\n" | ||
for job in jobstats: | ||
submit_time = datetime.utcfromtimestamp((job.submit_time)) | ||
string += ( | ||
f"{str(job.job_id):<5s} {job.user_name:<8s} " | ||
f"{job.job_state:<4s} {job.queue:<8} " | ||
f"{job.from_host:<11s} {job.exec_host:<11s} {job.name:<8s} " | ||
f"{submit_time}\n" | ||
) | ||
return string | ||
|
||
|
||
def read(path: Path, default: Optional[str] = None) -> Optional[str]: | ||
return path.read_text().strip() if path.exists() else default | ||
|
||
|
||
def main() -> None: | ||
args = get_parser().parse_args() | ||
|
||
jobdir = Path(os.getenv("PYTEST_TMP_PATH", ".")) / "mock_jobs" | ||
|
||
jobs: List[Job] = [] | ||
for jobid in args.jobids: | ||
pid = read(jobdir / f"{jobid}.pid") | ||
returncode = read(jobdir / f"{jobid}.returncode") | ||
state = LsfState.PEND | ||
if pid is not None: | ||
state = LsfState.RUN | ||
else: | ||
state = LsfState.DONE if returncode == 0 else LsfState.EXIT | ||
jobs.append( | ||
Job( | ||
**{ | ||
"job_id": jobid, | ||
"name": read(jobdir / "f{jobid}.name") or "_", | ||
"job_state": state, | ||
} | ||
) | ||
) | ||
|
||
print(lsf_formatter(jobs)) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#!/usr/bin/env bash | ||
exec "${PYTHON:-$(which python3)}" "$(dirname $0)/bkill.py" "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import argparse | ||
import os | ||
import signal | ||
import sys | ||
from pathlib import Path | ||
|
||
|
||
def get_parser() -> argparse.ArgumentParser: | ||
parser = argparse.ArgumentParser(description="Kill jobs") | ||
parser.add_argument("jobids", type=str, nargs="+") | ||
return parser | ||
|
||
|
||
def main() -> None: | ||
args = get_parser().parse_args() | ||
|
||
jobdir = Path(os.getenv("PYTEST_TMP_PATH", ".")) / "mock_jobs" | ||
killsignal = signal.SIGTERM | ||
for jobid in args.jobids: | ||
pidfile = jobdir / f"{jobid}.pid" | ||
if not pidfile.exists(): | ||
print("fixme, job did not exist") # verify_me | ||
sys.exit(1) # verify_me | ||
pid = int(pidfile.read_text(encoding="utf-8").strip()) | ||
print(f"{pidfile=} {pid=}") | ||
os.kill(pid, killsignal) | ||
pidfile.unlink() | ||
print(f"killed a job={pid} with {killsignal=}") # verify with actual bkill | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/usr/bin/env bash | ||
exec "${PYTHON:-$(which python3)}" "$(dirname $0)/bsub.py" "$@" & | ||
disown -a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import argparse | ||
import os | ||
import random | ||
import subprocess | ||
from pathlib import Path | ||
|
||
|
||
def get_parser() -> argparse.ArgumentParser: | ||
parser = argparse.ArgumentParser(description="Submit jobs to Slurm via LSF syntax") | ||
|
||
parser.add_argument("-J", "--job_name", type=str) | ||
parser.add_argument("shellcode", type=str, nargs="+") | ||
return parser | ||
|
||
|
||
def main() -> None: | ||
args = get_parser().parse_args() | ||
|
||
jobdir = Path(os.getenv("PYTEST_TMP_PATH", ".")) / "mock_jobs" | ||
jobid = str( | ||
random.randint(1, 2**15) | ||
) # todo: ensure not in use to avoid flakyness | ||
jobdir.mkdir(exist_ok=True, parents=True) | ||
|
||
(jobdir / f"{jobid}.script").write_text(" ".join(args.shellcode)) | ||
(jobdir / f"{jobid}.name").write_text(args.job_name or "no_name") | ||
print(f"Job <{jobid}> is submitted to default queue <normal>.") | ||
|
||
# Actually run the requested command/script on localhost | ||
subprocess.Popen( | ||
[Path(__file__).parent / "runner", str(jobdir / jobid)], | ||
) | ||
print("exiting main in bsub.py") | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/usr/bin/env bash | ||
job=$1 | ||
|
||
function handle_sigterm { | ||
# Torque uses (256 + SIGNAL) as the returncode | ||
# Fix this to whatever LSF does.. | ||
# SIGTERM=15 | ||
echo "271" > "${job}.returncode" | ||
kill $child_pid | ||
exit 0 | ||
} | ||
|
||
trap handle_sigterm SIGTERM | ||
|
||
echo "$$" > "${job}.pid" | ||
sh "${job}.script" > "${job}.stdout" 2> "${job}.stderr" & | ||
child_pid=$! | ||
wait | ||
|
||
echo "runner finished sh code" | ||
echo "$?" > "${job}.returncode" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters