diff --git a/apps/assets/tasks.py b/apps/assets/tasks.py index 8610deb2e..89e2e410e 100644 --- a/apps/assets/tasks.py +++ b/apps/assets/tasks.py @@ -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'] diff --git a/apps/audits/views.py b/apps/audits/views.py index 94039d1d8..20bc3f8aa 100644 --- a/apps/audits/views.py +++ b/apps/audits/views.py @@ -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): diff --git a/apps/ops/ansible/runner.py b/apps/ops/ansible/runner.py index 147531105..1af3d7a0d 100644 --- a/apps/ops/ansible/runner.py +++ b/apps/ops/ansible/runner.py @@ -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 diff --git a/apps/ops/models.py b/apps/ops/models.py index 53f6ce291..3ece921f3 100644 --- a/apps/ops/models.py +++ b/apps/ops/models.py @@ -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')) diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py index 6101ab932..0718b18ca 100644 --- a/apps/ops/tasks.py +++ b/apps/ops/tasks.py @@ -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) diff --git a/apps/ops/templates/ops/task_record_detail.html b/apps/ops/templates/ops/task_detail.html similarity index 98% rename from apps/ops/templates/ops/task_record_detail.html rename to apps/ops/templates/ops/task_detail.html index bd71a5a90..a0f38e86c 100644 --- a/apps/ops/templates/ops/task_record_detail.html +++ b/apps/ops/templates/ops/task_detail.html @@ -52,7 +52,7 @@ {% trans 'Date start' %}: - {{ object.date_start}} + {{ object.date_start }} {% trans 'Date finished' %}: @@ -64,11 +64,11 @@ {% trans 'Is finished' %}: - {{ object.is_finished }} + {{ object.is_finished|yesno:"Yes,No,Unkown" }} {% trans 'Is success ' %}: - {{ object.is_success }} + {{ object.is_success|yesno:"Yes,No,Unkown" }} {% trans 'Assets ' %}: diff --git a/apps/ops/templates/ops/task_record_list.html b/apps/ops/templates/ops/task_list.html similarity index 94% rename from apps/ops/templates/ops/task_record_list.html rename to apps/ops/templates/ops/task_list.html index fe4a2412e..cb64849a4 100644 --- a/apps/ops/templates/ops/task_record_list.html +++ b/apps/ops/templates/ops/task_list.html @@ -46,10 +46,10 @@ {% endblock %} {% block table_body %} - {% for object in task_record_list %} + {% for object in task_list %} - {{ object.name }} + {{ object.name }} {{ object.total_assets|length }} {% if object.is_success %} @@ -68,7 +68,7 @@ {{ object.date_start }} {{ object.timedelta }} s - {% trans "Repush" %} + {% trans "Run again" %} {% endfor %} diff --git a/apps/ops/urls/view_urls.py b/apps/ops/urls/view_urls.py index c8ef31529..17a9b77ed 100644 --- a/apps/ops/urls/view_urls.py +++ b/apps/ops/urls/view_urls.py @@ -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[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[0-9a-zA-Z-]+)/$', views.TaskDetailView.as_view(), name='task-detail'), + url(r'^task/(?P[0-9a-zA-Z-]+)/run/$', views.TaskRunView.as_view(), name='task-run'), ] \ No newline at end of file diff --git a/apps/ops/utils.py b/apps/ops/utils.py index b2b4d7b4f..9aa49a7d1 100644 --- a/apps/ops/utils.py +++ b/apps/ops/utils.py @@ -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) - - - - - - - diff --git a/apps/ops/views.py b/apps/ops/views.py index 33720dbc8..dadf71faf 100644 --- a/apps/ops/views.py +++ b/apps/ops/views.py @@ -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})) diff --git a/apps/perms/utils.py b/apps/perms/utils.py index 1e69d5af3..4d3e8f332 100644 --- a/apps/perms/utils.py +++ b/apps/perms/utils.py @@ -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 diff --git a/apps/templates/_nav.html b/apps/templates/_nav.html index a19585727..6792a22b2 100644 --- a/apps/templates/_nav.html +++ b/apps/templates/_nav.html @@ -49,7 +49,7 @@ {% trans 'Job Center' %}