[Update] 修改日志

pull/1156/head
ibuler 2018-04-01 23:45:37 +08:00
parent 09fc2776df
commit df80e8047a
21 changed files with 373 additions and 121 deletions

View File

@ -1,7 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import os
import json import json
import uuid
from django.core.cache import cache
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.views import Response from rest_framework.views import Response
from ldap3 import Server, Connection from ldap3 import Server, Connection
@ -11,6 +14,7 @@ from django.conf import settings
from .permissions import IsSuperUser, IsAppUser from .permissions import IsSuperUser, IsAppUser
from .serializers import MailTestSerializer, LDAPTestSerializer from .serializers import MailTestSerializer, LDAPTestSerializer
from .const import FILE_END_GUARD
class MailTestingAPI(APIView): class MailTestingAPI(APIView):
@ -105,3 +109,30 @@ class DjangoSettingsAPI(APIView):
if i.isupper(): if i.isupper():
configs[i] = str(getattr(settings, i)) configs[i] = str(getattr(settings, i))
return Response(configs) return Response(configs)
class FileTailApi(APIView):
permission_classes = (IsSuperUser,)
default_buff_size = 1024 * 10
end = False
buff_size = None
def get(self, request, *args, **kwargs):
file_path = request.query_params.get("file")
self.buff_size = request.query_params.get('buffer') or self.default_buff_size
mark = request.query_params.get("mark") or str(uuid.uuid4())
if not os.path.isfile(file_path):
return Response({"data": _("Waiting ...")}, status=203)
with open(file_path, 'r') as f:
offset = cache.get(mark, 0)
f.seek(offset)
data = f.read(self.buff_size).replace('\n', '\r\n')
mark = str(uuid.uuid4())
cache.set(mark, f.tell(), 5)
if FILE_END_GUARD in data:
data = data.replace(FILE_END_GUARD, '')
self.end = True
return Response({"data": data, 'end': self.end, 'mark': mark})

View File

@ -5,7 +5,7 @@ import json
from functools import wraps from functools import wraps
from celery import Celery, subtask from celery import Celery, subtask
from celery.signals import worker_ready, worker_shutdown from celery.signals import worker_ready, worker_shutdown, task_prerun, task_postrun
from django.db.utils import ProgrammingError, OperationalError from django.db.utils import ProgrammingError, OperationalError
from .utils import get_logger from .utils import get_logger
@ -199,3 +199,16 @@ def after_app_shutdown(sender=None, headers=None, body=None, **kwargs):
', '.join(__AFTER_APP_SHUTDOWN_CLEAN_TASKS)) ', '.join(__AFTER_APP_SHUTDOWN_CLEAN_TASKS))
) )
PeriodicTask.objects.filter(name__in=__AFTER_APP_SHUTDOWN_CLEAN_TASKS).delete() PeriodicTask.objects.filter(name__in=__AFTER_APP_SHUTDOWN_CLEAN_TASKS).delete()
@task_prerun.connect
def pre_run_task_signal_handler(sender, task, *args, **kwargs):
print("Sender: {}".format(sender))
print("Task: {}".format(task))
@task_postrun.connect
def post_run_task_signal_handler(sender, task, *args, **kwargs):
print("Sender: {}".format(sender))
print("Task: {}".format(task))

View File

@ -5,3 +5,4 @@ from django.utils.translation import ugettext as _
create_success_msg = _("<b>%(name)s</b> was created successfully") create_success_msg = _("<b>%(name)s</b> was created successfully")
update_success_msg = _("<b>%(name)s</b> was updated successfully") update_success_msg = _("<b>%(name)s</b> was updated successfully")
FILE_END_GUARD = ">>> Content End <<<"

View File

