diff --git a/spug_api/apps/schedule/executors.py b/spug_api/apps/schedule/executors.py index 82affc0..33f2fb6 100644 --- a/spug_api/apps/schedule/executors.py +++ b/spug_api/apps/schedule/executors.py @@ -36,8 +36,9 @@ def host_executor(q, host, pkey, command): q.put((host.id, exit_code, round(time.time() - now, 3), out)) -def dispatch(command, targets): - close_old_connections() +def dispatch(command, targets, in_view=False): + if not in_view: + close_old_connections() threads, pkey, q = [], AppSetting.get('private_key'), Queue() for t in targets: if t == 'local': diff --git a/spug_api/apps/schedule/urls.py b/spug_api/apps/schedule/urls.py index 63e824d..8abdb36 100644 --- a/spug_api/apps/schedule/urls.py +++ b/spug_api/apps/schedule/urls.py @@ -7,6 +7,5 @@ from .views import * urlpatterns = [ path('', Schedule.as_view()), - path('/', ScheduleInfo.as_view()), - path('/history/', HistoryView.as_view()), + path('/', HistoryView.as_view()), ] diff --git a/spug_api/apps/schedule/views.py b/spug_api/apps/schedule/views.py index 4017e7d..9a888c6 100644 --- a/spug_api/apps/schedule/views.py +++ b/spug_api/apps/schedule/views.py @@ -5,6 +5,7 @@ from django.views.generic import View from django_redis import get_redis_connection from apscheduler.triggers.cron import CronTrigger from apps.schedule.models import Task, History +from apps.schedule.executors import dispatch from apps.host.models import Host from django.conf import settings from libs import json_response, JsonParser, Argument, human_datetime @@ -90,13 +91,34 @@ class Schedule(View): class HistoryView(View): def get(self, request, t_id): + task = Task.objects.filter(pk=t_id).first() + if not task: + return json_response(error='未找到指定任务') + h_id = request.GET.get('id') if h_id: - return json_response(self.fetch_detail(h_id)) + h_id = task.latest_id if h_id == 'latest' else h_id + return json_response(self._fetch_detail(h_id)) histories = History.objects.filter(task_id=t_id) return json_response([x.to_list() for x in histories]) - def fetch_detail(self, h_id): + def post(self, request, t_id): + task = Task.objects.filter(pk=t_id).first() + if not task: + return json_response(error='未找到指定任务') + data = dispatch(task.command, json.loads(task.targets), True) + score = 0 + for item in data: + score += 1 if item[1] else 0 + history = History.objects.create( + task_id=t_id, + status=2 if score == len(data) else 1 if score else 0, + run_time=human_datetime(), + output=json.dumps(data) + ) + return json_response(history.id) + + def _fetch_detail(self, h_id): record = History.objects.filter(pk=h_id).first() outputs = json.loads(record.output) host_ids = (x[0] for x in outputs if isinstance(x[0], int)) @@ -113,23 +135,3 @@ class HistoryView(View): 'output': out}) data['duration'] = f"{data['duration'] / len(outputs):.3f}" return data - - -class ScheduleInfo(View): - def get(self, request, h_id): - history = History.objects.filter(pk=h_id).first() - outputs = json.loads(history.output) - host_ids = (x[0] for x in outputs if isinstance(x[0], int)) - hosts_info = {x.id: x.name for x in Host.objects.filter(id__in=host_ids)} - data = {'run_time': history.run_time, 'success': 0, 'failure': 0, 'duration': 0, 'outputs': []} - for h_id, code, duration, out in outputs: - key = 'success' if code == 0 else 'failure' - data[key] += 1 - data['duration'] += duration - data['outputs'].append({ - 'name': hosts_info.get(h_id, '本机'), - 'code': code, - 'duration': duration, - 'output': out}) - data['duration'] = f"{data['duration'] / len(outputs):.3f}" - return json_response(data) diff --git a/spug_web/src/pages/schedule/Info.js b/spug_web/src/pages/schedule/Info.js index d3e461b..852ba8b 100644 --- a/spug_web/src/pages/schedule/Info.js +++ b/spug_web/src/pages/schedule/Info.js @@ -20,7 +20,7 @@ class ComForm extends React.Component { } componentDidMount() { - http.get(`/api/schedule/${store.record.id}/`) + http.get(`/api/schedule/${store.record.id}/?id=${store.record.h_id}`) .then(info => this.setState({info})) .finally(() => this.setState({loading: false})) } @@ -56,7 +56,7 @@ class ComForm extends React.Component { tab={item.code === 0 ? item.name : {item.name}}>
执行时间: {run_time}({moment(run_time).fromNow()})
运行耗时: {item.duration} s
-
返回状态: {item.code}
+
返回状态: {item.code}(非 0 则判定为失败)
执行输出:
{item.output}
))} diff --git a/spug_web/src/pages/schedule/Record.js b/spug_web/src/pages/schedule/Record.js index 5f48335..c3da6ba 100644 --- a/spug_web/src/pages/schedule/Record.js +++ b/spug_web/src/pages/schedule/Record.js @@ -21,7 +21,7 @@ class Record extends React.Component { } componentDidMount() { - http.get(`/api/schedule/${store.record.id}/history/`) + http.get(`/api/schedule/${store.record.id}/`) .then(res => this.setState({records: res})) .finally(() => this.setState({loading: false})) } @@ -36,7 +36,7 @@ class Record extends React.Component { render: info => {info['status_alias']} }, { title: '操作', - render: info => store.showInfo(info)}>详情 + render: info => store.showInfo(null, info.id)}>详情 }]; render() { diff --git a/spug_web/src/pages/schedule/Table.js b/spug_web/src/pages/schedule/Table.js index a750a0a..72d5347 100644 --- a/spug_web/src/pages/schedule/Table.js +++ b/spug_web/src/pages/schedule/Table.js @@ -24,10 +24,13 @@ class ComTable extends React.Component { moreMenus = (info) => ( - this.handleActive(info)}>{info.is_active ? '禁用' : '激活'} + this.handleTest(info)}>执行测试 - store.showRecord(info)}>历史 + this.handleActive(info)}>{info.is_active ? '禁用任务' : '激活任务'} + + + store.showRecord(info)}>历史记录 @@ -72,7 +75,7 @@ class ComTable extends React.Component { width: 180, render: info => ( - store.showInfo(info, true)}>详情 + store.showInfo(info)}>详情 store.showForm(info)}>编辑 @@ -113,6 +116,15 @@ class ComTable extends React.Component { }) }; + handleTest = (text) => { + Modal.confirm({ + title: '操作确认', + content: '立即执行该任务(不影响调度规则)?', + onOk: () => http.post(`/api/schedule/${text.id}/`) + .then(res => store.showInfo(text, res)) + }) + }; + render() { let data = store.records; if (store.f_status !== undefined) { diff --git a/spug_web/src/pages/schedule/store.js b/spug_web/src/pages/schedule/store.js index c85a29e..a4e9a80 100644 --- a/spug_web/src/pages/schedule/store.js +++ b/spug_web/src/pages/schedule/store.js @@ -41,10 +41,10 @@ class Store { this.record = info }; - showInfo = (info = {}, isTask) => { - const record = isTask ? {id: info['latest_id']} : info; - this.infoVisible = true; - this.record = record + showInfo = (info, h_id='latest') => { + if (info) this.record = info; + this.record.h_id = h_id; + this.infoVisible = true }; showRecord = (info) => {