mirror of https://github.com/jumpserver/jumpserver
[Update] 修改celery位置
parent
a4c843ff13
commit
d247e49b70
|
@ -1,21 +1,15 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
import uuid
|
|
||||||
|
|
||||||
from django.core.cache import cache
|
|
||||||
from rest_framework.generics import RetrieveAPIView
|
|
||||||
from rest_framework.views import Response, APIView
|
from rest_framework.views import Response, APIView
|
||||||
from ldap3 import Server, Connection
|
from ldap3 import Server, Connection
|
||||||
from django.core.mail import get_connection, send_mail
|
from django.core.mail import get_connection, send_mail
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from .permissions import IsSuperUser, IsAppUser
|
from .permissions import IsSuperUser
|
||||||
from .serializers import MailTestSerializer, LDAPTestSerializer
|
from .serializers import MailTestSerializer, LDAPTestSerializer
|
||||||
from .celery import FINISHED
|
|
||||||
from .const import FILE_END_GUARD, celery_task_pre_key
|
|
||||||
|
|
||||||
|
|
||||||
class MailTestingAPI(APIView):
|
class MailTestingAPI(APIView):
|
||||||
|
@ -112,27 +106,4 @@ class DjangoSettingsAPI(APIView):
|
||||||
return Response(configs)
|
return Response(configs)
|
||||||
|
|
||||||
|
|
||||||
class CeleryTaskLogApi(APIView):
|
|
||||||
permission_classes = (IsSuperUser,)
|
|
||||||
buff_size = 1024 * 10
|
|
||||||
end = False
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
task_id = kwargs.get('pk')
|
|
||||||
info = cache.get(celery_task_pre_key + task_id, {})
|
|
||||||
log_path = info.get("log_path")
|
|
||||||
mark = request.query_params.get("mark") or str(uuid.uuid4())
|
|
||||||
|
|
||||||
if not log_path or not os.path.isfile(log_path):
|
|
||||||
return Response({"data": _("Waiting ...")}, status=203)
|
|
||||||
|
|
||||||
with open(log_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 data == '' and info["status"] == FINISHED:
|
|
||||||
self.end = True
|
|
||||||
return Response({"data": data, 'end': self.end, 'mark': mark})
|
|
||||||
|
|
|
@ -80,11 +80,3 @@ class Setting(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "settings"
|
db_table = "settings"
|
||||||
|
|
||||||
|
|
||||||
class CeleryTask(models.Model):
|
|
||||||
id = models.UUIDField()
|
|
||||||
name = models.CharField(max_length=1024)
|
|
||||||
status = models.CharField(max_length=128)
|
|
||||||
date_published = models.DateTimeField(auto_now_add=True)
|
|
||||||
date_start = models.DateTimeField(null=True)
|
|
||||||
date_finished = models.DateTimeField(null=True)
|
|
|
@ -10,5 +10,4 @@ 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/celery/task/(?P<pk>[0-9a-zA-Z\-]{36})/log/$', api.CeleryTaskLogApi.as_view(), name='celery-task-log'),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -11,6 +11,4 @@ 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'^celery/task/(?P<pk>[0-9a-zA-Z\-]{36})/log/$', views.CeleryTaskLogView.as_view(), name='celery-task-log'),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -122,18 +122,3 @@ class TerminalSettingView(AdminUserRequiredMixin, TemplateView):
|
||||||
return render(request, self.template_name, context)
|
return render(request, self.template_name, context)
|
||||||
|
|
||||||
|
|
||||||
class CeleryTaskLogView(AdminUserRequiredMixin, TemplateView):
|
|
||||||
template_name = 'common/celery_task_log.html'
|
|
||||||
task_log_path = None
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super().get_context_data(**kwargs)
|
|
||||||
task_id = self.kwargs.get("pk")
|
|
||||||
|
|
||||||
if cache.get(celery_task_pre_key+task_id) is None:
|
|
||||||
raise Http404()
|
|
||||||
|
|
||||||
context.update({
|
|
||||||
"task_id": self.kwargs.get("pk")
|
|
||||||
})
|
|
||||||
return context
|
|
||||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Jumpserver 0.3.3\n"
|
"Project-Id-Version: Jumpserver 0.3.3\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2018-03-23 19:50+0800\n"
|
"POT-Creation-Date: 2018-04-02 15:49+0800\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||||
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
|
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
|
||||||
|
@ -51,7 +51,7 @@ msgid "Labels"
|
||||||
msgstr "标签管理"
|
msgstr "标签管理"
|
||||||
|
|
||||||
#: assets/forms/asset.py:34 assets/forms/asset.py:70 assets/models/asset.py:52
|
#: assets/forms/asset.py:34 assets/forms/asset.py:70 assets/models/asset.py:52
|
||||||
#: assets/models/domain.py:34
|
#: assets/models/domain.py:46
|
||||||
msgid "Domain"
|
msgid "Domain"
|
||||||
msgstr "网域"
|
msgstr "网域"
|
||||||
|
|
||||||
|
@ -74,12 +74,12 @@ msgstr ""
|
||||||
|
|
||||||
#: assets/forms/asset.py:90 assets/forms/asset.py:94 assets/forms/domain.py:16
|
#: assets/forms/asset.py:90 assets/forms/asset.py:94 assets/forms/domain.py:16
|
||||||
#: assets/forms/label.py:15
|
#: assets/forms/label.py:15
|
||||||
#: perms/templates/perms/asset_permission_asset.html:88 users/forms.py:270
|
#: perms/templates/perms/asset_permission_asset.html:88 users/forms.py:272
|
||||||
msgid "Select assets"
|
msgid "Select assets"
|
||||||
msgstr "选择资产"
|
msgstr "选择资产"
|
||||||
|
|
||||||
#: assets/forms/asset.py:99 assets/models/asset.py:51
|
#: assets/forms/asset.py:99 assets/models/asset.py:51
|
||||||
#: assets/models/domain.py:32 assets/templates/assets/admin_user_assets.html:53
|
#: assets/models/domain.py:44 assets/templates/assets/admin_user_assets.html:53
|
||||||
#: assets/templates/assets/asset_detail.html:69
|
#: assets/templates/assets/asset_detail.html:69
|
||||||
#: assets/templates/assets/domain_gateway_list.html:58
|
#: assets/templates/assets/domain_gateway_list.html:58
|
||||||
#: assets/templates/assets/system_user_asset.html:51
|
#: assets/templates/assets/system_user_asset.html:51
|
||||||
|
@ -96,7 +96,7 @@ msgid "Select nodes"
|
||||||
msgstr "选择节点"
|
msgstr "选择节点"
|
||||||
|
|
||||||
#: assets/forms/domain.py:14 assets/forms/label.py:13
|
#: assets/forms/domain.py:14 assets/forms/label.py:13
|
||||||
#: assets/models/asset.py:156 assets/templates/assets/admin_user_list.html:25
|
#: assets/models/asset.py:165 assets/templates/assets/admin_user_list.html:25
|
||||||
#: assets/templates/assets/domain_detail.html:60
|
#: assets/templates/assets/domain_detail.html:60
|
||||||
#: assets/templates/assets/domain_list.html:15
|
#: assets/templates/assets/domain_list.html:15
|
||||||
#: assets/templates/assets/label_list.html:16
|
#: assets/templates/assets/label_list.html:16
|
||||||
|
@ -111,7 +111,7 @@ msgstr "资产"
|
||||||
|
|
||||||
#: assets/forms/domain.py:54 assets/forms/user.py:79 assets/forms/user.py:120
|
#: assets/forms/domain.py:54 assets/forms/user.py:79 assets/forms/user.py:120
|
||||||
#: assets/models/base.py:20 assets/models/cluster.py:18
|
#: assets/models/base.py:20 assets/models/cluster.py:18
|
||||||
#: assets/models/domain.py:15 assets/models/group.py:20
|
#: assets/models/domain.py:17 assets/models/group.py:20
|
||||||
#: assets/models/label.py:17 assets/templates/assets/admin_user_detail.html:56
|
#: assets/models/label.py:17 assets/templates/assets/admin_user_detail.html:56
|
||||||
#: assets/templates/assets/admin_user_list.html:23
|
#: assets/templates/assets/admin_user_list.html:23
|
||||||
#: assets/templates/assets/domain_detail.html:56
|
#: assets/templates/assets/domain_detail.html:56
|
||||||
|
@ -121,8 +121,8 @@ msgstr "资产"
|
||||||
#: assets/templates/assets/system_user_detail.html:58
|
#: assets/templates/assets/system_user_detail.html:58
|
||||||
#: assets/templates/assets/system_user_list.html:26 common/models.py:26
|
#: assets/templates/assets/system_user_list.html:26 common/models.py:26
|
||||||
#: common/templates/common/terminal_setting.html:67
|
#: common/templates/common/terminal_setting.html:67
|
||||||
#: common/templates/common/terminal_setting.html:85 ops/models.py:31
|
#: common/templates/common/terminal_setting.html:85 ops/models/adhoc.py:36
|
||||||
#: ops/templates/ops/task_detail.html:56 ops/templates/ops/task_list.html:34
|
#: ops/templates/ops/task_detail.html:59 ops/templates/ops/task_list.html:34
|
||||||
#: perms/models.py:14 perms/templates/perms/asset_permission_detail.html:62
|
#: perms/models.py:14 perms/templates/perms/asset_permission_detail.html:62
|
||||||
#: perms/templates/perms/asset_permission_user.html:54 terminal/models.py:16
|
#: perms/templates/perms/asset_permission_user.html:54 terminal/models.py:16
|
||||||
#: terminal/models.py:149 terminal/templates/terminal/terminal_detail.html:43
|
#: terminal/models.py:149 terminal/templates/terminal/terminal_detail.html:43
|
||||||
|
@ -190,7 +190,7 @@ msgid ""
|
||||||
"than 2 system user"
|
"than 2 system user"
|
||||||
msgstr "高优先级的系统用户将会作为默认登录用户"
|
msgstr "高优先级的系统用户将会作为默认登录用户"
|
||||||
|
|
||||||
#: assets/models/asset.py:49 assets/models/domain.py:31
|
#: assets/models/asset.py:49 assets/models/domain.py:43
|
||||||
#: assets/templates/assets/_asset_list_modal.html:21
|
#: assets/templates/assets/_asset_list_modal.html:21
|
||||||
#: assets/templates/assets/admin_user_assets.html:52
|
#: assets/templates/assets/admin_user_assets.html:52
|
||||||
#: assets/templates/assets/asset_detail.html:61
|
#: assets/templates/assets/asset_detail.html:61
|
||||||
|
@ -217,7 +217,7 @@ msgstr "IP"
|
||||||
msgid "Hostname"
|
msgid "Hostname"
|
||||||
msgstr "主机名"
|
msgstr "主机名"
|
||||||
|
|
||||||
#: assets/models/asset.py:54 assets/models/domain.py:36
|
#: assets/models/asset.py:54 assets/models/domain.py:48
|
||||||
#: assets/models/label.py:20 assets/templates/assets/asset_detail.html:105
|
#: assets/models/label.py:20 assets/templates/assets/asset_detail.html:105
|
||||||
#: perms/templates/perms/asset_permission_list.html:70
|
#: perms/templates/perms/asset_permission_list.html:70
|
||||||
msgid "Is active"
|
msgid "Is active"
|
||||||
|
@ -300,11 +300,11 @@ msgid "Created by"
|
||||||
msgstr "创建者"
|
msgstr "创建者"
|
||||||
|
|
||||||
#: assets/models/asset.py:83 assets/models/cluster.py:26
|
#: assets/models/asset.py:83 assets/models/cluster.py:26
|
||||||
#: assets/models/domain.py:18 assets/models/group.py:22
|
#: assets/models/domain.py:20 assets/models/group.py:22
|
||||||
#: assets/models/label.py:23 assets/templates/assets/admin_user_detail.html:64
|
#: assets/models/label.py:23 assets/templates/assets/admin_user_detail.html:64
|
||||||
#: assets/templates/assets/domain_detail.html:68
|
#: assets/templates/assets/domain_detail.html:68
|
||||||
#: assets/templates/assets/system_user_detail.html:92
|
#: assets/templates/assets/system_user_detail.html:92
|
||||||
#: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:60
|
#: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:63
|
||||||
#: perms/models.py:23 perms/models.py:80
|
#: perms/models.py:23 perms/models.py:80
|
||||||
#: perms/templates/perms/asset_permission_detail.html:90
|
#: perms/templates/perms/asset_permission_detail.html:90
|
||||||
#: terminal/templates/terminal/terminal_detail.html:59 users/models/group.py:17
|
#: terminal/templates/terminal/terminal_detail.html:59 users/models/group.py:17
|
||||||
|
@ -313,8 +313,8 @@ msgid "Date created"
|
||||||
msgstr "创建日期"
|
msgstr "创建日期"
|
||||||
|
|
||||||
#: assets/models/asset.py:84 assets/models/base.py:25
|
#: assets/models/asset.py:84 assets/models/base.py:25
|
||||||
#: assets/models/cluster.py:29 assets/models/domain.py:16
|
#: assets/models/cluster.py:29 assets/models/domain.py:18
|
||||||
#: assets/models/domain.py:35 assets/models/group.py:23
|
#: assets/models/domain.py:47 assets/models/group.py:23
|
||||||
#: assets/models/label.py:21 assets/templates/assets/admin_user_detail.html:72
|
#: assets/models/label.py:21 assets/templates/assets/admin_user_detail.html:72
|
||||||
#: assets/templates/assets/admin_user_list.html:29
|
#: assets/templates/assets/admin_user_list.html:29
|
||||||
#: assets/templates/assets/asset_detail.html:125
|
#: assets/templates/assets/asset_detail.html:125
|
||||||
|
@ -323,7 +323,7 @@ msgstr "创建日期"
|
||||||
#: assets/templates/assets/domain_list.html:17
|
#: assets/templates/assets/domain_list.html:17
|
||||||
#: assets/templates/assets/system_user_detail.html:100
|
#: assets/templates/assets/system_user_detail.html:100
|
||||||
#: assets/templates/assets/system_user_list.html:33 common/models.py:30
|
#: assets/templates/assets/system_user_list.html:33 common/models.py:30
|
||||||
#: ops/models.py:37 perms/models.py:24 perms/models.py:81
|
#: ops/models/adhoc.py:42 perms/models.py:24 perms/models.py:81
|
||||||
#: perms/templates/perms/asset_permission_detail.html:98 terminal/models.py:26
|
#: perms/templates/perms/asset_permission_detail.html:98 terminal/models.py:26
|
||||||
#: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:15
|
#: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:15
|
||||||
#: users/models/user.py:47 users/templates/users/user_detail.html:111
|
#: users/models/user.py:47 users/templates/users/user_detail.html:111
|
||||||
|
@ -387,7 +387,7 @@ msgstr "默认Cluster"
|
||||||
msgid "Cluster"
|
msgid "Cluster"
|
||||||
msgstr "集群"
|
msgstr "集群"
|
||||||
|
|
||||||
#: assets/models/domain.py:33 assets/models/user.py:104
|
#: assets/models/domain.py:45 assets/models/user.py:104
|
||||||
#: assets/templates/assets/domain_gateway_list.html:59
|
#: assets/templates/assets/domain_gateway_list.html:59
|
||||||
#: assets/templates/assets/system_user_detail.html:66
|
#: assets/templates/assets/system_user_detail.html:66
|
||||||
#: assets/templates/assets/system_user_list.html:28
|
#: assets/templates/assets/system_user_list.html:28
|
||||||
|
@ -407,7 +407,7 @@ msgstr "默认资产组"
|
||||||
#: terminal/templates/terminal/command_list.html:32
|
#: terminal/templates/terminal/command_list.html:32
|
||||||
#: terminal/templates/terminal/command_list.html:72
|
#: terminal/templates/terminal/command_list.html:72
|
||||||
#: terminal/templates/terminal/session_list.html:33
|
#: terminal/templates/terminal/session_list.html:33
|
||||||
#: terminal/templates/terminal/session_list.html:71 users/forms.py:218
|
#: terminal/templates/terminal/session_list.html:71 users/forms.py:220
|
||||||
#: users/models/user.py:30 users/models/user.py:254
|
#: users/models/user.py:30 users/models/user.py:254
|
||||||
#: users/templates/users/user_group_detail.html:78
|
#: users/templates/users/user_group_detail.html:78
|
||||||
#: users/templates/users/user_group_list.html:13 users/views/user.py:334
|
#: users/templates/users/user_group_list.html:13 users/views/user.py:334
|
||||||
|
@ -493,7 +493,7 @@ msgstr ""
|
||||||
msgid "推送系统用户到节点资产: {} => {}"
|
msgid "推送系统用户到节点资产: {} => {}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/tasks.py:431
|
#: assets/tasks.py:432
|
||||||
msgid "推送节点系统用户到新加入资产中: {}"
|
msgid "推送节点系统用户到新加入资产中: {}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -509,9 +509,9 @@ msgstr "仅修改你需要更新的字段"
|
||||||
#: assets/templates/assets/system_user_asset.html:21
|
#: assets/templates/assets/system_user_asset.html:21
|
||||||
#: assets/views/admin_user.py:29 assets/views/admin_user.py:47
|
#: assets/views/admin_user.py:29 assets/views/admin_user.py:47
|
||||||
#: assets/views/admin_user.py:63 assets/views/admin_user.py:78
|
#: assets/views/admin_user.py:63 assets/views/admin_user.py:78
|
||||||
#: assets/views/admin_user.py:102 assets/views/asset.py:48
|
#: assets/views/admin_user.py:102 assets/views/asset.py:49
|
||||||
#: assets/views/asset.py:94 assets/views/asset.py:154 assets/views/asset.py:171
|
#: assets/views/asset.py:95 assets/views/asset.py:155 assets/views/asset.py:172
|
||||||
#: assets/views/asset.py:195 assets/views/domain.py:29
|
#: assets/views/asset.py:196 assets/views/domain.py:29
|
||||||
#: assets/views/domain.py:45 assets/views/domain.py:61
|
#: assets/views/domain.py:45 assets/views/domain.py:61
|
||||||
#: assets/views/domain.py:74 assets/views/domain.py:98
|
#: assets/views/domain.py:74 assets/views/domain.py:98
|
||||||
#: assets/views/domain.py:126 assets/views/domain.py:150
|
#: assets/views/domain.py:126 assets/views/domain.py:150
|
||||||
|
@ -602,8 +602,8 @@ msgstr "可连接"
|
||||||
#: assets/templates/assets/domain_list.html:18
|
#: assets/templates/assets/domain_list.html:18
|
||||||
#: assets/templates/assets/label_list.html:17
|
#: assets/templates/assets/label_list.html:17
|
||||||
#: assets/templates/assets/system_user_list.html:34
|
#: assets/templates/assets/system_user_list.html:34
|
||||||
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:61
|
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
|
||||||
#: ops/templates/ops/task_history.html:62 ops/templates/ops/task_list.html:41
|
#: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:41
|
||||||
#: perms/templates/perms/asset_permission_list.html:72
|
#: perms/templates/perms/asset_permission_list.html:72
|
||||||
#: terminal/templates/terminal/session_list.html:80
|
#: terminal/templates/terminal/session_list.html:80
|
||||||
#: terminal/templates/terminal/terminal_list.html:36
|
#: terminal/templates/terminal/terminal_list.html:36
|
||||||
|
@ -774,9 +774,9 @@ msgstr "重置"
|
||||||
#: assets/templates/assets/domain_gateway_list.html:18
|
#: assets/templates/assets/domain_gateway_list.html:18
|
||||||
#: assets/templates/assets/system_user_asset.html:17
|
#: assets/templates/assets/system_user_asset.html:17
|
||||||
#: assets/templates/assets/system_user_detail.html:18
|
#: assets/templates/assets/system_user_detail.html:18
|
||||||
#: ops/templates/ops/adhoc_history.html:129
|
#: ops/templates/ops/adhoc_history.html:130
|
||||||
#: ops/templates/ops/task_adhoc.html:109
|
#: ops/templates/ops/task_adhoc.html:116
|
||||||
#: ops/templates/ops/task_history.html:132
|
#: ops/templates/ops/task_history.html:136
|
||||||
#: perms/templates/perms/asset_permission_asset.html:18
|
#: perms/templates/perms/asset_permission_asset.html:18
|
||||||
#: perms/templates/perms/asset_permission_detail.html:18
|
#: perms/templates/perms/asset_permission_detail.html:18
|
||||||
#: perms/templates/perms/asset_permission_user.html:18
|
#: perms/templates/perms/asset_permission_user.html:18
|
||||||
|
@ -822,7 +822,7 @@ msgstr "替换资产的管理员"
|
||||||
|
|
||||||
#: assets/templates/assets/admin_user_detail.html:100
|
#: assets/templates/assets/admin_user_detail.html:100
|
||||||
#: assets/templates/assets/asset_detail.html:200
|
#: assets/templates/assets/asset_detail.html:200
|
||||||
#: assets/templates/assets/asset_list.html:586
|
#: assets/templates/assets/asset_list.html:594
|
||||||
#: assets/templates/assets/system_user_detail.html:183
|
#: assets/templates/assets/system_user_detail.html:183
|
||||||
#: assets/templates/assets/system_user_list.html:138 templates/_modal.html:16
|
#: assets/templates/assets/system_user_list.html:138 templates/_modal.html:16
|
||||||
#: terminal/templates/terminal/session_detail.html:108
|
#: terminal/templates/terminal/session_detail.html:108
|
||||||
|
@ -849,7 +849,7 @@ msgstr "不可达"
|
||||||
#: assets/templates/assets/admin_user_list.html:28
|
#: assets/templates/assets/admin_user_list.html:28
|
||||||
#: assets/templates/assets/system_user_list.html:32
|
#: assets/templates/assets/system_user_list.html:32
|
||||||
#: ops/templates/ops/adhoc_history.html:54
|
#: ops/templates/ops/adhoc_history.html:54
|
||||||
#: ops/templates/ops/task_history.html:57
|
#: ops/templates/ops/task_history.html:60
|
||||||
msgid "Ratio"
|
msgid "Ratio"
|
||||||
msgstr "比例"
|
msgstr "比例"
|
||||||
|
|
||||||
|
@ -866,7 +866,7 @@ msgstr "节点"
|
||||||
msgid "Label"
|
msgid "Label"
|
||||||
msgstr "标签"
|
msgstr "标签"
|
||||||
|
|
||||||
#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:196
|
#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:197
|
||||||
msgid "Asset detail"
|
msgid "Asset detail"
|
||||||
msgstr "资产详情"
|
msgstr "资产详情"
|
||||||
|
|
||||||
|
@ -905,7 +905,7 @@ msgid "Update successfully!"
|
||||||
msgstr "更新成功"
|
msgstr "更新成功"
|
||||||
|
|
||||||
#: assets/templates/assets/asset_list.html:63
|
#: assets/templates/assets/asset_list.html:63
|
||||||
#: assets/templates/assets/asset_list.html:120 assets/views/asset.py:95
|
#: assets/templates/assets/asset_list.html:120 assets/views/asset.py:96
|
||||||
msgid "Create asset"
|
msgid "Create asset"
|
||||||
msgstr "创建资产"
|
msgstr "创建资产"
|
||||||
|
|
||||||
|
@ -955,7 +955,7 @@ msgstr "创建节点失败"
|
||||||
msgid "Have child node, cancel"
|
msgid "Have child node, cancel"
|
||||||
msgstr "存在子节点,不能删除"
|
msgstr "存在子节点,不能删除"
|
||||||
|
|
||||||
#: assets/templates/assets/asset_list.html:581
|
#: assets/templates/assets/asset_list.html:589
|
||||||
#: assets/templates/assets/system_user_list.html:133
|
#: assets/templates/assets/system_user_list.html:133
|
||||||
#: users/templates/users/user_detail.html:334
|
#: users/templates/users/user_detail.html:334
|
||||||
#: users/templates/users/user_detail.html:359
|
#: users/templates/users/user_detail.html:359
|
||||||
|
@ -964,20 +964,20 @@ msgstr "存在子节点,不能删除"
|
||||||
msgid "Are you sure?"
|
msgid "Are you sure?"
|
||||||
msgstr "你确认吗?"
|
msgstr "你确认吗?"
|
||||||
|
|
||||||
#: assets/templates/assets/asset_list.html:582
|
#: assets/templates/assets/asset_list.html:590
|
||||||
msgid "This will delete the selected assets !!!"
|
msgid "This will delete the selected assets !!!"
|
||||||
msgstr "删除选择资产"
|
msgstr "删除选择资产"
|
||||||
|
|
||||||
#: assets/templates/assets/asset_list.html:590
|
#: assets/templates/assets/asset_list.html:598
|
||||||
msgid "Asset Deleted."
|
msgid "Asset Deleted."
|
||||||
msgstr "已被删除"
|
msgstr "已被删除"
|
||||||
|
|
||||||
#: assets/templates/assets/asset_list.html:591
|
#: assets/templates/assets/asset_list.html:599
|
||||||
#: assets/templates/assets/asset_list.html:596
|
#: assets/templates/assets/asset_list.html:604
|
||||||
msgid "Asset Delete"
|
msgid "Asset Delete"
|
||||||
msgstr "删除"
|
msgstr "删除"
|
||||||
|
|
||||||
#: assets/templates/assets/asset_list.html:595
|
#: assets/templates/assets/asset_list.html:603
|
||||||
msgid "Asset Deleting failed."
|
msgid "Asset Deleting failed."
|
||||||
msgstr "删除失败"
|
msgstr "删除失败"
|
||||||
|
|
||||||
|
@ -1104,23 +1104,23 @@ msgstr "更新管理用户"
|
||||||
msgid "Admin user detail"
|
msgid "Admin user detail"
|
||||||
msgstr "管理用户详情"
|
msgstr "管理用户详情"
|
||||||
|
|
||||||
#: assets/views/asset.py:49 templates/_nav.html:23
|
#: assets/views/asset.py:50 templates/_nav.html:23
|
||||||
msgid "Asset list"
|
msgid "Asset list"
|
||||||
msgstr "资产列表"
|
msgstr "资产列表"
|
||||||
|
|
||||||
#: assets/views/asset.py:61 templates/_nav_user.html:4
|
#: assets/views/asset.py:62 templates/_nav_user.html:4
|
||||||
msgid "My assets"
|
msgid "My assets"
|
||||||
msgstr "我的资产"
|
msgstr "我的资产"
|
||||||
|
|
||||||
#: assets/views/asset.py:155
|
#: assets/views/asset.py:156
|
||||||
msgid "Bulk update asset"
|
msgid "Bulk update asset"
|
||||||
msgstr "批量更新资产"
|
msgstr "批量更新资产"
|
||||||
|
|
||||||
#: assets/views/asset.py:172
|
#: assets/views/asset.py:173
|
||||||
msgid "Update asset"
|
msgid "Update asset"
|
||||||
msgstr "更新资产"
|
msgstr "更新资产"
|
||||||
|
|
||||||
#: assets/views/asset.py:296
|
#: assets/views/asset.py:299
|
||||||
msgid "already exists"
|
msgid "already exists"
|
||||||
msgstr "已经存在"
|
msgstr "已经存在"
|
||||||
|
|
||||||
|
@ -1172,15 +1172,15 @@ msgstr "资产管理"
|
||||||
msgid "System user asset"
|
msgid "System user asset"
|
||||||
msgstr "系统用户集群资产"
|
msgstr "系统用户集群资产"
|
||||||
|
|
||||||
#: common/api.py:19
|
#: common/api.py:18
|
||||||
msgid "Test mail sent to {}, please check"
|
msgid "Test mail sent to {}, please check"
|
||||||
msgstr "邮件已经发送{}, 请检查"
|
msgstr "邮件已经发送{}, 请检查"
|
||||||
|
|
||||||
#: common/api.py:53
|
#: common/api.py:52
|
||||||
msgid "Test ldap success"
|
msgid "Test ldap success"
|
||||||
msgstr "连接LDAP成功"
|
msgstr "连接LDAP成功"
|
||||||
|
|
||||||
#: common/api.py:91
|
#: common/api.py:90
|
||||||
msgid "Match {} s users"
|
msgid "Match {} s users"
|
||||||
msgstr "匹配 {} 个用户"
|
msgstr "匹配 {} 个用户"
|
||||||
|
|
||||||
|
@ -1299,7 +1299,7 @@ msgstr "资产列表排序"
|
||||||
msgid "Heartbeat interval"
|
msgid "Heartbeat interval"
|
||||||
msgstr "心跳间隔"
|
msgstr "心跳间隔"
|
||||||
|
|
||||||
#: common/forms.py:150 ops/models.py:32
|
#: common/forms.py:150 ops/models/adhoc.py:37
|
||||||
msgid "Units: seconds"
|
msgid "Units: seconds"
|
||||||
msgstr "单位: 秒"
|
msgstr "单位: 秒"
|
||||||
|
|
||||||
|
@ -1349,28 +1349,28 @@ msgstr "启用"
|
||||||
#: common/templates/common/email_setting.html:15
|
#: common/templates/common/email_setting.html:15
|
||||||
#: common/templates/common/ldap_setting.html:15
|
#: common/templates/common/ldap_setting.html:15
|
||||||
#: common/templates/common/terminal_setting.html:16
|
#: common/templates/common/terminal_setting.html:16
|
||||||
#: common/templates/common/terminal_setting.html:42 common/views.py:21
|
#: common/templates/common/terminal_setting.html:42 common/views.py:22
|
||||||
msgid "Basic setting"
|
msgid "Basic setting"
|
||||||
msgstr "基本设置"
|
msgstr "基本设置"
|
||||||
|
|
||||||
#: common/templates/common/basic_setting.html:18
|
#: common/templates/common/basic_setting.html:18
|
||||||
#: common/templates/common/email_setting.html:18
|
#: common/templates/common/email_setting.html:18
|
||||||
#: common/templates/common/ldap_setting.html:18
|
#: common/templates/common/ldap_setting.html:18
|
||||||
#: common/templates/common/terminal_setting.html:20 common/views.py:47
|
#: common/templates/common/terminal_setting.html:20 common/views.py:48
|
||||||
msgid "Email setting"
|
msgid "Email setting"
|
||||||
msgstr "邮件设置"
|
msgstr "邮件设置"
|
||||||
|
|
||||||
#: common/templates/common/basic_setting.html:21
|
#: common/templates/common/basic_setting.html:21
|
||||||
#: common/templates/common/email_setting.html:21
|
#: common/templates/common/email_setting.html:21
|
||||||
#: common/templates/common/ldap_setting.html:21
|
#: common/templates/common/ldap_setting.html:21
|
||||||
#: common/templates/common/terminal_setting.html:24 common/views.py:73
|
#: common/templates/common/terminal_setting.html:24 common/views.py:74
|
||||||
msgid "LDAP setting"
|
msgid "LDAP setting"
|
||||||
msgstr "LDAP设置"
|
msgstr "LDAP设置"
|
||||||
|
|
||||||
#: common/templates/common/basic_setting.html:24
|
#: common/templates/common/basic_setting.html:24
|
||||||
#: common/templates/common/email_setting.html:24
|
#: common/templates/common/email_setting.html:24
|
||||||
#: common/templates/common/ldap_setting.html:24
|
#: common/templates/common/ldap_setting.html:24
|
||||||
#: common/templates/common/terminal_setting.html:28 common/views.py:103
|
#: common/templates/common/terminal_setting.html:28 common/views.py:104
|
||||||
msgid "Terminal setting"
|
msgid "Terminal setting"
|
||||||
msgstr "终端设置"
|
msgstr "终端设置"
|
||||||
|
|
||||||
|
@ -1380,97 +1380,101 @@ msgstr "终端设置"
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "类型"
|
msgstr "类型"
|
||||||
|
|
||||||
#: common/views.py:20 common/views.py:46 common/views.py:72 common/views.py:102
|
#: common/views.py:21 common/views.py:47 common/views.py:73 common/views.py:103
|
||||||
#: templates/_nav.html:73
|
#: templates/_nav.html:73
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr "系统设置"
|
msgstr "系统设置"
|
||||||
|
|
||||||
#: common/views.py:31 common/views.py:57 common/views.py:85 common/views.py:115
|
#: common/views.py:32 common/views.py:58 common/views.py:86 common/views.py:116
|
||||||
msgid "Update setting successfully, please restart program"
|
msgid "Update setting successfully, please restart program"
|
||||||
msgstr "更新设置成功, 请手动重启程序"
|
msgstr "更新设置成功, 请手动重启程序"
|
||||||
|
|
||||||
#: ops/models.py:32
|
#: ops/api.py:79
|
||||||
|
msgid "Waiting ..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ops/models/adhoc.py:37
|
||||||
msgid "Interval"
|
msgid "Interval"
|
||||||
msgstr "间隔"
|
msgstr "间隔"
|
||||||
|
|
||||||
#: ops/models.py:33
|
#: ops/models/adhoc.py:38
|
||||||
msgid "Crontab"
|
msgid "Crontab"
|
||||||
msgstr "Crontab"
|
msgstr "Crontab"
|
||||||
|
|
||||||
#: ops/models.py:33
|
#: ops/models/adhoc.py:38
|
||||||
msgid "5 * * * *"
|
msgid "5 * * * *"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ops/models.py:35
|
#: ops/models/adhoc.py:40
|
||||||
msgid "Callback"
|
msgid "Callback"
|
||||||
msgstr "回调"
|
msgstr "回调"
|
||||||
|
|
||||||
#: ops/models.py:149 ops/templates/ops/adhoc_detail.html:114
|
#: ops/models/adhoc.py:154 ops/templates/ops/adhoc_detail.html:114
|
||||||
msgid "Tasks"
|
msgid "Tasks"
|
||||||
msgstr "任务"
|
msgstr "任务"
|
||||||
|
|
||||||
#: ops/models.py:150 ops/templates/ops/adhoc_detail.html:57
|
#: ops/models/adhoc.py:155 ops/templates/ops/adhoc_detail.html:57
|
||||||
#: ops/templates/ops/task_adhoc.html:57
|
#: ops/templates/ops/task_adhoc.html:60
|
||||||
msgid "Pattern"
|
msgid "Pattern"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ops/models.py:151 ops/templates/ops/adhoc_detail.html:61
|
#: ops/models/adhoc.py:156 ops/templates/ops/adhoc_detail.html:61
|
||||||
msgid "Options"
|
msgid "Options"
|
||||||
msgstr "选项"
|
msgstr "选项"
|
||||||
|
|
||||||
#: ops/models.py:152 ops/templates/ops/adhoc_detail.html:53
|
#: ops/models/adhoc.py:157 ops/templates/ops/adhoc_detail.html:53
|
||||||
#: ops/templates/ops/task_adhoc.html:56 ops/templates/ops/task_list.html:37
|
#: ops/templates/ops/task_adhoc.html:59 ops/templates/ops/task_list.html:37
|
||||||
msgid "Hosts"
|
msgid "Hosts"
|
||||||
msgstr "主机"
|
msgstr "主机"
|
||||||
|
|
||||||
#: ops/models.py:153
|
#: ops/models/adhoc.py:158
|
||||||
msgid "Run as admin"
|
msgid "Run as admin"
|
||||||
msgstr "再次执行"
|
msgstr "再次执行"
|
||||||
|
|
||||||
#: ops/models.py:154 ops/templates/ops/adhoc_detail.html:72
|
#: ops/models/adhoc.py:159 ops/templates/ops/adhoc_detail.html:72
|
||||||
#: ops/templates/ops/adhoc_detail.html:77 ops/templates/ops/task_adhoc.html:58
|
#: ops/templates/ops/adhoc_detail.html:77 ops/templates/ops/task_adhoc.html:61
|
||||||
msgid "Run as"
|
msgid "Run as"
|
||||||
msgstr "用户"
|
msgstr "用户"
|
||||||
|
|
||||||
#: ops/models.py:155 ops/templates/ops/adhoc_detail.html:82
|
#: ops/models/adhoc.py:160 ops/templates/ops/adhoc_detail.html:82
|
||||||
#: ops/templates/ops/task_adhoc.html:59
|
#: ops/templates/ops/task_adhoc.html:62
|
||||||
msgid "Become"
|
msgid "Become"
|
||||||
msgstr "Become"
|
msgstr "Become"
|
||||||
|
|
||||||
#: ops/models.py:156 users/templates/users/user_group_detail.html:59
|
#: ops/models/adhoc.py:161 users/templates/users/user_group_detail.html:59
|
||||||
msgid "Create by"
|
msgid "Create by"
|
||||||
msgstr "创建者"
|
msgstr "创建者"
|
||||||
|
|
||||||
#: ops/models.py:307
|
#: ops/models/adhoc.py:323
|
||||||
msgid "Start time"
|
msgid "Start time"
|
||||||
msgstr "开始时间"
|
msgstr "开始时间"
|
||||||
|
|
||||||
#: ops/models.py:308
|
#: ops/models/adhoc.py:324
|
||||||
msgid "End time"
|
msgid "End time"
|
||||||
msgstr "完成时间"
|
msgstr "完成时间"
|
||||||
|
|
||||||
#: ops/models.py:309 ops/templates/ops/adhoc_history.html:57
|
#: ops/models/adhoc.py:325 ops/templates/ops/adhoc_history.html:57
|
||||||
#: ops/templates/ops/task_history.html:60 ops/templates/ops/task_list.html:40
|
#: ops/templates/ops/task_history.html:63 ops/templates/ops/task_list.html:40
|
||||||
msgid "Time"
|
msgid "Time"
|
||||||
msgstr "时间"
|
msgstr "时间"
|
||||||
|
|
||||||
#: ops/models.py:310 ops/templates/ops/adhoc_detail.html:106
|
#: ops/models/adhoc.py:326 ops/templates/ops/adhoc_detail.html:106
|
||||||
#: ops/templates/ops/adhoc_history.html:55
|
#: ops/templates/ops/adhoc_history.html:55
|
||||||
#: ops/templates/ops/adhoc_history_detail.html:66
|
#: ops/templates/ops/adhoc_history_detail.html:69
|
||||||
#: ops/templates/ops/task_detail.html:80 ops/templates/ops/task_history.html:58
|
#: ops/templates/ops/task_detail.html:83 ops/templates/ops/task_history.html:61
|
||||||
msgid "Is finished"
|
msgid "Is finished"
|
||||||
msgstr "是否完成"
|
msgstr "是否完成"
|
||||||
|
|
||||||
#: ops/models.py:311 ops/templates/ops/adhoc_history.html:56
|
#: ops/models/adhoc.py:327 ops/templates/ops/adhoc_history.html:56
|
||||||
#: ops/templates/ops/task_history.html:59
|
#: ops/templates/ops/task_history.html:62
|
||||||
msgid "Is success"
|
msgid "Is success"
|
||||||
msgstr "是否成功"
|
msgstr "是否成功"
|
||||||
|
|
||||||
#: ops/models.py:312
|
#: ops/models/adhoc.py:328
|
||||||
msgid "Adhoc raw result"
|
msgid "Adhoc raw result"
|
||||||
msgstr "结果"
|
msgstr "结果"
|
||||||
|
|
||||||
#: ops/models.py:313
|
#: ops/models/adhoc.py:329
|
||||||
msgid "Adhoc result summary"
|
msgid "Adhoc result summary"
|
||||||
msgstr "汇总"
|
msgstr "汇总"
|
||||||
|
|
||||||
|
@ -1485,8 +1489,8 @@ msgid "Version run history"
|
||||||
msgstr "执行历史"
|
msgstr "执行历史"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_detail.html:49
|
#: ops/templates/ops/adhoc_detail.html:49
|
||||||
#: ops/templates/ops/adhoc_history_detail.html:46
|
#: ops/templates/ops/adhoc_history_detail.html:49
|
||||||
#: ops/templates/ops/task_detail.html:52
|
#: ops/templates/ops/task_detail.html:55
|
||||||
#: terminal/templates/terminal/session_list.html:70
|
#: terminal/templates/terminal/session_list.html:70
|
||||||
#: users/templates/users/login_log_list.html:48
|
#: users/templates/users/login_log_list.html:48
|
||||||
msgid "ID"
|
msgid "ID"
|
||||||
|
@ -1496,59 +1500,59 @@ msgstr "ID"
|
||||||
msgid "Run times"
|
msgid "Run times"
|
||||||
msgstr "执行次数"
|
msgstr "执行次数"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_detail.html:98 ops/templates/ops/task_detail.html:72
|
#: ops/templates/ops/adhoc_detail.html:98 ops/templates/ops/task_detail.html:75
|
||||||
msgid "Last run"
|
msgid "Last run"
|
||||||
msgstr "最后运行"
|
msgstr "最后运行"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_detail.html:102
|
#: ops/templates/ops/adhoc_detail.html:102
|
||||||
#: ops/templates/ops/adhoc_history_detail.html:62
|
#: ops/templates/ops/adhoc_history_detail.html:65
|
||||||
#: ops/templates/ops/task_detail.html:76
|
#: ops/templates/ops/task_detail.html:79
|
||||||
msgid "Time delta"
|
msgid "Time delta"
|
||||||
msgstr "运行时间"
|
msgstr "运行时间"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_detail.html:110
|
#: ops/templates/ops/adhoc_detail.html:110
|
||||||
#: ops/templates/ops/adhoc_history_detail.html:70
|
#: ops/templates/ops/adhoc_history_detail.html:73
|
||||||
#: ops/templates/ops/task_detail.html:84
|
#: ops/templates/ops/task_detail.html:87
|
||||||
msgid "Is success "
|
msgid "Is success "
|
||||||
msgstr "成功"
|
msgstr "成功"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_detail.html:131
|
#: ops/templates/ops/adhoc_detail.html:131
|
||||||
#: ops/templates/ops/task_detail.html:105
|
#: ops/templates/ops/task_detail.html:108
|
||||||
msgid "Last run failed hosts"
|
msgid "Last run failed hosts"
|
||||||
msgstr "最后运行失败主机"
|
msgstr "最后运行失败主机"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_detail.html:151
|
#: ops/templates/ops/adhoc_detail.html:151
|
||||||
#: ops/templates/ops/adhoc_detail.html:176
|
#: ops/templates/ops/adhoc_detail.html:176
|
||||||
#: ops/templates/ops/task_detail.html:125
|
#: ops/templates/ops/task_detail.html:128
|
||||||
#: ops/templates/ops/task_detail.html:150
|
#: ops/templates/ops/task_detail.html:153
|
||||||
msgid "No hosts"
|
msgid "No hosts"
|
||||||
msgstr "没有主机"
|
msgstr "没有主机"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_detail.html:161
|
#: ops/templates/ops/adhoc_detail.html:161
|
||||||
#: ops/templates/ops/task_detail.html:135
|
#: ops/templates/ops/task_detail.html:138
|
||||||
msgid "Last run success hosts"
|
msgid "Last run success hosts"
|
||||||
msgstr "最后运行成功主机"
|
msgstr "最后运行成功主机"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_history.html:30
|
#: ops/templates/ops/adhoc_history.html:30
|
||||||
#: ops/templates/ops/task_history.html:33
|
#: ops/templates/ops/task_history.html:36
|
||||||
msgid "History of "
|
msgid "History of "
|
||||||
msgstr "执行历史"
|
msgstr "执行历史"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_history.html:52
|
#: ops/templates/ops/adhoc_history.html:52
|
||||||
#: ops/templates/ops/adhoc_history_detail.html:58
|
#: ops/templates/ops/adhoc_history_detail.html:61
|
||||||
#: ops/templates/ops/task_history.html:55 terminal/models.py:132
|
#: ops/templates/ops/task_history.html:58 terminal/models.py:132
|
||||||
#: terminal/templates/terminal/session_list.html:77
|
#: terminal/templates/terminal/session_list.html:77
|
||||||
msgid "Date start"
|
msgid "Date start"
|
||||||
msgstr "开始日期"
|
msgstr "开始日期"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_history.html:53
|
#: ops/templates/ops/adhoc_history.html:53
|
||||||
#: ops/templates/ops/task_history.html:56
|
#: ops/templates/ops/task_history.html:59
|
||||||
msgid "F/S/T"
|
msgid "F/S/T"
|
||||||
msgstr "失败/成功/总"
|
msgstr "失败/成功/总"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_history.html:58
|
#: ops/templates/ops/adhoc_history.html:58
|
||||||
#: ops/templates/ops/adhoc_history_detail.html:54
|
#: ops/templates/ops/adhoc_history_detail.html:57
|
||||||
#: ops/templates/ops/task_adhoc.html:55 ops/templates/ops/task_history.html:61
|
#: ops/templates/ops/task_adhoc.html:58 ops/templates/ops/task_history.html:64
|
||||||
msgid "Version"
|
msgid "Version"
|
||||||
msgstr "版本"
|
msgstr "版本"
|
||||||
|
|
||||||
|
@ -1556,24 +1560,29 @@ msgstr "版本"
|
||||||
msgid "Run history detail"
|
msgid "Run history detail"
|
||||||
msgstr "执行历史详情"
|
msgstr "执行历史详情"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_history_detail.html:27
|
#: ops/templates/ops/adhoc_history_detail.html:22
|
||||||
|
#: terminal/backends/command/models.py:14
|
||||||
|
msgid "Output"
|
||||||
|
msgstr "输出"
|
||||||
|
|
||||||
|
#: ops/templates/ops/adhoc_history_detail.html:30
|
||||||
msgid "History detail of"
|
msgid "History detail of"
|
||||||
msgstr "执行历史详情"
|
msgstr "执行历史详情"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_history_detail.html:50
|
#: ops/templates/ops/adhoc_history_detail.html:53
|
||||||
msgid "Task name"
|
msgid "Task name"
|
||||||
msgstr "任务名称"
|
msgstr "任务名称"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_history_detail.html:81
|
#: ops/templates/ops/adhoc_history_detail.html:84
|
||||||
msgid "Failed assets"
|
msgid "Failed assets"
|
||||||
msgstr "失败资产"
|
msgstr "失败资产"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_history_detail.html:101
|
#: ops/templates/ops/adhoc_history_detail.html:104
|
||||||
#: ops/templates/ops/adhoc_history_detail.html:126
|
#: ops/templates/ops/adhoc_history_detail.html:129
|
||||||
msgid "No assets"
|
msgid "No assets"
|
||||||
msgstr "没有资产"
|
msgstr "没有资产"
|
||||||
|
|
||||||
#: ops/templates/ops/adhoc_history_detail.html:111
|
#: ops/templates/ops/adhoc_history_detail.html:114
|
||||||
msgid "Success assets"
|
msgid "Success assets"
|
||||||
msgstr "成功资产"
|
msgstr "成功资产"
|
||||||
|
|
||||||
|
@ -1592,25 +1601,30 @@ msgstr "任务各版本"
|
||||||
msgid "Run history"
|
msgid "Run history"
|
||||||
msgstr "执行历史"
|
msgstr "执行历史"
|
||||||
|
|
||||||
#: ops/templates/ops/task_adhoc.html:33
|
#: ops/templates/ops/task_adhoc.html:28 ops/templates/ops/task_detail.html:28
|
||||||
|
#: ops/templates/ops/task_history.html:28
|
||||||
|
msgid "Last run output"
|
||||||
|
msgstr "输出"
|
||||||
|
|
||||||
|
#: ops/templates/ops/task_adhoc.html:36
|
||||||
msgid "Versions of "
|
msgid "Versions of "
|
||||||
msgstr "版本"
|
msgstr "版本"
|
||||||
|
|
||||||
#: ops/templates/ops/task_adhoc.html:60
|
#: ops/templates/ops/task_adhoc.html:63
|
||||||
#: terminal/templates/terminal/command_list.html:76
|
#: terminal/templates/terminal/command_list.html:76
|
||||||
#: terminal/templates/terminal/session_detail.html:50
|
#: terminal/templates/terminal/session_detail.html:50
|
||||||
msgid "Datetime"
|
msgid "Datetime"
|
||||||
msgstr "日期"
|
msgstr "日期"
|
||||||
|
|
||||||
#: ops/templates/ops/task_detail.html:64
|
#: ops/templates/ops/task_detail.html:67
|
||||||
msgid "Total versions"
|
msgid "Total versions"
|
||||||
msgstr "版本数量"
|
msgstr "版本数量"
|
||||||
|
|
||||||
#: ops/templates/ops/task_detail.html:68
|
#: ops/templates/ops/task_detail.html:71
|
||||||
msgid "Latest version"
|
msgid "Latest version"
|
||||||
msgstr "最新版本"
|
msgstr "最新版本"
|
||||||
|
|
||||||
#: ops/templates/ops/task_detail.html:88
|
#: ops/templates/ops/task_detail.html:91
|
||||||
msgid "Contents"
|
msgid "Contents"
|
||||||
msgstr "内容"
|
msgstr "内容"
|
||||||
|
|
||||||
|
@ -1639,7 +1653,7 @@ msgstr "日期"
|
||||||
msgid "Run"
|
msgid "Run"
|
||||||
msgstr "执行"
|
msgstr "执行"
|
||||||
|
|
||||||
#: ops/templates/ops/task_list.html:123
|
#: ops/templates/ops/task_list.html:124
|
||||||
msgid "Task start: "
|
msgid "Task start: "
|
||||||
msgstr "任务开始: "
|
msgstr "任务开始: "
|
||||||
|
|
||||||
|
@ -1705,7 +1719,7 @@ msgstr "添加"
|
||||||
msgid "Add asset group to this permission"
|
msgid "Add asset group to this permission"
|
||||||
msgstr "添加资产组"
|
msgstr "添加资产组"
|
||||||
|
|
||||||
#: perms/templates/perms/asset_permission_asset.html:116 users/forms.py:273
|
#: perms/templates/perms/asset_permission_asset.html:116 users/forms.py:275
|
||||||
msgid "Select asset groups"
|
msgid "Select asset groups"
|
||||||
msgstr "选择资产组"
|
msgstr "选择资产组"
|
||||||
|
|
||||||
|
@ -1734,7 +1748,7 @@ msgstr "资产组数量"
|
||||||
msgid "System user count"
|
msgid "System user count"
|
||||||
msgstr "系统用户数量"
|
msgstr "系统用户数量"
|
||||||
|
|
||||||
#: perms/templates/perms/asset_permission_detail.html:144 users/forms.py:276
|
#: perms/templates/perms/asset_permission_detail.html:144 users/forms.py:278
|
||||||
msgid "Select system users"
|
msgid "Select system users"
|
||||||
msgstr "选择系统用户"
|
msgstr "选择系统用户"
|
||||||
|
|
||||||
|
@ -1787,7 +1801,7 @@ msgstr "商业支持"
|
||||||
msgid "Docs"
|
msgid "Docs"
|
||||||
msgstr "文档"
|
msgstr "文档"
|
||||||
|
|
||||||
#: templates/_header_bar.html:37 templates/_nav_user.html:9 users/forms.py:92
|
#: templates/_header_bar.html:37 templates/_nav_user.html:9 users/forms.py:94
|
||||||
#: users/templates/users/_user.html:36
|
#: users/templates/users/_user.html:36
|
||||||
#: users/templates/users/user_password_update.html:37
|
#: users/templates/users/user_password_update.html:37
|
||||||
#: users/templates/users/user_profile.html:17
|
#: users/templates/users/user_profile.html:17
|
||||||
|
@ -1912,10 +1926,6 @@ msgstr "过滤"
|
||||||
msgid "Input"
|
msgid "Input"
|
||||||
msgstr "输入"
|
msgstr "输入"
|
||||||
|
|
||||||
#: terminal/backends/command/models.py:14
|
|
||||||
msgid "Output"
|
|
||||||
msgstr "输出"
|
|
||||||
|
|
||||||
#: terminal/backends/command/models.py:15
|
#: terminal/backends/command/models.py:15
|
||||||
#: terminal/templates/terminal/command_list.html:75
|
#: terminal/templates/terminal/command_list.html:75
|
||||||
#: terminal/templates/terminal/terminal_list.html:33
|
#: terminal/templates/terminal/terminal_list.html:33
|
||||||
|
@ -2179,11 +2189,11 @@ msgstr ""
|
||||||
msgid "Role"
|
msgid "Role"
|
||||||
msgstr "角色"
|
msgstr "角色"
|
||||||
|
|
||||||
#: users/forms.py:30 users/forms.py:138
|
#: users/forms.py:30 users/forms.py:140
|
||||||
msgid "ssh public key"
|
msgid "ssh public key"
|
||||||
msgstr "ssh公钥"
|
msgstr "ssh公钥"
|
||||||
|
|
||||||
#: users/forms.py:31 users/forms.py:139
|
#: users/forms.py:31 users/forms.py:141
|
||||||
msgid "ssh-rsa AAAA..."
|
msgid "ssh-rsa AAAA..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2195,39 +2205,39 @@ msgstr "复制用户公钥到这里"
|
||||||
msgid "Join user groups"
|
msgid "Join user groups"
|
||||||
msgstr "添加到用户组"
|
msgstr "添加到用户组"
|
||||||
|
|
||||||
#: users/forms.py:58 users/forms.py:153
|
#: users/forms.py:60 users/forms.py:155
|
||||||
msgid "Public key should not be the same as your old one."
|
msgid "Public key should not be the same as your old one."
|
||||||
msgstr "不能和原来的密钥相同"
|
msgstr "不能和原来的密钥相同"
|
||||||
|
|
||||||
#: users/forms.py:62 users/forms.py:157 users/serializers.py:42
|
#: users/forms.py:64 users/forms.py:159 users/serializers.py:42
|
||||||
msgid "Not a valid ssh public key"
|
msgid "Not a valid ssh public key"
|
||||||
msgstr "ssh密钥不合法"
|
msgstr "ssh密钥不合法"
|
||||||
|
|
||||||
#: users/forms.py:98
|
#: users/forms.py:100
|
||||||
msgid "Old password"
|
msgid "Old password"
|
||||||
msgstr "原来密码"
|
msgstr "原来密码"
|
||||||
|
|
||||||
#: users/forms.py:103
|
#: users/forms.py:105
|
||||||
msgid "New password"
|
msgid "New password"
|
||||||
msgstr "新密码"
|
msgstr "新密码"
|
||||||
|
|
||||||
#: users/forms.py:108
|
#: users/forms.py:110
|
||||||
msgid "Confirm password"
|
msgid "Confirm password"
|
||||||
msgstr "确认密码"
|
msgstr "确认密码"
|
||||||
|
|
||||||
#: users/forms.py:118
|
#: users/forms.py:120
|
||||||
msgid "Old password error"
|
msgid "Old password error"
|
||||||
msgstr "原来密码错误"
|
msgstr "原来密码错误"
|
||||||
|
|
||||||
#: users/forms.py:126
|
#: users/forms.py:128
|
||||||
msgid "Password does not match"
|
msgid "Password does not match"
|
||||||
msgstr "密码不一致"
|
msgstr "密码不一致"
|
||||||
|
|
||||||
#: users/forms.py:140
|
#: users/forms.py:142
|
||||||
msgid "Paste your id_rsa.pub here."
|
msgid "Paste your id_rsa.pub here."
|
||||||
msgstr "复制你的公钥到这里"
|
msgstr "复制你的公钥到这里"
|
||||||
|
|
||||||
#: users/forms.py:168 users/models/user.py:46
|
#: users/forms.py:170 users/models/user.py:46
|
||||||
#: users/templates/users/user_password_update.html:43
|
#: users/templates/users/user_password_update.html:43
|
||||||
#: users/templates/users/user_profile.html:71
|
#: users/templates/users/user_profile.html:71
|
||||||
#: users/templates/users/user_profile_update.html:43
|
#: users/templates/users/user_profile_update.html:43
|
||||||
|
@ -2235,7 +2245,7 @@ msgstr "复制你的公钥到这里"
|
||||||
msgid "Public key"
|
msgid "Public key"
|
||||||
msgstr "ssh公钥"
|
msgstr "ssh公钥"
|
||||||
|
|
||||||
#: users/forms.py:175 users/forms.py:180 users/forms.py:192 users/forms.py:222
|
#: users/forms.py:177 users/forms.py:182 users/forms.py:194 users/forms.py:224
|
||||||
msgid "Select users"
|
msgid "Select users"
|
||||||
msgstr "选择用户"
|
msgstr "选择用户"
|
||||||
|
|
||||||
|
@ -2777,4 +2787,3 @@ msgstr "密码更新"
|
||||||
#: users/views/user.py:375
|
#: users/views/user.py:375
|
||||||
msgid "Public key update"
|
msgid "Public key update"
|
||||||
msgstr "密钥更新"
|
msgstr "密钥更新"
|
||||||
|
|
||||||
|
|
|
@ -6,18 +6,15 @@ 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 django.utils.translation import ugettext as _
|
||||||
from rest_framework import viewsets, generics
|
from rest_framework import viewsets, generics
|
||||||
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, CeleryTask
|
||||||
from .models import Task, AdHoc, AdHocRunHistory
|
from .serializers import TaskSerializer, AdHocSerializer, \
|
||||||
from .serializers import TaskSerializer, AdHocSerializer, AdHocRunHistorySerializer
|
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
|
||||||
|
@ -67,28 +64,28 @@ class AdHocRunHistorySet(viewsets.ModelViewSet):
|
||||||
return self.queryset
|
return self.queryset
|
||||||
|
|
||||||
|
|
||||||
class LogFileViewApi(APIView):
|
class CeleryTaskLogApi(generics.RetrieveAPIView):
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
buff_size = 1024 * 10
|
buff_size = 1024 * 10
|
||||||
end = False
|
end = False
|
||||||
|
queryset = CeleryTask.objects.all()
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
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())
|
||||||
|
task = super().get_object()
|
||||||
|
log_path = task.full_log_path
|
||||||
|
|
||||||
if not os.path.isfile(file_path):
|
if not log_path or not os.path.isfile(log_path):
|
||||||
print(file_path)
|
return Response({"data": _("Waiting ...")}, status=203)
|
||||||
return Response({"error": _("Log file not found")}, status=204)
|
|
||||||
|
|
||||||
with open(file_path, 'r') as f:
|
with open(log_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')
|
||||||
mark = str(uuid.uuid4())
|
mark = str(uuid.uuid4())
|
||||||
cache.set(mark, f.tell(), 5)
|
cache.set(mark, f.tell(), 5)
|
||||||
|
|
||||||
if FILE_END_GUARD in data:
|
if data == '' and task.is_finished():
|
||||||
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})
|
||||||
|
|
||||||
|
|
|
@ -5,3 +5,7 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
class OpsConfig(AppConfig):
|
class OpsConfig(AppConfig):
|
||||||
name = 'ops'
|
name = 'ops'
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
super().ready()
|
||||||
|
from .celery import signal_handler
|
||||||
|
|
|
@ -15,4 +15,3 @@ app = Celery('jumpserver')
|
||||||
# pickle the object when using Windows.
|
# pickle the object when using Windows.
|
||||||
app.config_from_object('django.conf:settings', namespace='CELERY')
|
app.config_from_object('django.conf:settings', namespace='CELERY')
|
||||||
app.autodiscover_tasks(lambda: [app_config.split('.')[0] for app_config in settings.INSTALLED_APPS])
|
app.autodiscover_tasks(lambda: [app_config.split('.')[0] for app_config in settings.INSTALLED_APPS])
|
||||||
|
|
||||||
|
|
|
@ -5,27 +5,21 @@ import datetime
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.utils import timezone
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
from django.db import transaction
|
||||||
from celery import subtask
|
from celery import subtask
|
||||||
from celery.signals import worker_ready, worker_shutdown, task_prerun, \
|
from celery.signals import worker_ready, worker_shutdown, task_prerun, \
|
||||||
task_postrun, after_task_publish
|
task_postrun, after_task_publish
|
||||||
|
|
||||||
from django_celery_beat.models import PeriodicTask
|
from django_celery_beat.models import PeriodicTask
|
||||||
|
|
||||||
from common.utils import get_logger, TeeObj
|
from common.utils import get_logger, TeeObj, get_object_or_none
|
||||||
from common.const import celery_task_pre_key
|
from common.const import celery_task_pre_key
|
||||||
|
|
||||||
from .utils import get_after_app_ready_tasks, get_after_app_shutdown_clean_tasks
|
from .utils import get_after_app_ready_tasks, get_after_app_shutdown_clean_tasks
|
||||||
|
from ..models import CeleryTask
|
||||||
|
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
|
|
||||||
WAITING = "waiting"
|
|
||||||
RUNNING = "running"
|
|
||||||
FINISHED = "finished"
|
|
||||||
|
|
||||||
EXPIRE_TIME = 3600
|
|
||||||
|
|
||||||
|
|
||||||
@worker_ready.connect
|
@worker_ready.connect
|
||||||
def on_app_ready(sender=None, headers=None, body=None, **kwargs):
|
def on_app_ready(sender=None, headers=None, body=None, **kwargs):
|
||||||
|
@ -54,18 +48,31 @@ def after_app_shutdown(sender=None, headers=None, body=None, **kwargs):
|
||||||
PeriodicTask.objects.filter(name__in=tasks).delete()
|
PeriodicTask.objects.filter(name__in=tasks).delete()
|
||||||
|
|
||||||
|
|
||||||
|
@after_task_publish.connect
|
||||||
|
def after_task_publish_signal_handler(sender, headers=None, **kwargs):
|
||||||
|
CeleryTask.objects.create(
|
||||||
|
id=headers["id"], status=CeleryTask.WAITING, name=headers["task"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@task_prerun.connect
|
@task_prerun.connect
|
||||||
def pre_run_task_signal_handler(sender, task_id=None, task=None, **kwargs):
|
def pre_run_task_signal_handler(sender, task_id=None, task=None, **kwargs):
|
||||||
task_key = celery_task_pre_key + task_id
|
t = get_object_or_none(CeleryTask, id=task_id)
|
||||||
info = cache.get(task_key, {})
|
if t is None:
|
||||||
|
logger.warn("Not get the task: {}".format(task_id))
|
||||||
|
return
|
||||||
now = datetime.datetime.now().strftime("%Y-%m-%d")
|
now = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||||
log_dir = os.path.join(settings.PROJECT_DIR, "data", "celery", now)
|
log_path = os.path.join(now, task_id + '.log')
|
||||||
if not os.path.exists(log_dir):
|
full_path = os.path.join(CeleryTask.LOG_DIR, log_path)
|
||||||
os.makedirs(log_dir)
|
|
||||||
log_path = os.path.join(log_dir, task_id + '.log')
|
if not os.path.exists(os.path.dirname(full_path)):
|
||||||
info.update({"status": RUNNING, "log_path": log_path})
|
os.makedirs(os.path.dirname(full_path))
|
||||||
cache.set(task_key, info, EXPIRE_TIME)
|
with transaction.atomic():
|
||||||
f = open(log_path, 'w')
|
t.date_start = timezone.now()
|
||||||
|
t.status = CeleryTask.RUNNING
|
||||||
|
t.log_path = log_path
|
||||||
|
t.save()
|
||||||
|
f = open(full_path, 'w')
|
||||||
tee = TeeObj(f)
|
tee = TeeObj(f)
|
||||||
sys.stdout = tee
|
sys.stdout = tee
|
||||||
task.log_f = tee
|
task.log_f = tee
|
||||||
|
@ -73,17 +80,15 @@ def pre_run_task_signal_handler(sender, task_id=None, task=None, **kwargs):
|
||||||
|
|
||||||
@task_postrun.connect
|
@task_postrun.connect
|
||||||
def post_run_task_signal_handler(sender, task_id=None, task=None, **kwargs):
|
def post_run_task_signal_handler(sender, task_id=None, task=None, **kwargs):
|
||||||
task_key = celery_task_pre_key + task_id
|
t = get_object_or_none(CeleryTask, id=task_id)
|
||||||
info = cache.get(task_key, {})
|
if t is None:
|
||||||
info.update({"status": FINISHED})
|
logger.warn("Not get the task: {}".format(task_id))
|
||||||
cache.set(task_key, info, EXPIRE_TIME)
|
return
|
||||||
|
with transaction.atomic():
|
||||||
|
t.status = CeleryTask.FINISHED
|
||||||
|
t.date_finished = timezone.now()
|
||||||
|
t.save()
|
||||||
task.log_f.flush()
|
task.log_f.flush()
|
||||||
sys.stdout = task.log_f.origin_stdout
|
sys.stdout = task.log_f.origin_stdout
|
||||||
task.log_f.close()
|
task.log_f.close()
|
||||||
|
|
||||||
|
|
||||||
@after_task_publish.connect
|
|
||||||
def after_task_publish_signal_handler(sender, headers=None, **kwargs):
|
|
||||||
task_id = headers["id"]
|
|
||||||
key = celery_task_pre_key + task_id
|
|
||||||
cache.set(key, {"status": WAITING}, EXPIRE_TIME)
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
|
||||||
|
from .adhoc import *
|
||||||
|
from .celery import *
|
|
@ -11,15 +11,14 @@ 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
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django_celery_beat.models import CrontabSchedule, IntervalSchedule, \
|
from django_celery_beat.models import PeriodicTask
|
||||||
PeriodicTask
|
|
||||||
|
|
||||||
from common.utils import get_signer, get_logger
|
from common.utils import get_signer, get_logger
|
||||||
from .celery.utils import delete_celery_periodic_task, \
|
from ..celery.utils import delete_celery_periodic_task, \
|
||||||
create_or_update_celery_periodic_tasks, \
|
create_or_update_celery_periodic_tasks, \
|
||||||
disable_celery_periodic_task
|
disable_celery_periodic_task
|
||||||
from .ansible import AdHocRunner, AnsibleError
|
from ..ansible import AdHocRunner, AnsibleError
|
||||||
from .inventory import JMSInventory
|
from ..inventory import JMSInventory
|
||||||
|
|
||||||
__all__ = ["Task", "AdHoc", "AdHocRunHistory"]
|
__all__ = ["Task", "AdHoc", "AdHocRunHistory"]
|
||||||
|
|
||||||
|
@ -91,7 +90,7 @@ class Task(models.Model):
|
||||||
|
|
||||||
def save(self, force_insert=False, force_update=False, using=None,
|
def save(self, force_insert=False, force_update=False, using=None,
|
||||||
update_fields=None):
|
update_fields=None):
|
||||||
from .tasks import run_ansible_task
|
from ..tasks import run_ansible_task
|
||||||
super().save(
|
super().save(
|
||||||
force_insert=force_insert, force_update=force_update,
|
force_insert=force_insert, force_update=force_update,
|
||||||
using=using, update_fields=update_fields,
|
using=using, update_fields=update_fields,
|
|
@ -0,0 +1,36 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
import uuid
|
||||||
|
import os
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class CeleryTask(models.Model):
|
||||||
|
WAITING = "waiting"
|
||||||
|
RUNNING = "running"
|
||||||
|
FINISHED = "finished"
|
||||||
|
LOG_DIR = os.path.join(settings.PROJECT_DIR, 'data', 'celery')
|
||||||
|
|
||||||
|
STATUS_CHOICES = (
|
||||||
|
(WAITING, WAITING),
|
||||||
|
(RUNNING, RUNNING),
|
||||||
|
(FINISHED, FINISHED),
|
||||||
|
)
|
||||||
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
|
||||||
|
name = models.CharField(max_length=1024)
|
||||||
|
status = models.CharField(max_length=128, choices=STATUS_CHOICES)
|
||||||
|
log_path = models.CharField(max_length=256, blank=True, null=True)
|
||||||
|
date_published = models.DateTimeField(auto_now_add=True)
|
||||||
|
date_start = models.DateTimeField(null=True)
|
||||||
|
date_finished = models.DateTimeField(null=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "{}: {}".format(self.name, self.id)
|
||||||
|
|
||||||
|
def is_finished(self):
|
||||||
|
return self.status == self.FINISHED
|
||||||
|
|
||||||
|
@property
|
||||||
|
def full_log_path(self):
|
||||||
|
return os.path.join(self.LOG_DIR, self.log_path)
|
|
@ -1,7 +1,6 @@
|
||||||
# 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
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<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>
|
<li>
|
||||||
<a href="{% url 'ops:adhoc-history-output' pk=object.pk %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'History output' %} </a>
|
<a class="text-center celery-task-log" onclick="window.open('{% url 'ops:celery-task-log' pk=object.pk %}','', 'width=800,height=600')"><i class="fa fa-laptop"></i> {% trans 'Output' %} </a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% load static %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block custom_head_css_js %}
|
|
||||||
<link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet">
|
|
||||||
<link href="{% static "css/plugins/sweetalert/sweetalert.css" %}" rel="stylesheet">
|
|
||||||
<script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
|
|
||||||
<script src="{% static "js/plugins/sweetalert/sweetalert.min.js" %}"></script>
|
|
||||||
</head>
|
|
||||||
{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<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>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
var rowHeight = 1;
|
var rowHeight = 1;
|
||||||
var colWidth = 1;
|
var colWidth = 1;
|
||||||
var mark = '';
|
var mark = '';
|
||||||
var url = "{% url 'api-common:celery-task-log' pk=task_id %}";
|
var url = "{% url 'api-ops:celery-task-log' pk=object.id %}";
|
||||||
var term;
|
var term;
|
||||||
var end = false;
|
var end = false;
|
||||||
var error = false;
|
var error = false;
|
|
@ -1,94 +0,0 @@
|
||||||
{% 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>
|
|
|
@ -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 class="text-center celery-task-log" onclick="window.open('{% url 'ops:celery-task-log' pk=object.latest_history.pk %}','', 'width=800,height=600')"><i class="fa fa-laptop"></i> {% trans 'Last run output' %} </a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
<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>
|
<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>
|
<a class="text-center celery-task-log" onclick="window.open('{% url 'ops:celery-task-log' pk=object.latest_history.pk %}','', 'width=800,height=600')"><i class="fa fa-laptop"></i> {% trans 'Last run output' %} </a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
<li class="active">
|
<li class="active">
|
||||||
<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 class="text-center celery-task-log" onclick="window.open('{% url 'ops:celery-task-log' pk=object.latest_history.pk %}','', 'width=800,height=600')"><i class="fa fa-laptop"></i> {% trans 'Last run output' %} </a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
|
|
|
@ -113,8 +113,8 @@ $(document).ready(function() {
|
||||||
};
|
};
|
||||||
var success = function(data) {
|
var success = function(data) {
|
||||||
var task_id = data.task;
|
var task_id = data.task;
|
||||||
var url = '{% url "common:celery-task-log" pk=DEFAULT_PK %}'.replace("{{ DEFAULT_PK }}", task_id);
|
var url = '{% url "ops:celery-task-log" pk=DEFAULT_PK %}'.replace("{{ DEFAULT_PK }}", task_id);
|
||||||
window.open(url, '', 'width=800,height=800')
|
window.open(url, '', 'width=800,height=600')
|
||||||
};
|
};
|
||||||
APIUpdateAttr({
|
APIUpdateAttr({
|
||||||
url: the_url,
|
url: the_url,
|
||||||
|
|
|
@ -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.CeleryTaskOutputApi.as_view(), name='history-output'),
|
url(r'^v1/celery/task/(?P<pk>[0-9a-zA-Z\-]{36})/log/$', api.CeleryTaskLogApi.as_view(), name='celery-task-log'),
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns += router.urls
|
urlpatterns += router.urls
|
||||||
|
|
|
@ -18,6 +18,5 @@ 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'^celery/task/(?P<pk>[0-9a-zA-Z\-]{36})/log/$', views.CeleryTaskLogView.as_view(), name='celery-task-log'),
|
||||||
url(r'^adhoc/history/(?P<pk>[0-9a-zA-Z\-]{36})/output/$', views.AdHocHistoryOutputView.as_view(), name='adhoc-history-output'),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.conf import settings
|
||||||
from django.views.generic import ListView, DetailView, TemplateView
|
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, CeleryTask
|
||||||
from .hands import AdminUserRequiredMixin
|
from .hands import AdminUserRequiredMixin
|
||||||
|
|
||||||
|
|
||||||
|
@ -121,19 +121,6 @@ class AdHocHistoryDetailView(AdminUserRequiredMixin, DetailView):
|
||||||
return super().get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class CeleryTaskOutputView(AdminUserRequiredMixin, TemplateView):
|
class CeleryTaskLogView(AdminUserRequiredMixin, DetailView):
|
||||||
model = AdHocRunHistory
|
template_name = 'ops/celery_task_log.html'
|
||||||
template_name = 'ops/celery_task_output.html'
|
model = CeleryTask
|
||||||
|
|
||||||
|
|
||||||
class AdHocHistoryOutputView(AdminUserRequiredMixin, DetailView):
|
|
||||||
model = AdHocRunHistory
|
|
||||||
template_name = 'ops/adhoc_history_output.html'
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = {
|
|
||||||
'app': _('Ops'),
|
|
||||||
'action': _('Run history detail'),
|
|
||||||
}
|
|
||||||
kwargs.update(context)
|
|
||||||
return super().get_context_data(**kwargs)
|
|
||||||
|
|
Loading…
Reference in New Issue