@ -0,0 +1,96 @@
{% load static %}
<head>
<title>term.js</title>
<script src="{% static 'js/jquery-2.1.1.js' %}"></script>
<style>
html {
background: #000;
}
h1 {
margin-bottom: 20px;
font: 20px/1.5 sans-serif;
}
.terminal {
float: left;
font-family: 'Monaco', 'Consolas', "DejaVu Sans Mono", "Liberation Mono", monospace;
font-size: 12px;
color: #f0f0f0;
background-color: #555;
padding: 20px 20px 20px;
}
.terminal-cursor {
color: #000;
background: #f0f0f0;
}
</style>
</head>
<div class="container">
<div id="term">
</div>
</div>
<script src="{% static 'js/term.js' %}"></script>
<script>
var rowHeight = 1;
var colWidth = 1;
var mark = '';
var url = "{% url 'api-common:tail-file' %}?file={{ file_path }}";
var term;
var end = false;
var error = false;
var interval = 200;
function calWinSize() {
var t = $('.terminal');
rowHeight = 1.00 * t.height() / 24;
colWidth = 1.00 * t.width() / 80;
}
function resize() {
var rows = Math.floor(window.innerHeight / rowHeight) - 2;
var cols = Math.floor(window.innerWidth / colWidth) - 10;
term.resize(cols, rows);
}
function requestAndWrite() {
if (!end) {
$.ajax({
url: url + '&mark=' + mark,
method: "GET",
contentType: "application/json; charset=utf-8"
}).done(function(data, textStatue, jqXHR) {
if (jqXHR.status === 203) {
error = true;
term.write('.');
interval = 500;
}
if (jqXHR.status === 200){
term.write(data.data);
mark = data.mark;
if (data.end){
end = true
}
}
})
}
}
$(document).ready(function () {
term = new Terminal({
cols: 80,
rows: 24,
useStyle: true,
screenKeys: false,
convertEol: false,
cursorBlink: false
});
term.open();
term.on('data', function (data) {
term.write(data.replace('\r', '\r\n'))
});
calWinSize();
resize();
$('.terminal').detach().appendTo('#term');
setInterval(function () {
requestAndWrite()
}, interval)
});
</script>

View File

@ -10,4 +10,5 @@ urlpatterns = [
url(r'^v1/mail/testing/$', api.MailTestingAPI.as_view(), name='mail-testing'), url(r'^v1/mail/testing/$', api.MailTestingAPI.as_view(), name='mail-testing'),
url(r'^v1/ldap/testing/$', api.LDAPTestingAPI.as_view(), name='ldap-testing'), url(r'^v1/ldap/testing/$', api.LDAPTestingAPI.as_view(), name='ldap-testing'),
url(r'^v1/django-settings/$', api.DjangoSettingsAPI.as_view(), name='django-settings'), url(r'^v1/django-settings/$', api.DjangoSettingsAPI.as_view(), name='django-settings'),
url(r'^v1/tail-file/$', api.FileTailApi.as_view(), name='tail-file'),
] ]

View File

@ -11,4 +11,7 @@ urlpatterns = [
url(r'^email/$', views.EmailSettingView.as_view(), name='email-setting'), url(r'^email/$', views.EmailSettingView.as_view(), name='email-setting'),
url(r'^ldap/$', views.LDAPSettingView.as_view(), name='ldap-setting'), url(r'^ldap/$', views.LDAPSettingView.as_view(), name='ldap-setting'),
url(r'^terminal/$', views.TerminalSettingView.as_view(), name='terminal-setting'), url(r'^terminal/$', views.TerminalSettingView.as_view(), name='terminal-setting'),
url(r'^tail-file/$', views.TailFileView.as_view(), name='tail-file'),
url(r'^celery/task/log/$', views.CeleryTaskLogView.as_view(), name='celery-task-log'),
] ]

View File

