nlttask 1.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- funtask/__init__.py +1 -0
- funtask/__main__.py +4 -0
- funtask/models/__init__.py +1 -0
- funtask/models/base.py +6 -0
- funtask/models/task_model.py +27 -0
- funtask/task/__init__.py +0 -0
- funtask/task/manager.py +50 -0
- funtask/task/submit.py +84 -0
- funtask/web/app.py +90 -0
- nlttask-1.0.2.dist-info/METADATA +15 -0
- nlttask-1.0.2.dist-info/RECORD +13 -0
- nlttask-1.0.2.dist-info/WHEEL +5 -0
- nlttask-1.0.2.dist-info/top_level.txt +1 -0
funtask/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .models import Task
|
funtask/__main__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .base import Task
|
funtask/models/base.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Text
|
|
3
|
+
from sqlalchemy.ext.declarative import declarative_base
|
|
4
|
+
from sqlalchemy.orm import sessionmaker
|
|
5
|
+
|
|
6
|
+
Base = declarative_base()
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TaskModel(Base):
|
|
10
|
+
__tablename__ = "tasks"
|
|
11
|
+
|
|
12
|
+
id = Column(Integer, primary_key=True)
|
|
13
|
+
task_dir = Column(String(255), nullable=False)
|
|
14
|
+
status = Column(
|
|
15
|
+
String(50), default="pending"
|
|
16
|
+
) # pending, running, completed, failed
|
|
17
|
+
created_at = Column(DateTime, default=datetime.now)
|
|
18
|
+
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
|
|
19
|
+
description = Column(Text, nullable=True)
|
|
20
|
+
task_type = Column(String(50)) # slurm, cpp, etc.
|
|
21
|
+
output = Column(Text, nullable=True)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# 创建数据库连接
|
|
25
|
+
engine = create_engine("sqlite:///tasks.db", echo=True)
|
|
26
|
+
Base.metadata.create_all(engine)
|
|
27
|
+
Session = sessionmaker(bind=engine)
|
funtask/task/__init__.py
ADDED
|
File without changes
|
funtask/task/manager.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import List, Optional
|
|
3
|
+
from ..models.task_model import TaskModel, Session
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TaskManager:
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self.session = Session()
|
|
9
|
+
|
|
10
|
+
def create_task(
|
|
11
|
+
self, task_dir: str, task_type: str, description: Optional[str] = None
|
|
12
|
+
) -> TaskModel:
|
|
13
|
+
task = TaskModel(
|
|
14
|
+
task_dir=task_dir,
|
|
15
|
+
task_type=task_type,
|
|
16
|
+
description=description,
|
|
17
|
+
status="pending",
|
|
18
|
+
)
|
|
19
|
+
self.session.add(task)
|
|
20
|
+
self.session.commit()
|
|
21
|
+
return task
|
|
22
|
+
|
|
23
|
+
def get_task(self, task_id: int) -> Optional[TaskModel]:
|
|
24
|
+
return self.session.query(TaskModel).filter(TaskModel.id == task_id).first()
|
|
25
|
+
|
|
26
|
+
def get_all_tasks(self) -> List[TaskModel]:
|
|
27
|
+
return self.session.query(TaskModel).order_by(TaskModel.created_at.desc()).all()
|
|
28
|
+
|
|
29
|
+
def update_task_status(
|
|
30
|
+
self, task_id: int, status: str, output: Optional[str] = None
|
|
31
|
+
) -> Optional[TaskModel]:
|
|
32
|
+
task = self.get_task(task_id)
|
|
33
|
+
if task:
|
|
34
|
+
task.status = status
|
|
35
|
+
task.updated_at = datetime.now()
|
|
36
|
+
if output:
|
|
37
|
+
task.output = output
|
|
38
|
+
self.session.commit()
|
|
39
|
+
return task
|
|
40
|
+
|
|
41
|
+
def delete_task(self, task_id: int) -> bool:
|
|
42
|
+
task = self.get_task(task_id)
|
|
43
|
+
if task:
|
|
44
|
+
self.session.delete(task)
|
|
45
|
+
self.session.commit()
|
|
46
|
+
return True
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
def __del__(self):
|
|
50
|
+
self.session.close()
|
funtask/task/submit.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""
|
|
2
|
+
#!/bin/bash
|
|
3
|
+
task_root='/work/home/liuc12/workbench'
|
|
4
|
+
timestamp=$(date +"%Y%m%d%H%M%S")
|
|
5
|
+
task_dir="$task_root/task_$timestamp"
|
|
6
|
+
|
|
7
|
+
mkdir "$task_dir"
|
|
8
|
+
cp -r *.cpp *.h *.sh *.slurm *.f90 *.dat $task_dir 2>/dev/null
|
|
9
|
+
cd "$task_dir"
|
|
10
|
+
pwd
|
|
11
|
+
#ls -al
|
|
12
|
+
sbatch config.slurm
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
from datetime import datetime
|
|
17
|
+
|
|
18
|
+
from funbuild.shell import run_shell
|
|
19
|
+
from nltlog import getLogger
|
|
20
|
+
|
|
21
|
+
from .manager import TaskManager
|
|
22
|
+
|
|
23
|
+
logger = getLogger("funbuild")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def submit_task():
|
|
27
|
+
task_dir = os.path.join(
|
|
28
|
+
os.environ["HOME"], "/workbench", datetime.now().strftime("%Y%m%d%H%M%S")
|
|
29
|
+
)
|
|
30
|
+
logger.info(f"任务主目录:{task_dir}")
|
|
31
|
+
os.makedirs(task_dir, exist_ok=True)
|
|
32
|
+
|
|
33
|
+
# 创建任务管理器实例
|
|
34
|
+
task_manager = TaskManager()
|
|
35
|
+
task_type = None
|
|
36
|
+
description = None
|
|
37
|
+
|
|
38
|
+
logger.info(f"step1: 复制文件到任务主目录:{task_dir}")
|
|
39
|
+
run_shell(f"cp -r *.cpp *.h *.sh *.slurm *.f90 *.dat {task_dir} 2>/dev/null")
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
if os.path.exists("config.slurm"):
|
|
43
|
+
task_type = "slurm"
|
|
44
|
+
description = "SLURM cluster task"
|
|
45
|
+
logger.info("step2: 检测到config.slurm文件,提交任务")
|
|
46
|
+
# 创建任务记录
|
|
47
|
+
task = task_manager.create_task(task_dir, task_type, description)
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
output = run_shell(f"cd {task_dir} && sbatch config.slurm")
|
|
51
|
+
task_manager.update_task_status(task.id, "running", output)
|
|
52
|
+
except Exception as e:
|
|
53
|
+
task_manager.update_task_status(task.id, "failed", str(e))
|
|
54
|
+
raise e
|
|
55
|
+
|
|
56
|
+
elif os.path.exists("main.cpp"):
|
|
57
|
+
task_type = "cpp"
|
|
58
|
+
description = "Local C++ compilation and execution"
|
|
59
|
+
# 创建任务记录
|
|
60
|
+
task = task_manager.create_task(task_dir, task_type, description)
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
logger.info("step2: 检测到main.cpp文件,编译")
|
|
64
|
+
compile_output = run_shell(f"cd {task_dir} && g++ main.cpp -o task.app")
|
|
65
|
+
logger.info("step3: 编译完成,开始执行")
|
|
66
|
+
execution_output = run_shell(f"cd {task_dir} && ./task.app")
|
|
67
|
+
task_manager.update_task_status(
|
|
68
|
+
task.id,
|
|
69
|
+
"completed",
|
|
70
|
+
f"Compilation: {compile_output}\nExecution: {execution_output}",
|
|
71
|
+
)
|
|
72
|
+
except Exception as e:
|
|
73
|
+
task_manager.update_task_status(task.id, "failed", str(e))
|
|
74
|
+
raise e
|
|
75
|
+
|
|
76
|
+
logger.info("任务提交完成")
|
|
77
|
+
return task_dir
|
|
78
|
+
except Exception as e:
|
|
79
|
+
logger.error(f"任务执行失败: {str(e)}")
|
|
80
|
+
raise e
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
if __name__ == "__main__":
|
|
84
|
+
submit_task()
|
funtask/web/app.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
from nicegui import ui
|
|
2
|
+
from ..task.manager import TaskManager
|
|
3
|
+
from ..task.submit import submit_task
|
|
4
|
+
|
|
5
|
+
task_manager = TaskManager()
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def create_task_list():
|
|
9
|
+
with ui.card().classes("w-full"):
|
|
10
|
+
ui.label("任务列表").classes("text-h6")
|
|
11
|
+
|
|
12
|
+
# 创建任务表格
|
|
13
|
+
columns = [
|
|
14
|
+
{"name": "id", "label": "ID", "field": "id"},
|
|
15
|
+
{"name": "task_dir", "label": "任务目录", "field": "task_dir"},
|
|
16
|
+
{"name": "status", "label": "状态", "field": "status"},
|
|
17
|
+
{"name": "task_type", "label": "任务类型", "field": "task_type"},
|
|
18
|
+
{"name": "created_at", "label": "创建时间", "field": "created_at"},
|
|
19
|
+
{"name": "description", "label": "描述", "field": "description"},
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
tasks = task_manager.get_all_tasks()
|
|
23
|
+
rows = [
|
|
24
|
+
{
|
|
25
|
+
"id": task.id,
|
|
26
|
+
"task_dir": task.task_dir,
|
|
27
|
+
"status": task.status,
|
|
28
|
+
"task_type": task.task_type,
|
|
29
|
+
"created_at": task.created_at.strftime("%Y-%m-%d %H:%M:%S"),
|
|
30
|
+
"description": task.description,
|
|
31
|
+
}
|
|
32
|
+
for task in tasks
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
table = ui.table(columns=columns, rows=rows, row_key="id").classes("w-full")
|
|
36
|
+
|
|
37
|
+
async def refresh_table():
|
|
38
|
+
tasks = task_manager.get_all_tasks()
|
|
39
|
+
rows = [
|
|
40
|
+
{
|
|
41
|
+
"id": task.id,
|
|
42
|
+
"task_dir": task.task_dir,
|
|
43
|
+
"status": task.status,
|
|
44
|
+
"task_type": task.task_type,
|
|
45
|
+
"created_at": task.created_at.strftime("%Y-%m-%d %H:%M:%S"),
|
|
46
|
+
"description": task.description,
|
|
47
|
+
}
|
|
48
|
+
for task in tasks
|
|
49
|
+
]
|
|
50
|
+
table.rows = rows
|
|
51
|
+
|
|
52
|
+
async def delete_task(task_id: int):
|
|
53
|
+
if task_manager.delete_task(task_id):
|
|
54
|
+
ui.notify(f"任务 {task_id} 已删除")
|
|
55
|
+
await refresh_table()
|
|
56
|
+
else:
|
|
57
|
+
ui.notify(f"删除任务 {task_id} 失败", type="negative")
|
|
58
|
+
|
|
59
|
+
async def view_task_output(task_id: int):
|
|
60
|
+
task = task_manager.get_task(task_id)
|
|
61
|
+
if task and task.output:
|
|
62
|
+
with ui.dialog() as dialog, ui.card():
|
|
63
|
+
ui.label(f"任务 {task_id} 输出").classes("text-h6")
|
|
64
|
+
ui.textarea(value=task.output, readonly=True).classes("w-full")
|
|
65
|
+
ui.button("关闭", on_click=dialog.close)
|
|
66
|
+
dialog.open()
|
|
67
|
+
else:
|
|
68
|
+
ui.notify("没有可用的输出", type="warning")
|
|
69
|
+
|
|
70
|
+
# 添加操作按钮
|
|
71
|
+
with ui.row():
|
|
72
|
+
ui.button("刷新", on_click=refresh_table).classes("mr-2")
|
|
73
|
+
for row in rows:
|
|
74
|
+
with ui.row():
|
|
75
|
+
ui.button(
|
|
76
|
+
"查看输出", on_click=lambda r=row: view_task_output(r["id"])
|
|
77
|
+
).classes("mr-2")
|
|
78
|
+
ui.button(
|
|
79
|
+
"删除", on_click=lambda r=row: delete_task(r["id"]), color="red"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@ui.page("/")
|
|
84
|
+
def main_page():
|
|
85
|
+
ui.label("任务管理系统").classes("text-h4 q-mb-md")
|
|
86
|
+
create_task_list()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def start_web_server(host="0.0.0.0", port=8080):
|
|
90
|
+
ui.run(host=host, port=port, title="任务管理系统")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nlttask
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: nlttask
|
|
5
|
+
Author-email: 牛哥 <niuliangtao@qq.com>, farfarfun <farfarfun@qq.com>
|
|
6
|
+
Maintainer-email: 牛哥 <niuliangtao@qq.com>, farfarfun <farfarfun@qq.com>
|
|
7
|
+
Project-URL: Organization, https://github.com/farfarfun
|
|
8
|
+
Project-URL: Repository, https://github.com/farfarfun/funtask
|
|
9
|
+
Project-URL: Releases, https://github.com/farfarfun/funtask/releases
|
|
10
|
+
Requires-Python: >=3.8
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: nltlog>=1.1.3
|
|
13
|
+
Requires-Dist: sqlalchemy>=2.0.50
|
|
14
|
+
|
|
15
|
+
# notetask
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
funtask/__init__.py,sha256=1An9ji9Yqij_SZdHEcVm8V_HRgpd_D9QbAro9bGklVw,25
|
|
2
|
+
funtask/__main__.py,sha256=vPcdHTqX2krxMpQfa58Vei7_lzQcGbOZiSxr5Iv7_hY,89
|
|
3
|
+
funtask/models/__init__.py,sha256=WanozeTJqTPVIpaXQzB5lvDI9XJLPoioyEKWB9RYwUQ,23
|
|
4
|
+
funtask/models/base.py,sha256=1mPWWKfwU4upK1xUshwcSCFHecTWpbZ86-FJvOYDzd4,116
|
|
5
|
+
funtask/models/task_model.py,sha256=Q4W30WfQo0eKorR88SFHskwkRgXBiGluqUcGlRXf7r4,911
|
|
6
|
+
funtask/task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
funtask/task/manager.py,sha256=KzO9vUiPBsMTTzfO_WrdWxU56pC3AffjhDi5t8JomYU,1498
|
|
8
|
+
funtask/task/submit.py,sha256=rILZLceHf0t8THZbL0eXzfUxvgPexDy3u4OA4y9R6e4,2681
|
|
9
|
+
funtask/web/app.py,sha256=onrKVp290rVNqs3_0vjGfb7tfn6NoUSX3IuTYYo7_nk,3323
|
|
10
|
+
nlttask-1.0.2.dist-info/METADATA,sha256=_jt-VcvjA1zRt2RLZj8XgHUCvyDxz8VbAvEGZ5PPl5I,541
|
|
11
|
+
nlttask-1.0.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
12
|
+
nlttask-1.0.2.dist-info/top_level.txt,sha256=svcT_-fhz7u77X8wJYILLorz0fp2LjdYljx7QGa6ieg,8
|
|
13
|
+
nlttask-1.0.2.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
funtask
|