mirror of https://github.com/jumpserver/jumpserver
[Fixture] 添加task list 搜索,重试
parent
a4504dc0c7
commit
caec9709ef
|
@ -12,8 +12,8 @@ def update_assets_hardware_info(assets):
|
|||
task_tuple = (
|
||||
('setup', ''),
|
||||
)
|
||||
task = run_AdHoc.delay(task_tuple, assets, record=False)
|
||||
summary, result = task.get(timeout=60*10)
|
||||
task_name = ','.join([asset.hostname for asset in assets])
|
||||
summary, result = run_AdHoc(task_tuple, assets, record=True, task_name=task_name)
|
||||
for hostname, info in result['contacted'].items():
|
||||
if info:
|
||||
info = info[0]['ansible_facts']
|
||||
|
|
|
@ -46,12 +46,12 @@ class ProxyLogListView(AdminUserRequiredMixin, ListView):
|
|||
filter_kwargs = {}
|
||||
if self.date_from_s:
|
||||
date_from = datetime.strptime(self.date_from_s, self.date_format)
|
||||
date_from.replace(tzinfo=timezone.get_current_timezone())
|
||||
date_from = date_from.replace(tzinfo=timezone.get_current_timezone())
|
||||
filter_kwargs['date_start__gt'] = date_from
|
||||
if self.date_to_s:
|
||||
date_to = timezone.datetime.strptime(
|
||||
self.date_to_s + ' 23:59:59', '%m/%d/%Y %H:%M:%S')
|
||||
date_to.replace(tzinfo=timezone.get_current_timezone())
|
||||
date_to = date_to.replace(tzinfo=timezone.get_current_timezone())
|
||||
filter_kwargs['date_start__lt'] = date_to
|
||||
if self.user:
|
||||
filter_kwargs['user'] = self.user
|
||||
|
@ -64,6 +64,8 @@ class ProxyLogListView(AdminUserRequiredMixin, ListView):
|
|||
Q(user__icontains=self.keyword) |
|
||||
Q(asset__icontains=self.keyword) |
|
||||
Q(system_user__icontains=self.keyword)).distinct()
|
||||
if filter_kwargs:
|
||||
self.queryset = self.queryset.filter(**filter_kwargs)
|
||||
return self.queryset
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
|
|
@ -19,7 +19,7 @@ from .callback import AdHocResultCallback, PlaybookResultCallBack, \
|
|||
from common.utils import get_logger
|
||||
|
||||
|
||||
__all__ = ["ADHocRunner", "Options"]
|
||||
__all__ = ["AdHocRunner", "PlayBookRunner"]
|
||||
|
||||
C.HOST_KEY_CHECKING = False
|
||||
|
||||
|
|
|
@ -8,13 +8,13 @@ import json
|
|||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
__all__ = ["TaskRecord"]
|
||||
__all__ = ["Task"]
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TaskRecord(models.Model):
|
||||
class Task(models.Model):
|
||||
uuid = models.CharField(max_length=128, verbose_name=_('UUID'), primary_key=True)
|
||||
name = models.CharField(max_length=128, blank=True, verbose_name=_('Name'))
|
||||
date_start = models.DateTimeField(auto_now_add=True, verbose_name=_('Start time'))
|
||||
|
|
|
@ -2,108 +2,21 @@
|
|||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import json
|
||||
import time
|
||||
|
||||
from celery import shared_task
|
||||
from django.utils import timezone
|
||||
|
||||
from assets.models import Asset
|
||||
from common.utils import get_logger, encrypt_password
|
||||
from .ansible.runner import AdHocRunner
|
||||
from common.utils import get_logger
|
||||
from .utils import run_AdHoc
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
@shared_task(bind=True)
|
||||
def run_AdHoc(self, task_tuple, assets,
|
||||
task_name='Ansible AdHoc runner',
|
||||
pattern='all', record=True):
|
||||
|
||||
if not assets:
|
||||
logger.warning('Empty assets, runner cancel')
|
||||
if isinstance(assets[0], Asset):
|
||||
assets = [asset._to_secret_json() for asset in assets]
|
||||
|
||||
runner = AdHocRunner(assets)
|
||||
if record:
|
||||
from .models import TaskRecord
|
||||
if not TaskRecord.objects.filter(uuid=self.request.id):
|
||||
record = TaskRecord(uuid=self.request.id,
|
||||
name=task_name,
|
||||
assets=','.join(str(asset['id']) for asset in assets),
|
||||
module_args=task_tuple,
|
||||
pattern=pattern)
|
||||
record.save()
|
||||
else:
|
||||
record = TaskRecord.objects.get(uuid=self.request.id)
|
||||
record.date_start = timezone.now()
|
||||
ts_start = time.time()
|
||||
logger.warn('Start runner {}'.format(task_name))
|
||||
result = runner.run(task_tuple, pattern=pattern, task_name=task_name)
|
||||
timedelta = round(time.time() - ts_start, 2)
|
||||
summary = runner.clean_result()
|
||||
if record:
|
||||
record.date_finished = timezone.now()
|
||||
record.is_finished = True
|
||||
record.result = json.dumps(result)
|
||||
record.summary = json.dumps(summary)
|
||||
record.timedelta = timedelta
|
||||
if len(summary['failed']) == 0:
|
||||
record.is_success = True
|
||||
else:
|
||||
record.is_success = False
|
||||
record.save()
|
||||
return summary, result
|
||||
|
||||
|
||||
def rerun_AdHoc(uuid):
|
||||
from .models import TaskRecord
|
||||
record = TaskRecord.objects.get(uuid=uuid)
|
||||
@shared_task
|
||||
def rerun_task(task_id):
|
||||
from .models import Task
|
||||
record = Task.objects.get(uuid=task_id)
|
||||
assets = record.assets_json
|
||||
task_tuple = record.module_args
|
||||
pattern = record.pattern
|
||||
task_name = record.name
|
||||
task = run_AdHoc.apply_async((task_tuple, assets),
|
||||
{'pattern': pattern, 'task_name': task_name},
|
||||
task_id=uuid)
|
||||
return task
|
||||
|
||||
|
||||
def push_users(assets, users):
|
||||
"""
|
||||
user: {
|
||||
name: 'web',
|
||||
username: 'web',
|
||||
shell: '/bin/bash',
|
||||
password: '123123123',
|
||||
public_key: 'string',
|
||||
sudo: '/bin/whoami,/sbin/ifconfig'
|
||||
}
|
||||
"""
|
||||
if isinstance(users, dict):
|
||||
users = [users]
|
||||
if isinstance(assets, dict):
|
||||
assets = [assets]
|
||||
task_tuple = []
|
||||
|
||||
for user in users:
|
||||
# 添加用户, 设置公钥, 设置sudo
|
||||
task_tuple.extend([
|
||||
('user', 'name={} shell={} state=present password={}'.format(
|
||||
user['username'], user.get('shell', '/bin/bash'),
|
||||
encrypt_password(user.get('password', None)))),
|
||||
('authorized_key', "user={} state=present key='{}'".format(
|
||||
user['username'], user['public_key'])),
|
||||
('lineinfile',
|
||||
"name=/etc/sudoers state=present regexp='^{0} ALL=(ALL)' "
|
||||
"line='{0} ALL=(ALL) NOPASSWD: {1}' "
|
||||
"validate='visudo -cf %s'".format(
|
||||
user['username'], user.get('sudo', '/bin/whoami')
|
||||
))
|
||||
])
|
||||
task_name = 'Push user {}'.format(','.join([user['name'] for user in users]))
|
||||
task = run_AdHoc.delay(task_tuple, assets, pattern='all', task_name=task_name)
|
||||
return task
|
||||
|
||||
|
||||
return run_AdHoc(task_tuple, assets, pattern=pattern,
|
||||
task_name=task_name, task_id=task_id)
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Date start' %}:</td>
|
||||
<td><b>{{ object.date_start}}</b></td>
|
||||
<td><b>{{ object.date_start }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Date finished' %}:</td>
|
||||
|
@ -64,11 +64,11 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Is finished' %}:</td>
|
||||
<td><b>{{ object.is_finished }}</b></td>
|
||||
<td><b>{{ object.is_finished|yesno:"Yes,No,Unkown" }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Is success ' %}:</td>
|
||||
<td><b>{{ object.is_success }}</b></td>
|
||||
<td><b>{{ object.is_success|yesno:"Yes,No,Unkown" }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Assets ' %}:</td>
|
|
@ -46,10 +46,10 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block table_body %}
|
||||
{% for object in task_record_list %}
|
||||
{% for object in task_list %}
|
||||
<tr class="gradeX">
|
||||
<td class="text-center"><input type="checkbox" class="cbx-term"> </td>
|
||||
<td class="text-center"><a href="{% url 'ops:task-record-detail' pk=object.uuid %}">{{ object.name }}</a></td>
|
||||
<td class="text-center"><a href="{% url 'ops:task-detail' pk=object.uuid %}">{{ object.name }}</a></td>
|
||||
<td class="text-center">{{ object.total_assets|length }}</td>
|
||||
<td class="text-center">
|
||||
{% if object.is_success %}
|
||||
|
@ -68,7 +68,7 @@
|
|||
<td class="text-center">{{ object.date_start }}</td>
|
||||
<td class="text-center">{{ object.timedelta }} s</td>
|
||||
<td class="text-center">
|
||||
<a href="" class="btn btn-xs btn-info">{% trans "Repush" %}</a>
|
||||
<a href="{% url 'ops:task-run' pk=object.uuid %}" class="btn btn-xs btn-info">{% trans "Run again" %}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
|
@ -9,6 +9,7 @@ __all__ = ["urlpatterns"]
|
|||
|
||||
urlpatterns = [
|
||||
# TResource Task url
|
||||
url(r'^task-record/$', views.TaskRecordListView.as_view(), name='task-record-list'),
|
||||
url(r'^task-record/(?P<pk>[0-9a-zA-Z-]+)/$', views.TaskRecordDetailView.as_view(), name='task-record-detail'),
|
||||
url(r'^task/$', views.TaskListView.as_view(), name='task-list'),
|
||||
url(r'^task/(?P<pk>[0-9a-zA-Z-]+)/$', views.TaskDetailView.as_view(), name='task-detail'),
|
||||
url(r'^task/(?P<pk>[0-9a-zA-Z-]+)/run/$', views.TaskRunView.as_view(), name='task-run'),
|
||||
]
|
|
@ -17,7 +17,8 @@ logger = get_logger(__file__)
|
|||
|
||||
def run_AdHoc(task_tuple, assets,
|
||||
task_name='Ansible AdHoc runner',
|
||||
task_id=None, pattern='all', record=True):
|
||||
task_id=None, pattern='all',
|
||||
record=True, verbose=False):
|
||||
|
||||
if not assets:
|
||||
logger.warning('Empty assets, runner cancel')
|
||||
|
@ -29,26 +30,28 @@ def run_AdHoc(task_tuple, assets,
|
|||
|
||||
runner = AdHocRunner(assets)
|
||||
if record:
|
||||
from .models import TaskRecord
|
||||
if not TaskRecord.objects.filter(uuid=task_id):
|
||||
record = TaskRecord(uuid=task_id,
|
||||
name=task_name,
|
||||
assets=','.join(str(asset['id']) for asset in assets),
|
||||
module_args=task_tuple,
|
||||
pattern=pattern)
|
||||
from .models import Task
|
||||
if not Task.objects.filter(uuid=task_id):
|
||||
record = Task(uuid=task_id,
|
||||
name=task_name,
|
||||
assets=','.join(str(asset['id']) for asset in assets),
|
||||
module_args=task_tuple,
|
||||
pattern=pattern)
|
||||
record.save()
|
||||
else:
|
||||
record = TaskRecord.objects.get(uuid=task_id)
|
||||
record = Task.objects.get(uuid=task_id)
|
||||
record.date_start = timezone.now()
|
||||
ts_start = time.time()
|
||||
logger.warn('Start runner {}'.format(task_name))
|
||||
if verbose:
|
||||
logger.debug('Start runner {}'.format(task_name))
|
||||
result = runner.run(task_tuple, pattern=pattern, task_name=task_name)
|
||||
timedelta = round(time.time() - ts_start, 2)
|
||||
summary = runner.clean_result()
|
||||
if record:
|
||||
record.date_finished = timezone.now()
|
||||
record.is_finished = True
|
||||
record.result = json.dumps(result)
|
||||
if verbose:
|
||||
record.result = json.dumps(result)
|
||||
record.summary = json.dumps(summary)
|
||||
record.timedelta = timedelta
|
||||
if len(summary['failed']) == 0:
|
||||
|
@ -57,21 +60,3 @@ def run_AdHoc(task_tuple, assets,
|
|||
record.is_success = False
|
||||
record.save()
|
||||
return summary, result
|
||||
|
||||
|
||||
def rerun_AdHoc(task_id):
|
||||
from .models import TaskRecord
|
||||
record = TaskRecord.objects.get(uuid=task_id)
|
||||
assets = record.assets_json
|
||||
task_tuple = record.module_args
|
||||
pattern = record.pattern
|
||||
task_name = record.name
|
||||
return run_AdHoc(task_tuple, assets, pattern=pattern,
|
||||
task_name=task_name, task_id=task_id)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,33 +1,69 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django.views.generic import ListView, DetailView
|
||||
from django.views.generic import ListView, DetailView, View
|
||||
from django.utils import timezone
|
||||
from django.shortcuts import redirect, reverse
|
||||
|
||||
from .models import TaskRecord
|
||||
from .models import Task
|
||||
from ops.tasks import rerun_task
|
||||
|
||||
|
||||
class TaskRecordListView(ListView):
|
||||
class TaskListView(ListView):
|
||||
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
||||
model = TaskRecord
|
||||
model = Task
|
||||
ordering = ('-date_start',)
|
||||
context_object_name = 'task_record_list'
|
||||
template_name = 'ops/task_record_list.html'
|
||||
context_object_name = 'task_list'
|
||||
template_name = 'ops/task_list.html'
|
||||
date_format = '%m/%d/%Y'
|
||||
keyword = date_from_s = date_to_s = ''
|
||||
|
||||
def get_queryset(self):
|
||||
date_now = timezone.localtime(timezone.now())
|
||||
date_to_default = date_now.strftime(self.date_format)
|
||||
date_from_default = (date_now - timezone.timedelta(7)) \
|
||||
.strftime(self.date_format)
|
||||
|
||||
self.queryset = super(TaskListView, self).get_queryset()
|
||||
self.keyword = self.request.GET.get('keyword', '')
|
||||
self.date_from_s = self.request.GET.get('date_from', date_from_default)
|
||||
self.date_to_s = self.request.GET.get('date_to', date_to_default)
|
||||
|
||||
if self.date_from_s:
|
||||
date_from = datetime.strptime(self.date_from_s, self.date_format)
|
||||
date_from = date_from.replace(tzinfo=timezone.get_current_timezone())
|
||||
self.queryset = self.queryset.filter(date_start__gt=date_from)
|
||||
|
||||
if self.date_to_s:
|
||||
date_to = timezone.datetime.strptime(
|
||||
self.date_to_s + ' 23:59:59', '%m/%d/%Y %H:%M:%S')
|
||||
date_to = date_to.replace(tzinfo=timezone.get_current_timezone())
|
||||
self.queryset = self.queryset.filter(date_finished__lt=date_to)
|
||||
|
||||
if self.keyword:
|
||||
self.queryset = self.queryset.filter(
|
||||
name__icontains=self.keyword,
|
||||
)
|
||||
return self.queryset
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': 'Ops',
|
||||
'action': 'Task record list',
|
||||
'date_from': self.date_from_s,
|
||||
'date_to': self.date_to_s,
|
||||
'keyword': self.keyword,
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(TaskRecordListView, self).get_context_data(**kwargs)
|
||||
return super(TaskListView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class TaskRecordDetailView(DetailView):
|
||||
model = TaskRecord
|
||||
template_name = 'ops/task_record_detail.html'
|
||||
class TaskDetailView(DetailView):
|
||||
model = Task
|
||||
template_name = 'ops/task_detail.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
|
@ -36,4 +72,13 @@ class TaskRecordDetailView(DetailView):
|
|||
'results': json.loads(self.object.summary),
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(TaskRecordDetailView, self).get_context_data(**kwargs)
|
||||
return super(TaskDetailView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class TaskRunView(View):
|
||||
pk_url_kwarg = 'pk'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
pk = kwargs.get(self.pk_url_kwarg)
|
||||
rerun_task.delay(pk)
|
||||
return redirect(reverse('ops:task-detail', kwargs={'pk': pk}))
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from common.utils import setattr_bulk, get_logger
|
||||
from ops.tasks import push_users
|
||||
from .tasks import push_users
|
||||
from .hands import User, UserGroup, Asset, AssetGroup, SystemUser
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
@ -231,7 +231,7 @@ def push_system_user(assets, system_user):
|
|||
|
||||
assets = [asset._to_secret_json() for asset in assets]
|
||||
system_user = system_user._to_secret_json()
|
||||
task = push_users(assets, system_user)
|
||||
task = push_users.delay(assets, system_user)
|
||||
return task.id
|
||||
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<i class="fa fa-coffee"></i> <span class="nav-label">{% trans 'Job Center' %}</span><span class="fa arrow"></span>
|
||||
</a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li id="task-record"><a href="{% url 'ops:task-record-list' %}">{% trans 'Task Record' %}</a></li>
|
||||
<li id="task"><a href="{% url 'ops:task-list' %}">{% trans 'Task' %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
|
Loading…
Reference in New Issue