@ -1,5 +1,7 @@
from django.views.generic import TemplateView
from django.shortcuts import render, redirect from django.core.cache import cache
from django.views.generic import TemplateView, View
from django.shortcuts import render, redirect, Http404, reverse
from django.contrib import messages from django.contrib import messages
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.conf import settings from django.conf import settings
@ -120,3 +122,34 @@ class TerminalSettingView(AdminUserRequiredMixin, TemplateView):
context.update({"form": form}) context.update({"form": form})
return render(request, self.template_name, context) return render(request, self.template_name, context)
class TailFileView(AdminUserRequiredMixin, TemplateView):
template_name = 'common/tail_file.html'
def get_context_data(self, **kwargs):
file_path = self.request.GET.get("file")
context = super().get_context_data(**kwargs)
context.update({"file_path": file_path})
return context
class CeleryTaskLogView(AdminUserRequiredMixin, TemplateView):
template_name = 'common/tail_file.html'
task_log_path = None
def get(self, request, *args, **kwargs):
task = self.request.GET.get('task')
if not task:
raise Http404("Not found task")
self.task_log_path = cache.get(task)
if not self.task_log_path:
raise Http404("Not found task log file")
return super().get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({
'file_path': self.task_log_path
})
return context

View File

@ -1,19 +1,23 @@
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
import uuid import uuid
import re import os
from django.core.cache import cache from django.core.cache import cache
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext as _
from rest_framework import viewsets, generics from rest_framework import viewsets, generics
from rest_framework.generics import RetrieveAPIView from rest_framework.views import APIView
from rest_framework.views import Response from rest_framework.views import Response
from .hands import IsSuperUser from .hands import IsSuperUser
from common.const import FILE_END_GUARD
from .models import Task, AdHoc, AdHocRunHistory from .models import Task, AdHoc, AdHocRunHistory
from .serializers import TaskSerializer, AdHocSerializer, AdHocRunHistorySerializer from .serializers import TaskSerializer, AdHocSerializer, AdHocRunHistorySerializer
from .tasks import run_ansible_task from .tasks import run_ansible_task
class TaskViewSet(viewsets.ModelViewSet): class TaskViewSet(viewsets.ModelViewSet):
queryset = Task.objects.all() queryset = Task.objects.all()
serializer_class = TaskSerializer serializer_class = TaskSerializer
@ -27,8 +31,8 @@ class TaskRun(generics.RetrieveAPIView):
def retrieve(self, request, *args, **kwargs): def retrieve(self, request, *args, **kwargs):
task = self.get_object() task = self.get_object()
run_ansible_task.delay(str(task.id)) t = run_ansible_task.delay(str(task.id))
return Response({"msg": "start"}) return Response({"task": t.id})
class AdHocViewSet(viewsets.ModelViewSet): class AdHocViewSet(viewsets.ModelViewSet):
@ -63,24 +67,28 @@ class AdHocRunHistorySet(viewsets.ModelViewSet):
return self.queryset return self.queryset
class AdHocHistoryOutputAPI(RetrieveAPIView): class LogFileViewApi(APIView):
queryset = AdHocRunHistory.objects.all()
permission_classes = (IsSuperUser,) permission_classes = (IsSuperUser,)
buff_size = 1024 * 10 buff_size = 1024 * 10
end = False end = False
def retrieve(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
history = self.get_object() file_path = request.query_params.get("file")
mark = request.query_params.get("mark") or str(uuid.uuid4()) mark = request.query_params.get("mark") or str(uuid.uuid4())
with open(history.log_path, 'r') as f: if not os.path.isfile(file_path):
print(file_path)
return Response({"error": _("Log file not found")}, status=204)
with open(file_path, 'r') as f:
offset = cache.get(mark, 0) offset = cache.get(mark, 0)
f.seek(offset) f.seek(offset)
data = f.read(self.buff_size).replace('\n', '\r\n') data = f.read(self.buff_size).replace('\n', '\r\n')
print(repr(data))
mark = str(uuid.uuid4()) mark = str(uuid.uuid4())
cache.set(mark, f.tell(), 5) cache.set(mark, f.tell(), 5)
if history.is_finished and data == '': if FILE_END_GUARD in data:
data.replace(FILE_END_GUARD, '')
self.end = True self.end = True
return Response({"data": data, 'end': self.end, 'mark': mark}) return Response({"data": data, 'end': self.end, 'mark': mark})

View File

@ -6,6 +6,7 @@ import os
import time import time
import datetime import datetime
from celery import current_task
from django.db import models from django.db import models
from django.conf import settings from django.conf import settings
from django.utils import timezone from django.utils import timezone
@ -211,11 +212,20 @@ class AdHoc(models.Model):
return self._run_only() return self._run_only()
def _run_and_record(self): def _run_and_record(self):
history = AdHocRunHistory(adhoc=self, task=self.task)
time_start = time.time()
try: try:
with open(history.log_path, 'w') as f: hid = current_task.request.id
raw, summary = self._run_only(file_obj=f) except AttributeError:
hid = str(uuid.uuid4())
history = AdHocRunHistory(id=hid, adhoc=self, task=self.task)
time_start = time.time()
# f = open(history.log_path, 'w')
try:
date_start = timezone.now().strftime('%Y-%m-%d %H:%M:%S')
# f.write("{} {}\r\n\r\n".format(date_start, self.task.name))
raw, summary = self._run_only()
# raw, summary = self._run_only(file_obj=f)
date_end = timezone.now().strftime('%Y-%m-%d %H:%M:%S')
# f.write("\r\n{} Task finish\r\n".format(date_end))
history.is_finished = True history.is_finished = True
if summary.get('dark'): if summary.get('dark'):
history.is_success = False history.is_success = False
@ -227,6 +237,7 @@ class AdHoc(models.Model):
except Exception as e: except Exception as e:
return {}, {"dark": {"all": str(e)}, "contacted": []} return {}, {"dark": {"all": str(e)}, "contacted": []}
finally: finally:
# f.close()
history.date_finished = timezone.now() history.date_finished = timezone.now()
history.timedelta = time.time() - time_start history.timedelta = time.time() - time_start
history.save() history.save()

View File

@ -1,6 +1,7 @@
# coding: utf-8 # coding: utf-8
from celery import shared_task, subtask from celery import shared_task, subtask
from common.utils import get_logger, get_object_or_none from common.utils import get_logger, get_object_or_none
from .models import Task from .models import Task
@ -12,14 +13,13 @@ def rerun_task():
@shared_task @shared_task
def run_ansible_task(task_id, callback=None, **kwargs): def run_ansible_task(tid, callback=None, **kwargs):
""" """
:param task_id: is the tasks serialized data :param tid: is the tasks serialized data
:param callback: callback function name :param callback: callback function name
:return: :return:
""" """
task = get_object_or_none(Task, id=tid)
task = get_object_or_none(Task, id=task_id)
if task: if task:
result = task.run() result = task.run()
if callback is not None: if callback is not None:

View File

@ -82,7 +82,8 @@ function initTable() {
select: [], select: [],
columnDefs: [ columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) { {targets: 1, createdCell: function (td, cellData, rowData) {
$(td).html(cellData); var d = new Date(cellData);
$(td).html(d);
}}, }},
{targets: 2, createdCell: function (td, cellData) { {targets: 2, createdCell: function (td, cellData) {
var total = "<span>" + cellData.total + "</span>"; var total = "<span>" + cellData.total + "</span>";

View File

@ -18,6 +18,9 @@
<li class="active"> <li class="active">
<a href="{% url 'ops:adhoc-history-detail' pk=object.pk %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Run history detail' %} </a> <a href="{% url 'ops:adhoc-history-detail' pk=object.pk %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Run history detail' %} </a>
</li> </li>
<li>
<a href="{% url 'ops:adhoc-history-output' pk=object.pk %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'History output' %} </a>
</li>
</ul> </ul>
</div> </div>
<div class="tab-content"> <div class="tab-content">

View File

@ -1,93 +1,37 @@
{% extends 'base.html' %}
{% load static %} {% load static %}
<!doctype html> {% load i18n %}
<html>
<head> {% block custom_head_css_js %}
<title>term.js</title> <link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet">
<script src="{% static 'js/jquery-2.1.1.js' %}"></script> <link href="{% static "css/plugins/sweetalert/sweetalert.css" %}" rel="stylesheet">
<style> <script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
html { <script src="{% static "js/plugins/sweetalert/sweetalert.min.js" %}"></script>
background: #000;
}
h1 {
margin-bottom: 20px;
font: 20px/1.5 sans-serif;
}
.terminal {
float: left;
font-family: 'Monaco', 'Consolas', "DejaVu Sans Mono", "Liberation Mono", monospace;
font-size: 14px;
color: #f0f0f0;
background-color: #555;
padding: 20px 20px 20px;
}
.terminal-cursor {
color: #000;
background: #f0f0f0;
}
</style>
</head> </head>
<body> {% endblock %}
<div class="container"> {% block content %}
<div id="term"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="panel-options">
<ul class="nav nav-tabs">
<li>
<a href="{% url 'ops:adhoc-history-detail' pk=object.pk %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Run history detail' %} </a>
</li>
<li class="active">
<a href="{% url 'ops:adhoc-history-output' pk=object.pk %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'History output' %} </a>
</li>
</ul>
</div>
<div class="tab-content" style="height: 800px">
<iframe src="{% url 'ops:adhoc-history-output-alone' pk=object.pk %}" width="100%" height="100%">
</iframe>
</div> </div>
</div> </div>
</body> </div>
</div>
</div>
{% endblock %}
<script src="{% static 'js/term.js' %}"></script>
<script>
var rowHeight = 1;
var colWidth = 1;
var mark = '';
var url = "{% url 'api-ops:history-output' pk=object.id %}";
var term;
var end = false;
function calWinSize() {
var t = $('.terminal');
console.log(t.height());
rowHeight = 1.00 * t.height() / 24;
colWidth = 1.00 * t.width() / 80;
}
function resize() {
var rows = Math.floor(window.innerHeight / rowHeight) - 2;
var cols = Math.floor(window.innerWidth / colWidth) - 5;
term.resize(cols, rows);
}
function requestAndWrite() {
if (!end) {
$.ajax({
url: url + '?mark=' + mark,
method: "GET",
contentType: "application/json; charset=utf-8"
}).done(function(data, textStatue, jqXHR) {
term.write(data.data);
mark = data.mark;
if (data.end){
end = true
}
}).fail(function(jqXHR, textStatus, errorThrown) {
});
}
}
$(document).ready(function () {
term = new Terminal({
cols: 80,
rows: 24,
useStyle: true,
screenKeys: false
});
term.open();
term.on('data', function (data) {
term.write(data.replace('\r', '\r\n'))
});
calWinSize();
resize();
$('.terminal').detach().appendTo('#term');
term.write('\x1b[31mWelcome to term.js!\x1b[m\r\n');
setInterval(function () {
requestAndWrite()
}, 100)
});
</script>
</html>

View File

@ -0,0 +1,94 @@
{% load static %}
<head>
<title>term.js</title>
<script src="{% static 'js/jquery-2.1.1.js' %}"></script>
<style>
html {
background: #000;
}
h1 {
margin-bottom: 20px;
font: 20px/1.5 sans-serif;
}
.terminal {
float: left;
font-family: 'Monaco', 'Consolas', "DejaVu Sans Mono", "Liberation Mono", monospace;
font-size: 12px;
color: #f0f0f0;
background-color: #555;
padding: 20px 20px 20px;
}
.terminal-cursor {
color: #000;
background: #f0f0f0;
}
</style>
</head>
<div class="container">
<div id="term">
</div>
</div>
<script src="{% static 'js/term.js' %}"></script>
<script>
var rowHeight = 1;
var colWidth = 1;
var mark = '';
var url = "{% url 'api-ops:history-output' pk=object.id %}";
var term;
var end = false;
var has_error = false;
function calWinSize() {
var t = $('.terminal');
rowHeight = 1.00 * t.height() / 24;
colWidth = 1.00 * t.width() / 80;
}
function resize() {
var rows = Math.floor(window.innerHeight / rowHeight) - 2;
var cols = Math.floor(window.innerWidth / colWidth) - 5;
term.resize(cols, rows);
}
function requestAndWrite() {
if (!end) {
$.ajax({
url: url + '?mark=' + mark,
method: "GET",
contentType: "application/json; charset=utf-8"
}).done(function(data, textStatue, jqXHR) {
term.write(data.data);
mark = data.mark;
if (data.end){
end = true
}
}).fail(function(jqXHR, textStatus, errorThrown) {
if (!has_error) {
var error = jqXHR.responseJSON.error;
term.write('\x1b[31m' + error + '\x1b[m\r\n');
has_error = true
}
});
}
}
$(document).ready(function () {
term = new Terminal({
cols: 80,
rows: 24,
useStyle: true,
screenKeys: false,
convertEol: false,
cursorBlink: false
});
term.open();
term.on('data', function (data) {
term.write(data.replace('\r', '\r\n'))
});
calWinSize();
resize();
$('.terminal').detach().appendTo('#term');
setInterval(function () {
requestAndWrite()
}, 200)
});
</script>

View File

@ -105,6 +105,10 @@
$(td).html(cellData.user) $(td).html(cellData.user)
} }
}}, }},
{targets: 6, createdCell: function (td, cellData) {
var d = new Date(cellData);
$(td).html(d.toLocaleString())
}},
{targets: 7, createdCell: function (td, cellData, rowData) { {targets: 7, createdCell: function (td, cellData, rowData) {
var detail_btn = '<a class="btn btn-xs btn-primary m-l-xs btn-run" href="{% url 'ops:adhoc-detail' pk=DEFAULT_PK %}">{% trans "Detail" %}</a>'.replace('{{ DEFAULT_PK }}', cellData); var detail_btn = '<a class="btn btn-xs btn-primary m-l-xs btn-run" href="{% url 'ops:adhoc-detail' pk=DEFAULT_PK %}">{% trans "Detail" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
if (cellData) { if (cellData) {

View File

@ -24,6 +24,9 @@
<li> <li>
<a href="{% url 'ops:task-history' pk=object.pk %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Run history' %} </a> <a href="{% url 'ops:task-history' pk=object.pk %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Run history' %} </a>
</li> </li>
<li>
<a href="{% url 'ops:adhoc-history-output' pk=object.latest_history.pk %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Last run output' %} </a>
</li>
</ul> </ul>
</div> </div>
<div class="tab-content"> <div class="tab-content">
@ -160,6 +163,5 @@
</div> </div>
</div> </div>
</div> </div>
{% include 'users/_user_update_pk_modal.html' %}
{% endblock %} {% endblock %}

View File

@ -30,7 +30,7 @@
<div class="col-sm-12" style="padding-left: 0"> <div class="col-sm-12" style="padding-left: 0">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span style="float: left">{% trans 'History of ' %} <b>{{ object.task.name }}:{{ object.short_id }}</b></span> <span style="float: left">{% trans 'History of ' %} <b>{{ object.name }}:{{ object.short_id }}</b></span>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
@ -85,7 +85,8 @@ function initTable() {
select: [], select: [],
columnDefs: [ columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) { {targets: 1, createdCell: function (td, cellData, rowData) {
$(td).html(cellData); var d = new Date(cellData);
$(td).html(d.toLocaleString());
}}, }},
{targets: 2, createdCell: function (td, cellData) { {targets: 2, createdCell: function (td, cellData) {
var total = "<span>" + cellData.total + "</span>"; var total = "<span>" + cellData.total + "</span>";

View File

@ -111,9 +111,9 @@ $(document).ready(function() {
var error = function (data) { var error = function (data) {
alert(data) alert(data)
}; };
var success = function () { var success = function(data) {
alert("任务开始执行,重定向到任务详情页面,多刷新几次查看结果") var task_id = data.task;
window.location = "{% url 'ops:task-detail' pk=DEFAULT_PK %}".replace('{{ DEFAULT_PK }}', uid); window.location = "{% url 'ops:adhoc-history-output' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", task_id);
}; };
APIUpdateAttr({ APIUpdateAttr({
url: the_url, url: the_url,

View File

@ -15,7 +15,7 @@ router.register(r'v1/history', api.AdHocRunHistorySet, 'history')
urlpatterns = [ urlpatterns = [
url(r'^v1/tasks/(?P<pk>[0-9a-zA-Z\-]{36})/run/$', api.TaskRun.as_view(), name='task-run'), url(r'^v1/tasks/(?P<pk>[0-9a-zA-Z\-]{36})/run/$', api.TaskRun.as_view(), name='task-run'),
url(r'^v1/history/(?P<pk>[0-9a-zA-Z\-]{36})/output/$', api.AdHocHistoryOutputAPI.as_view(), name='history-output'), # url(r'^v1/history/(?P<pk>[0-9a-zA-Z\-]{36})/output/$', api.CeleryTaskOutputApi.as_view(), name='history-output'),
] ]
urlpatterns += router.urls urlpatterns += router.urls

View File

@ -18,5 +18,6 @@ urlpatterns = [
url(r'^adhoc/(?P<pk>[0-9a-zA-Z\-]{36})/$', views.AdHocDetailView.as_view(), name='adhoc-detail'), url(r'^adhoc/(?P<pk>[0-9a-zA-Z\-]{36})/$', views.AdHocDetailView.as_view(), name='adhoc-detail'),
url(r'^adhoc/(?P<pk>[0-9a-zA-Z\-]{36})/history/$', views.AdHocHistoryView.as_view(), name='adhoc-history'), url(r'^adhoc/(?P<pk>[0-9a-zA-Z\-]{36})/history/$', views.AdHocHistoryView.as_view(), name='adhoc-history'),
url(r'^adhoc/history/(?P<pk>[0-9a-zA-Z\-]{36})/$', views.AdHocHistoryDetailView.as_view(), name='adhoc-history-detail'), url(r'^adhoc/history/(?P<pk>[0-9a-zA-Z\-]{36})/$', views.AdHocHistoryDetailView.as_view(), name='adhoc-history-detail'),
url(r'^adhoc/history/(?P<pk>[0-9a-zA-Z\-]{36})/_output/$', views.CeleryTaskOutputView.as_view(), name='adhoc-history-output-alone'),
url(r'^adhoc/history/(?P<pk>[0-9a-zA-Z\-]{36})/output/$', views.AdHocHistoryOutputView.as_view(), name='adhoc-history-output'), url(r'^adhoc/history/(?P<pk>[0-9a-zA-Z\-]{36})/output/$', views.AdHocHistoryOutputView.as_view(), name='adhoc-history-output'),
] ]

View File

@ -2,7 +2,7 @@
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.conf import settings from django.conf import settings
from django.views.generic import ListView, DetailView from django.views.generic import ListView, DetailView, TemplateView
from common.mixins import DatetimeSearchMixin from common.mixins import DatetimeSearchMixin
from .models import Task, AdHoc, AdHocRunHistory from .models import Task, AdHoc, AdHocRunHistory
@ -121,6 +121,11 @@ class AdHocHistoryDetailView(AdminUserRequiredMixin, DetailView):
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
class CeleryTaskOutputView(AdminUserRequiredMixin, TemplateView):
model = AdHocRunHistory
template_name = 'ops/celery_task_output.html'
class AdHocHistoryOutputView(AdminUserRequiredMixin, DetailView): class AdHocHistoryOutputView(AdminUserRequiredMixin, DetailView):
model = AdHocRunHistory model = AdHocRunHistory
template_name = 'ops/adhoc_history_output.html' template_name = 'ops/adhoc_history_output.html'