mirror of https://github.com/jumpserver/jumpserver
[Update] 增加task最大允许事件,并设置命令最大运行时间为60s
parent
afe9471aa2
commit
6e7446f530
|
@ -70,6 +70,14 @@ class IsCurrentUserOrReadOnly(permissions.BasePermission):
|
||||||
return obj == request.user
|
return obj == request.user
|
||||||
|
|
||||||
|
|
||||||
|
class LoginRequiredMixin(UserPassesTestMixin):
|
||||||
|
def test_func(self):
|
||||||
|
if self.request.user.is_authenticated:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class AdminUserRequiredMixin(UserPassesTestMixin):
|
class AdminUserRequiredMixin(UserPassesTestMixin):
|
||||||
def test_func(self):
|
def test_func(self):
|
||||||
if not self.request.user.is_authenticated:
|
if not self.request.user.is_authenticated:
|
||||||
|
|
|
@ -475,6 +475,7 @@ CELERY_WORKER_REDIRECT_STDOUTS = True
|
||||||
CELERY_WORKER_REDIRECT_STDOUTS_LEVEL = "INFO"
|
CELERY_WORKER_REDIRECT_STDOUTS_LEVEL = "INFO"
|
||||||
# CELERY_WORKER_HIJACK_ROOT_LOGGER = True
|
# CELERY_WORKER_HIJACK_ROOT_LOGGER = True
|
||||||
CELERY_WORKER_MAX_TASKS_PER_CHILD = 40
|
CELERY_WORKER_MAX_TASKS_PER_CHILD = 40
|
||||||
|
CELERY_TASK_SOFT_TIME_LIMIT = 3600
|
||||||
|
|
||||||
# Cache use redis
|
# Cache use redis
|
||||||
CACHES = {
|
CACHES = {
|
||||||
|
|
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: 2019-03-22 17:12+0800\n"
|
"POT-Creation-Date: 2019-03-27 10:57+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"
|
||||||
|
@ -2434,35 +2434,35 @@ msgstr "任务列表"
|
||||||
msgid "Go"
|
msgid "Go"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ops/templates/ops/command_execution_create.html:144
|
#: ops/templates/ops/command_execution_create.html:148
|
||||||
msgid "Selected assets"
|
msgid "Selected assets"
|
||||||
msgstr "已选择资产"
|
msgstr "已选择资产"
|
||||||
|
|
||||||
#: ops/templates/ops/command_execution_create.html:147
|
#: ops/templates/ops/command_execution_create.html:151
|
||||||
msgid "In total"
|
msgid "In total"
|
||||||
msgstr "总共"
|
msgstr "总共"
|
||||||
|
|
||||||
#: ops/templates/ops/command_execution_create.html:182
|
#: ops/templates/ops/command_execution_create.html:186
|
||||||
msgid ""
|
msgid ""
|
||||||
"Select the left asset, select the running system user, execute command in "
|
"Select the left asset, select the running system user, execute command in "
|
||||||
"batch"
|
"batch"
|
||||||
msgstr "选择左侧资产, 选择运行的系统用户,批量执行命令"
|
msgstr "选择左侧资产, 选择运行的系统用户,批量执行命令"
|
||||||
|
|
||||||
#: ops/templates/ops/command_execution_create.html:200
|
#: ops/templates/ops/command_execution_create.html:204
|
||||||
msgid "Unselected assets"
|
msgid "Unselected assets"
|
||||||
msgstr "没有选中资产"
|
msgstr "没有选中资产"
|
||||||
|
|
||||||
#: ops/templates/ops/command_execution_create.html:204
|
#: ops/templates/ops/command_execution_create.html:208
|
||||||
msgid "No input command"
|
msgid "No input command"
|
||||||
msgstr "没有输入命令"
|
msgstr "没有输入命令"
|
||||||
|
|
||||||
#: ops/templates/ops/command_execution_create.html:208
|
#: ops/templates/ops/command_execution_create.html:212
|
||||||
msgid "No system user was selected"
|
msgid "No system user was selected"
|
||||||
msgstr "没有选择系统用户"
|
msgstr "没有选择系统用户"
|
||||||
|
|
||||||
#: ops/templates/ops/command_execution_create.html:253
|
#: ops/templates/ops/command_execution_create.html:257
|
||||||
msgid "Pending"
|
msgid "Pending"
|
||||||
msgstr ""
|
msgstr "等待"
|
||||||
|
|
||||||
#: ops/templates/ops/command_execution_list.html:64
|
#: ops/templates/ops/command_execution_list.html:64
|
||||||
msgid "Finished"
|
msgid "Finished"
|
||||||
|
@ -2521,7 +2521,7 @@ msgstr "更新任务内容: {}"
|
||||||
|
|
||||||
#: ops/views/adhoc.py:44 ops/views/adhoc.py:69 ops/views/adhoc.py:82
|
#: ops/views/adhoc.py:44 ops/views/adhoc.py:69 ops/views/adhoc.py:82
|
||||||
#: ops/views/adhoc.py:95 ops/views/adhoc.py:108 ops/views/adhoc.py:121
|
#: ops/views/adhoc.py:95 ops/views/adhoc.py:108 ops/views/adhoc.py:121
|
||||||
#: ops/views/adhoc.py:134 ops/views/command.py:43 ops/views/command.py:67
|
#: ops/views/adhoc.py:134 ops/views/command.py:44 ops/views/command.py:68
|
||||||
msgid "Ops"
|
msgid "Ops"
|
||||||
msgstr "作业中心"
|
msgstr "作业中心"
|
||||||
|
|
||||||
|
@ -2533,11 +2533,11 @@ msgstr "任务列表"
|
||||||
msgid "Task run history"
|
msgid "Task run history"
|
||||||
msgstr "执行历史"
|
msgstr "执行历史"
|
||||||
|
|
||||||
#: ops/views/command.py:44
|
#: ops/views/command.py:45
|
||||||
msgid "Command execution list"
|
msgid "Command execution list"
|
||||||
msgstr "命令执行列表"
|
msgstr "命令执行列表"
|
||||||
|
|
||||||
#: ops/views/command.py:68 templates/_nav_user.html:9
|
#: ops/views/command.py:69 templates/_nav_user.html:9
|
||||||
msgid "Command execution"
|
msgid "Command execution"
|
||||||
msgstr "命令执行"
|
msgstr "命令执行"
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import subprocess
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from celery import shared_task, subtask
|
from celery import shared_task, subtask
|
||||||
|
from celery.exceptions import SoftTimeLimitExceeded
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from common.utils import get_logger, get_object_or_none
|
from common.utils import get_logger, get_object_or_none
|
||||||
|
@ -38,11 +39,14 @@ def run_ansible_task(tid, callback=None, **kwargs):
|
||||||
logger.error("No task found")
|
logger.error("No task found")
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
@shared_task(soft_time_limit=60)
|
||||||
def run_command_execution(cid, **kwargs):
|
def run_command_execution(cid, **kwargs):
|
||||||
execution = get_object_or_none(CommandExecution, id=cid)
|
execution = get_object_or_none(CommandExecution, id=cid)
|
||||||
if execution:
|
if execution:
|
||||||
|
try:
|
||||||
execution.run()
|
execution.run()
|
||||||
|
except SoftTimeLimitExceeded:
|
||||||
|
print("HLLL")
|
||||||
else:
|
else:
|
||||||
logger.error("Not found the execution id: {}".format(cid))
|
logger.error("Not found the execution id: {}".format(cid))
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
<script>
|
<script>
|
||||||
var zTree, show = 0;
|
var zTree, show = 0;
|
||||||
var systemUserId = null;
|
var systemUserId = null;
|
||||||
|
var treeUrl = "{% url 'api-perms:my-nodes-assets-as-tree' %}?cache_policy=1";
|
||||||
|
|
||||||
function initTree() {
|
function initTree() {
|
||||||
var setting = {
|
var setting = {
|
||||||
|
@ -110,14 +111,17 @@ function initTree() {
|
||||||
onCheck: onCheck
|
onCheck: onCheck
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var url = "{% url 'api-perms:my-nodes-assets-as-tree' %}?cache_policy=1";
|
|
||||||
if (systemUserId) {
|
if (systemUserId) {
|
||||||
url += '&system_user=' + systemUserId
|
url = treeUrl + '&system_user=' + systemUserId
|
||||||
}
|
}
|
||||||
|
|
||||||
$.get(url, function(data, status){
|
$.get(url, function(data, status){
|
||||||
$.fn.zTree.init($("#assetTree"), setting, data);
|
$.fn.zTree.init($("#assetTree"), setting, data);
|
||||||
zTree = $.fn.zTree.getZTreeObj("assetTree");
|
zTree = $.fn.zTree.getZTreeObj("assetTree");
|
||||||
|
rootNodeAddDom(zTree, function () {
|
||||||
|
treeUrl = treeUrl.replace('cache_policy=1', 'cache_policy=2');
|
||||||
|
initTree();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +254,8 @@ function execute() {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
flash_message: false,
|
flash_message: false,
|
||||||
success: function (resp) {
|
success: function (resp) {
|
||||||
term.write("{% trans 'Pending' %}" + "...\r\n");
|
var msg = "{% trans 'Pending' %}";
|
||||||
|
term.write(msg + "...\r\n");
|
||||||
log_url = resp.log_url;
|
log_url = resp.log_url;
|
||||||
int = setInterval(function () {
|
int = setInterval(function () {
|
||||||
writeExecutionOutput()
|
writeExecutionOutput()
|
||||||
|
|
|
@ -5,6 +5,7 @@ from django.utils.translation import ugettext as _
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.views.generic import ListView, TemplateView
|
from django.views.generic import ListView, TemplateView
|
||||||
|
|
||||||
|
from common.permissions import AdminUserRequiredMixin, LoginRequiredMixin
|
||||||
from common.mixins import DatetimeSearchMixin
|
from common.mixins import DatetimeSearchMixin
|
||||||
from ..models import CommandExecution
|
from ..models import CommandExecution
|
||||||
from ..forms import CommandExecutionForm
|
from ..forms import CommandExecutionForm
|
||||||
|
@ -15,7 +16,7 @@ __all__ = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class CommandExecutionListView(DatetimeSearchMixin, ListView):
|
class CommandExecutionListView(AdminUserRequiredMixin, DatetimeSearchMixin, ListView):
|
||||||
template_name = 'ops/command_execution_list.html'
|
template_name = 'ops/command_execution_list.html'
|
||||||
model = CommandExecution
|
model = CommandExecution
|
||||||
paginate_by = settings.DISPLAY_PER_PAGE
|
paginate_by = settings.DISPLAY_PER_PAGE
|
||||||
|
@ -50,7 +51,7 @@ class CommandExecutionListView(DatetimeSearchMixin, ListView):
|
||||||
return super().get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class CommandExecutionStartView(TemplateView):
|
class CommandExecutionStartView(LoginRequiredMixin, TemplateView):
|
||||||
template_name = 'ops/command_execution_create.html'
|
template_name = 'ops/command_execution_create.html'
|
||||||
form_class = CommandExecutionForm
|
form_class = CommandExecutionForm
|
||||||
|
|
||||||
|
|
|
@ -104,8 +104,8 @@ class AssetPermissionUtil:
|
||||||
"SystemUser": get_node_permissions,
|
"SystemUser": get_node_permissions,
|
||||||
}
|
}
|
||||||
|
|
||||||
CACHE_KEY = '_ASSET_PERM_CACHE_{obj_id}_{filter_id}_{resource}'
|
CACHE_KEY_PREFIX = '_ASSET_PERM_CACHE_'
|
||||||
CACHE_META_KEY = '_ASSET_PERM_META_KEY_{obj_id}_{filter_id}'
|
CACHE_META_KEY_PREFIX = '_ASSET_PERM_META_KEY_'
|
||||||
CACHE_TIME = settings.ASSETS_PERM_CACHE_TIME
|
CACHE_TIME = settings.ASSETS_PERM_CACHE_TIME
|
||||||
CACHE_POLICY_MAP = (('0', 'never'), ('1', 'using'), ('2', 'refresh'))
|
CACHE_POLICY_MAP = (('0', 'never'), ('1', 'using'), ('2', 'refresh'))
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ class AssetPermissionUtil:
|
||||||
self._permissions = None
|
self._permissions = None
|
||||||
self._permissions_id = None # 标记_permission的唯一值
|
self._permissions_id = None # 标记_permission的唯一值
|
||||||
self._assets = None
|
self._assets = None
|
||||||
self._filter_id = '' # 当通过filter更改 permission是标记
|
self._filter_id = 'None' # 当通过filter更改 permission是标记
|
||||||
self.cache_policy = cache_policy
|
self.cache_policy = cache_policy
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -195,7 +195,8 @@ class AssetPermissionUtil:
|
||||||
return self._assets
|
return self._assets
|
||||||
|
|
||||||
def get_cache_key(self, resource):
|
def get_cache_key(self, resource):
|
||||||
return self.CACHE_KEY.format(
|
cache_key = self.CACHE_KEY_PREFIX + '{obj_id}_{filter_id}_{resource}'
|
||||||
|
return cache_key.format(
|
||||||
obj_id=self.obj_id, filter_id=self._filter_id,
|
obj_id=self.obj_id, filter_id=self._filter_id,
|
||||||
resource=resource
|
resource=resource
|
||||||
)
|
)
|
||||||
|
@ -281,7 +282,8 @@ class AssetPermissionUtil:
|
||||||
return self.get_system_user_without_cache()
|
return self.get_system_user_without_cache()
|
||||||
|
|
||||||
def get_meta_cache_key(self):
|
def get_meta_cache_key(self):
|
||||||
key = self.CACHE_META_KEY.format(
|
cache_key = self.CACHE_META_KEY_PREFIX + '{obj_id}_{filter_id}'
|
||||||
|
key = cache_key.format(
|
||||||
obj_id=str(self.object.id), filter_id=self._filter_id
|
obj_id=str(self.object.id), filter_id=self._filter_id
|
||||||
)
|
)
|
||||||
return key
|
return key
|
||||||
|
@ -301,8 +303,9 @@ class AssetPermissionUtil:
|
||||||
cache.set(key, meta, self.CACHE_TIME)
|
cache.set(key, meta, self.CACHE_TIME)
|
||||||
|
|
||||||
def expire_cache_meta(self):
|
def expire_cache_meta(self):
|
||||||
key = self.get_meta_cache_key()
|
cache_key = self.CACHE_META_KEY_PREFIX + '{obj_id}_*'
|
||||||
cache.delete(key)
|
key = cache_key.format(obj_id=str(self.object.id))
|
||||||
|
cache.delete_pattern(key)
|
||||||
|
|
||||||
def update_cache(self):
|
def update_cache(self):
|
||||||
assets = self.get_assets_without_cache()
|
assets = self.get_assets_without_cache()
|
||||||
|
@ -319,17 +322,19 @@ class AssetPermissionUtil:
|
||||||
缓存,以免造成不统一的情况
|
缓存,以免造成不统一的情况
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
key = self.CACHE_KEY.format(str(self.object.id), '*')
|
cache_key = self.CACHE_KEY_PREFIX + '{obj_id}_*'
|
||||||
|
key = cache_key.format(obj_id='*')
|
||||||
cache.delete_pattern(key)
|
cache.delete_pattern(key)
|
||||||
self.expire_cache_meta()
|
self.expire_cache_meta()
|
||||||
|
|
||||||
def expire_all_cache_meta(self):
|
@classmethod
|
||||||
key = self.CACHE_META_KEY.format('*')
|
def expire_all_cache_meta(cls):
|
||||||
|
key = cls.CACHE_META_KEY_PREFIX + '*'
|
||||||
cache.delete_pattern(key)
|
cache.delete_pattern(key)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def expire_all_cache(cls):
|
def expire_all_cache(cls):
|
||||||
key = cls.CACHE_KEY.format('*', '*')
|
key = cls.CACHE_KEY_PREFIX + '*'
|
||||||
cache.delete_pattern(key)
|
cache.delete_pattern(key)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue