ansible Task接口更上层抽象的基本实现

pull/530/head
yumaojun03 2016-12-19 14:07:21 +08:00
parent 86c5f0d3d3
commit 150e1030c3
13 changed files with 92 additions and 35 deletions

View File

@ -1,7 +1,7 @@
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
from __future__ import unicode_literals from __future__ import unicode_literals
from ..models import HostAlia, UserAlia, CmdAlia, RunasAlia, Extra_conf, Privilege, Sudo, CronTable from ops.models import *
from rest_framework import serializers from rest_framework import serializers
@ -51,3 +51,9 @@ class CronTableSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = CronTable model = CronTable
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
read_only_fields = ('record',)

View File

@ -13,6 +13,7 @@ __all__ = ["HostAliaViewSet",
"PrivilegeViewSet", "PrivilegeViewSet",
"SudoViewSet", "SudoViewSet",
"CronTableViewSet", "CronTableViewSet",
"TaskViewSet",
] ]
@ -63,5 +64,10 @@ class CronTableViewSet(viewsets.ModelViewSet):
serializer_class = CronTableSerializer serializer_class = CronTableSerializer
permission_classes = (AdminUserRequired,) permission_classes = (AdminUserRequired,)
class TaskViewSet(viewsets.ModelViewSet):
queryset = Task.objects.all()
serializer_class = TaskSerializer
permission_classes = (AdminUserRequired,)

View File

@ -2,3 +2,4 @@ from ansible import *
from cron import * from cron import *
from sudo import * from sudo import *
from utils import * from utils import *

View File

@ -9,13 +9,13 @@ from assets.models import Asset
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
__all__ = ["Task", "Tasker", "AnsiblePlay", "AnsibleTask", "AnsibleHostResult"] __all__ = ["Task", "TaskRecord", "AnsiblePlay", "AnsibleTask", "AnsibleHostResult"]
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Tasker(models.Model): class TaskRecord(models.Model):
uuid = models.CharField(max_length=128, verbose_name=_('UUID'), primary_key=True) uuid = models.CharField(max_length=128, verbose_name=_('UUID'), primary_key=True)
name = models.CharField(max_length=128, blank=True, verbose_name=_('Name')) name = models.CharField(max_length=128, blank=True, verbose_name=_('Name'))
start = models.DateTimeField(auto_now_add=True, verbose_name=_('Start Time')) start = models.DateTimeField(auto_now_add=True, verbose_name=_('Start Time'))
@ -51,7 +51,7 @@ class Tasker(models.Model):
class AnsiblePlay(models.Model): class AnsiblePlay(models.Model):
tasker = models.ForeignKey(Tasker, related_name='plays', blank=True, null=True) tasker = models.ForeignKey(TaskRecord, related_name='plays', blank=True, null=True)
uuid = models.CharField(max_length=128, verbose_name=_('UUID'), primary_key=True) uuid = models.CharField(max_length=128, verbose_name=_('UUID'), primary_key=True)
name = models.CharField(max_length=128, verbose_name=_('Name')) name = models.CharField(max_length=128, verbose_name=_('Name'))
@ -73,7 +73,7 @@ class AnsiblePlay(models.Model):
name=forgery_py.name.full_name(), name=forgery_py.name.full_name(),
) )
try: try:
play.tasker = choice(Tasker.objects.all()) play.tasker = choice(TaskRecord.objects.all())
play.save() play.save()
logger.debug('Generate fake play: %s' % play.name) logger.debug('Generate fake play: %s' % play.name)
except Exception as e: except Exception as e:
@ -293,8 +293,16 @@ class AnsibleHostResult(models.Model):
continue continue
class Task(models.Model): class Task(models.Model):
record = models.OneToOneField(TaskRecord)
name = models.CharField(max_length=128, blank=True, verbose_name=_('Name')) name = models.CharField(max_length=128, blank=True, verbose_name=_('Name'))
asset = models.ForeignKey(Asset, null=True, blank=True, related_name='crontables') module_name = models.CharField(max_length=128, verbose_name=_('Ansible Module Name'))
module_args = models.CharField(max_length=512, blank=True, verbose_name=_("Ansible Module Args"))
register = models.CharField(max_length=128, blank=True, verbose_name=_('Ansible Task Register'))
is_gather_facts = models.BooleanField(default=False,verbose_name=_('Is Gather Ansible Facts'))
asset = models.ManyToManyField(Asset, related_name='tasks')
def __unicode__(self): def __unicode__(self):
return "%s %s" % (self.module_name, self.module_args)
def run(self):
pass pass

View File

@ -5,7 +5,7 @@ import logging
from jinja2 import Template from jinja2 import Template
from django.db import models from django.db import models
from django.utils import timezone from django.utils.timezone import now
from assets.models import Asset, AssetGroup from assets.models import Asset, AssetGroup
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -174,7 +174,7 @@ class Sudo(models.Model):
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'), name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'),
help_text=_('Name for this sudo')) help_text=_('Name for this sudo'))
created_time = models.DateTimeField(verbose_name=_('Created Time'), default=timezone.now(), created_time = models.DateTimeField(verbose_name=_('Created Time'), auto_created=True,
help_text=_('The create time of this sudo')) help_text=_('The create time of this sudo'))
modify_time = models.DateTimeField(auto_now=True, verbose_name=_('Modify Time'), modify_time = models.DateTimeField(auto_now=True, verbose_name=_('Modify Time'),
help_text=_('The recent modify time of this sudo')) help_text=_('The recent modify time of this sudo'))
@ -310,7 +310,7 @@ root ALL=(ALL:ALL) ALL
seed() seed()
for i in range(count): for i in range(count):
sudo = cls(name=forgery_py.name.full_name(), sudo = cls(name=forgery_py.name.full_name(),
created_time=timezone.now() created_time=now()
) )
try: try:
sudo.save() sudo.save()

View File

@ -9,6 +9,6 @@ __all__ = ["generate_fake"]
def generate_fake(): def generate_fake():
for cls in (Tasker, AnsiblePlay, AnsibleTask, AnsibleHostResult, CronTable, for cls in (TaskRecord, AnsiblePlay, AnsibleTask, AnsibleHostResult, CronTable,
HostAlia, UserAlia, CmdAlia, RunasAlia, Privilege, Sudo): HostAlia, UserAlia, CmdAlia, RunasAlia, Privilege, Sudo):
cls.generate_fake() cls.generate_fake()

View File

@ -3,7 +3,7 @@ from __future__ import unicode_literals
from ops.tasks import _celery_tasks from ops.tasks import _celery_tasks
from ops.models import Tasker from ops.models import TaskRecord
from uuid import uuid1 from uuid import uuid1
from celery.result import AsyncResult from celery.result import AsyncResult
@ -23,7 +23,7 @@ def get_result(task_id):
def __get_result_by_tasker_id(tasker_uuid, deal_method): def __get_result_by_tasker_id(tasker_uuid, deal_method):
tasker = Tasker.objects.get(uuid=tasker_uuid) tasker = TaskRecord.objects.get(uuid=tasker_uuid)
total = tasker.total_hosts total = tasker.total_hosts
total_len = len(total) total_len = len(total)
host_results = [] host_results = []

View File

@ -3,7 +3,7 @@
{% block table_search %} {% block table_search %}
{% endblock %} {% endblock %}
{% block table_container %} {% block table_container %}
<div class="uc pull-left m-l-5 m-r-5"><a href="{% url "users:user-create" %}" class="btn btn-sm btn-primary"> {% trans "Create sudo" %} </a></div> <div class="uc pull-left m-l-5 m-r-5"><a href="{% url "ops:page-task-create" %}" class="btn btn-sm btn-primary"> {% trans "Create task" %} </a></div>
{#<div class="uc pull-left"><a href="javascript:void(0);" class="btn btnbtn-sm btn-primary" data-toggle="modal" data-target="#user_import_modal"> {% trans "Import user" %} </a></div>#} {#<div class="uc pull-left"><a href="javascript:void(0);" class="btn btnbtn-sm btn-primary" data-toggle="modal" data-target="#user_import_modal"> {% trans "Import user" %} </a></div>#}
<table class="table table-striped table-bordered table-hover " id="sudo_list_table"> <table class="table table-striped table-bordered table-hover " id="sudo_list_table">
<thead> <thead>
@ -12,8 +12,9 @@
<input id="" type="checkbox" class="ipt_check_all"> <input id="" type="checkbox" class="ipt_check_all">
</th> </th>
<th class="text-center">{% trans 'Name' %}</th> <th class="text-center">{% trans 'Name' %}</th>
<th class="text-center">{% trans 'Privileges' %}</th> <th class="text-center">{% trans 'UUID' %}</th>
<th class="text-center">{% trans 'Extra Lines' %}</th> <th class="text-center">{% trans 'Start' %}</th>
<th class="text-center">{% trans 'Completed' %}</th>
<th class="text-center">{% trans 'Action' %}</th> <th class="text-center">{% trans 'Action' %}</th>
</tr> </tr>
@ -35,8 +36,6 @@
</div> </div>
</div> </div>
</div> </div>
{#{% include "users/_user_bulk_update_modal.html" %}#}
{#{% include "users/_user_import_modal.html" %}#}
{% endblock %} {% endblock %}
{% block content_bottom_left %}{% endblock %} {% block content_bottom_left %}{% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
@ -47,23 +46,23 @@ $(document).ready(function(){
ele: $('#sudo_list_table'), ele: $('#sudo_list_table'),
columnDefs: [ columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) { {targets: 1, createdCell: function (td, cellData, rowData) {
var detail_btn = '<a href="{% url "ops:page-sudo-detail" pk=99991937 %}">' + cellData + '</a>'; var detail_btn = '<a href="{% url "ops:page-task-detail" pk=99991937 %}">' + cellData + '</a>';
$(td).html(detail_btn.replace('99991937', rowData.id)); $(td).html(detail_btn.replace('99991937', rowData.id));
}}, }},
{targets: 4, createdCell: function (td, cellData, rowData) { {targets: 3, createdCell: function (td, cellData) {
var update_btn = '<a href="{% url "users:user-update" pk=99991937 %}" class="btn btn-xs btn-info m-l-xs">{% trans "Update" %}</a>'.replace('99991937', cellData); if (!cellData) {
var preview_btn = '<a href="{% url "users:user-update" pk=99991937 %}" class="btn btn-xs btn-info m-l-xs">{% trans "Preview" %}</a>'.replace('99991937', cellData); $(td).html('<i class="fa fa-times text-danger"></i>')
var job_btn = '<a href="{% url "users:user-update" pk=99991937 %}" class="btn btn-xs btn-primary m-l-xs">{% trans "Job" %}</a>'.replace('99991937', cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData);
if (rowData.id === 1 || rowData.username == "admin") {
$(td).html(update_btn)
} else { } else {
$(td).html(preview_btn + job_btn + update_btn + del_btn) $(td).html('<i class="fa fa-check text-navy"></i>')
} }
}},
{targets: 4, createdCell: function (td, cellData) {
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData)
$(td).html(del_btn)
}}], }}],
ajax_url: '{% url "api-ops:sudo-list" %}', ajax_url: '{% url "api-ops:task-list" %}',
columns: [{data: "id"}, {data: "name" }, {data: "privilege_items" }, {data: "extra_lines" }, {data: "id" }], columns: [{data: "name"}, {data: "uuid" }, {data: "start" }, {data: "completed" }, {data: "id" }],
op_html: $('#actions').html() op_html: $('#actions').html()
}; };
var table = jumpserver.initDataTable(options); var table = jumpserver.initDataTable(options);

View File

@ -15,5 +15,6 @@ api_router.register(r'v1/extra_conf', v1_api.ExtraconfViewSet)
api_router.register(r'v1/privilege', v1_api.PrivilegeViewSet) api_router.register(r'v1/privilege', v1_api.PrivilegeViewSet)
api_router.register(r'v1/sudo', v1_api.SudoViewSet) api_router.register(r'v1/sudo', v1_api.SudoViewSet)
api_router.register(r'v1/cron', v1_api.CronTableViewSet) api_router.register(r'v1/cron', v1_api.CronTableViewSet)
api_router.register(r'v1/task', v1_api.TaskViewSet)
urlpatterns = api_router.urls urlpatterns = api_router.urls

View File

@ -19,4 +19,10 @@ urlpatterns = [
url(r'^cron/create$', page_view.CronCreateView.as_view(), name='page-cron-create'), url(r'^cron/create$', page_view.CronCreateView.as_view(), name='page-cron-create'),
url(r'^cron/(?P<pk>[0-9]+)/detail$', page_view.CronDetailView.as_view(), name='page-cron-detail'), url(r'^cron/(?P<pk>[0-9]+)/detail$', page_view.CronDetailView.as_view(), name='page-cron-detail'),
url(r'^cron/(?P<pk>[0-9]+)/update$', page_view.CronUpdateView.as_view(), name='page-cron-update'), url(r'^cron/(?P<pk>[0-9]+)/update$', page_view.CronUpdateView.as_view(), name='page-cron-update'),
# TResource Task url
url(r'^task/list$', page_view.TaskListView.as_view(), name='page-task-list'),
url(r'^task/create$', page_view.TaskCreateView.as_view(), name='page-task-create'),
url(r'^task/(?P<pk>[0-9]+)/detail$', page_view.TaskDetailView.as_view(), name='page-task-detail'),
url(r'^task/(?P<pk>[0-9]+)/update$', page_view.TaskUpdateView.as_view(), name='page-task-update'),
] ]

View File

@ -18,7 +18,7 @@ from ansible.utils.display import Display
from ansible.playbook.play import Play from ansible.playbook.play import Play
from ansible.plugins.callback import CallbackBase from ansible.plugins.callback import CallbackBase
from ops.models import Tasker, AnsiblePlay, AnsibleTask, AnsibleHostResult from ops.models import TaskRecord, AnsiblePlay, AnsibleTask, AnsibleHostResult
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -196,7 +196,7 @@ class CallbackModule(CallbackBase):
} }
try: try:
tasker = Tasker.objects.get(uuid=self.tasker_id) tasker = TaskRecord.objects.get(uuid=self.tasker_id)
play = AnsiblePlay(tasker, name=ret['name'], uuid=ret['uuid']) play = AnsiblePlay(tasker, name=ret['name'], uuid=ret['uuid'])
play.save() play.save()
except Exception as e: except Exception as e:
@ -429,7 +429,7 @@ class ADHocRunner(InventoryMixin):
@staticmethod @staticmethod
def update_db_tasker(tasker_id, ext_code): def update_db_tasker(tasker_id, ext_code):
try: try:
tasker = Tasker.objects.get(uuid=tasker_id) tasker = TaskRecord.objects.get(uuid=tasker_id)
tasker.end = timezone.now() tasker.end = timezone.now()
tasker.completed = True tasker.completed = True
tasker.exit_code = ext_code tasker.exit_code = ext_code
@ -440,7 +440,7 @@ class ADHocRunner(InventoryMixin):
def create_db_tasker(self, name, uuid): def create_db_tasker(self, name, uuid):
try: try:
hosts = [host.get('name') for host in self.hosts] hosts = [host.get('name') for host in self.hosts]
tasker = Tasker(name=name, uuid=uuid, hosts=','.join(hosts), start=timezone.now()) tasker = TaskRecord(name=name, uuid=uuid, hosts=','.join(hosts), start=timezone.now())
tasker.save() tasker.save()
except Exception as e: except Exception as e:
logger.error("Save Tasker to database error!, %s" % e.message) logger.error("Save Tasker to database error!, %s" % e.message)

View File

@ -56,3 +56,32 @@ class CronDetailView(DetailView):
context_object_name = 'cron' context_object_name = 'cron'
template_name = 'cron/detail.html' template_name = 'cron/detail.html'
class TaskListView(AdminUserRequiredMixin, ListView):
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
model = Task
context_object_name = 'tasks'
template_name = 'task/list.html'
def get_context_data(self, **kwargs):
context = {
'task': 'Assets',
'action': 'Create asset',
}
kwargs.update(context)
return super(TaskListView, self).get_context_data(**kwargs)
class TaskCreateView(AdminUserRequiredMixin, CreateView):
model = Task
template_name = 'task/create.html'
class TaskUpdateView(AdminUserRequiredMixin, UpdateView):
model = Task
template_name = 'task/update.html'
class TaskDetailView(DetailView):
model = Task
context_object_name = 'task'
template_name = 'task/detail.html'

View File

@ -46,6 +46,7 @@
<i class="fa fa-coffee"></i> <span class="nav-label">{% trans 'Job Center' %}</span><span class="fa arrow"></span> <i class="fa fa-coffee"></i> <span class="nav-label">{% trans 'Job Center' %}</span><span class="fa arrow"></span>
</a> </a>
<ul class="nav nav-second-level"> <ul class="nav nav-second-level">
<li id="task"><a href="{% url 'ops:page-task-list' %}">{% trans 'Task' %}</a></li>
<li id="sudo"><a href="{% url 'ops:page-sudo-list' %}">{% trans 'Sudo' %}</a></li> <li id="sudo"><a href="{% url 'ops:page-sudo-list' %}">{% trans 'Sudo' %}</a></li>
<li id="cron"><a href="{% url 'ops:page-cron-list' %}">{% trans 'Cron' %}</a></li> <li id="cron"><a href="{% url 'ops:page-cron-list' %}">{% trans 'Cron' %}</a></li>
</ul> </ul>