mirror of https://github.com/jumpserver/jumpserver
[future]ansible运行结果存入数据库中...
parent
eb5f0fcf68
commit
96bc1cd8f1
|
@ -3,6 +3,10 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
|
import ansible.constants as default_config
|
||||||
|
|
||||||
|
|
||||||
from ansible.executor.task_queue_manager import TaskQueueManager
|
from ansible.executor.task_queue_manager import TaskQueueManager
|
||||||
from ansible.inventory import Inventory, Host, Group
|
from ansible.inventory import Inventory, Host, Group
|
||||||
from ansible.vars import VariableManager
|
from ansible.vars import VariableManager
|
||||||
|
@ -10,9 +14,13 @@ from ansible.parsing.dataloader import DataLoader
|
||||||
from ansible.executor import playbook_executor
|
from ansible.executor import playbook_executor
|
||||||
from ansible.utils.display import Display
|
from ansible.utils.display import Display
|
||||||
from ansible.playbook.play import Play
|
from ansible.playbook.play import Play
|
||||||
import ansible.constants as default_config
|
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
|
|
||||||
|
from models import AnsiblePlay, AnsibleTask, AnsibleHostResult
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class AnsibleError(StandardError):
|
class AnsibleError(StandardError):
|
||||||
pass
|
pass
|
||||||
|
@ -175,21 +183,28 @@ class CallbackModule(CallbackBase):
|
||||||
self.output = {}
|
self.output = {}
|
||||||
|
|
||||||
def _new_play(self, play):
|
def _new_play(self, play):
|
||||||
return {
|
"""将Play保持到数据里面
|
||||||
'play': {
|
"""
|
||||||
'name': play.name,
|
ret = {
|
||||||
'id': str(play._uuid)
|
'name': play.name,
|
||||||
},
|
'uuid': str(play._uuid),
|
||||||
'tasks': []
|
'tasks': []
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
play = AnsiblePlay(name=ret['name'], uuid=ret['uuid'], completed=False)
|
||||||
|
play.save()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Save ansible play uuid to database error!, %s" % e.message)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
def _new_task(self, task):
|
def _new_task(self, task):
|
||||||
return {
|
"""将Task保持到数据库里,需要和Play进行关联
|
||||||
'task': {
|
"""
|
||||||
'name': task.name,
|
ret = {
|
||||||
'id': str(task._uuid)
|
'name': task.name,
|
||||||
},
|
'uuid': str(task._uuid),
|
||||||
'failed': {},
|
'failed': {},
|
||||||
'unreachable': {},
|
'unreachable': {},
|
||||||
'skipped': {},
|
'skipped': {},
|
||||||
|
@ -197,23 +212,61 @@ class CallbackModule(CallbackBase):
|
||||||
'success': {}
|
'success': {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
play = AnsiblePlay.objects.get(uuid=self.__play_uuid)
|
||||||
|
task = AnsibleTask(play=play, uuid=ret['uuid'], name=ret['name'])
|
||||||
|
task.save()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Save ansible task uuid to database error!, %s" % e.message)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
@property
|
||||||
|
def __task_uuid(self):
|
||||||
|
return self.results[-1]['tasks'][-1]['uuid']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def __play_uuid(self):
|
||||||
|
return self.results[-1]['uuid']
|
||||||
|
|
||||||
|
def save_task_result(self, result):
|
||||||
|
try:
|
||||||
|
task = AnsibleTask.objects.get(uuid=self.__task_uuid)
|
||||||
|
host_result = AnsibleHostResult(task=task, name=result._host)
|
||||||
|
host_result.save()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Save Ansible host result to database error!, %s" % e.message)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def save_no_host_result(task):
|
||||||
|
try:
|
||||||
|
task = AnsibleTask.objects.get(uuid=task._uuid)
|
||||||
|
host_result = AnsibleHostResult(task=task, no_host="no host to run this task")
|
||||||
|
host_result.save()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Save Ansible host result to database error!, %s" % e.message)
|
||||||
|
|
||||||
def v2_runner_on_failed(self, result, ignore_errors=False):
|
def v2_runner_on_failed(self, result, ignore_errors=False):
|
||||||
|
self.save_task_result(result)
|
||||||
host = result._host
|
host = result._host
|
||||||
self.results[-1]['tasks'][-1]['failed'][host.name] = result._result
|
self.results[-1]['tasks'][-1]['failed'][host.name] = result._result
|
||||||
|
|
||||||
def v2_runner_on_unreachable(self, result):
|
def v2_runner_on_unreachable(self, result):
|
||||||
|
self.save_task_result(result)
|
||||||
host = result._host
|
host = result._host
|
||||||
self.results[-1]['tasks'][-1]['unreachable'][host.name] = result._result
|
self.results[-1]['tasks'][-1]['unreachable'][host.name] = result._result
|
||||||
|
|
||||||
def v2_runner_on_skipped(self, result):
|
def v2_runner_on_skipped(self, result):
|
||||||
|
self.save_task_result(result)
|
||||||
host = result._host
|
host = result._host
|
||||||
self.results[-1]['tasks'][-1]['skipped'][host.name] = result._result
|
self.results[-1]['tasks'][-1]['skipped'][host.name] = result._result
|
||||||
|
|
||||||
def v2_runner_on_no_hosts(self, task):
|
def v2_runner_on_no_hosts(self, task):
|
||||||
self.results[-1]['tasks'][-1]['no_hosts']['name'] = task.name
|
self.save_no_host_result(task)
|
||||||
self.results[-1]['tasks'][-1]['no_hosts']['uuid'] = task.uuid
|
self.results[-1]['tasks'][-1]['no_hosts']['msg'] = "no host to run this task"
|
||||||
|
|
||||||
def v2_runner_on_ok(self, result):
|
def v2_runner_on_ok(self, result):
|
||||||
|
self.save_task_result(result)
|
||||||
host = result._host
|
host = result._host
|
||||||
self.results[-1]['tasks'][-1]['success'][host.name] = result._result
|
self.results[-1]['tasks'][-1]['success'][host.name] = result._result
|
||||||
|
|
||||||
|
@ -224,7 +277,8 @@ class CallbackModule(CallbackBase):
|
||||||
self.results[-1]['tasks'].append(self._new_task(task))
|
self.results[-1]['tasks'].append(self._new_task(task))
|
||||||
|
|
||||||
def v2_playbook_on_stats(self, stats):
|
def v2_playbook_on_stats(self, stats):
|
||||||
"""Display info about playbook statistics"""
|
"""AdHoc模式下这个钩子不会执行
|
||||||
|
"""
|
||||||
hosts = sorted(stats.processed.keys())
|
hosts = sorted(stats.processed.keys())
|
||||||
|
|
||||||
summary = {}
|
summary = {}
|
||||||
|
@ -234,6 +288,7 @@ class CallbackModule(CallbackBase):
|
||||||
|
|
||||||
self.output['plays'] = self.results
|
self.output['plays'] = self.results
|
||||||
self.output['stats'] = summary
|
self.output['stats'] = summary
|
||||||
|
print "summary: %s" % summary
|
||||||
|
|
||||||
|
|
||||||
class PlayBookRunner(InventoryMixin):
|
class PlayBookRunner(InventoryMixin):
|
||||||
|
@ -358,8 +413,19 @@ class ADHocRunner(InventoryMixin):
|
||||||
|
|
||||||
self.play = Play().load(play_data, variable_manager=self.variable_manager, loader=self.loader)
|
self.play = Play().load(play_data, variable_manager=self.variable_manager, loader=self.loader)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def update_db_play(result, ext_code):
|
||||||
|
try:
|
||||||
|
play = AnsiblePlay.objects.get(uuid=result[0]['uuid'])
|
||||||
|
play.completed = True
|
||||||
|
play.status_code = ext_code
|
||||||
|
play.save()
|
||||||
|
except Exception as e:
|
||||||
|
print e.message
|
||||||
|
logger.error("Update Ansible Play Status into database error!, %s" % e.message)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""执行ADHoc 记录日志, 处理结果
|
"""执行ADHoc, 执行完后, 修改AnsiblePlay的状态
|
||||||
"""
|
"""
|
||||||
tqm = None
|
tqm = None
|
||||||
# TODO:日志和结果分析
|
# TODO:日志和结果分析
|
||||||
|
@ -374,13 +440,17 @@ class ADHocRunner(InventoryMixin):
|
||||||
)
|
)
|
||||||
ext_code = tqm.run(self.play)
|
ext_code = tqm.run(self.play)
|
||||||
result = json.dumps(self.results_callback.results)
|
result = json.dumps(self.results_callback.results)
|
||||||
|
|
||||||
|
self.update_db_play(result, ext_code)
|
||||||
|
|
||||||
return ext_code, result
|
return ext_code, result
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
if tqm:
|
if tqm:
|
||||||
tqm.cleanup()
|
tqm.cleanup()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def test_run():
|
||||||
conf = Config()
|
conf = Config()
|
||||||
assets = [
|
assets = [
|
||||||
{
|
{
|
||||||
|
@ -388,7 +458,7 @@ if __name__ == "__main__":
|
||||||
"ip": "192.168.1.119",
|
"ip": "192.168.1.119",
|
||||||
"port": "22",
|
"port": "22",
|
||||||
"username": "root",
|
"username": "root",
|
||||||
"password": "xxx",
|
"password": "tongfang_test",
|
||||||
"key": "asset_private_key",
|
"key": "asset_private_key",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -408,10 +478,14 @@ if __name__ == "__main__":
|
||||||
"gather_facts": "no",
|
"gather_facts": "no",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
dict(action=dict(module='setup')),
|
dict(action=dict(module='setup')),
|
||||||
dict(action=dict(module='command', args='lsdfd'))
|
dict(action=dict(module='command', args='ls'))
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
hoc = ADHocRunner(conf, play_source, *assets)
|
hoc = ADHocRunner(conf, play_source, *assets)
|
||||||
ext_code, result = hoc.run()
|
ext_code, result = hoc.run()
|
||||||
print ext_code
|
print ext_code
|
||||||
print result
|
print result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_run()
|
||||||
|
|
|
@ -10,25 +10,66 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Play(models.Model):
|
class AnsiblePlay(models.Model):
|
||||||
|
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'))
|
||||||
uuid = models.CharField(max_length=128, verbose_name=_('UUID'))
|
|
||||||
completed = models.BooleanField(default=False, verbose_name=_('IsCompleted'))
|
completed = models.BooleanField(default=False, verbose_name=_('IsCompleted'))
|
||||||
status_code = models.IntegerField(default=0, verbose_name=_('StatusCode'))
|
status_code = models.IntegerField(default=0, verbose_name=_('StatusCode'))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return "AnsiblePlay: %s<%s>" % (self.name, self.uuid)
|
||||||
|
|
||||||
|
|
||||||
class Task(models.Model):
|
class AnsibleTask(models.Model):
|
||||||
play = models.ForeignKey(Play, related_name='tasks', blank=True)
|
uuid = models.CharField(max_length=128, verbose_name=_('UUID'), primary_key=True)
|
||||||
name = models.CharField(max_length=128, blank=True, blverbose_name=_('Name'))
|
play = models.ForeignKey(AnsiblePlay, related_name='tasks', blank=True)
|
||||||
uuid = models.CharField(max_length=128, verbose_name=_('UUID'))
|
name = models.CharField(max_length=128, blank=True, verbose_name=_('Name'))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.clean()
|
return "AnsibleTask: %s<%s>" % (self.name, self.uuid)
|
||||||
|
|
||||||
|
def failed(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def success(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HostResult(models.Model):
|
class AnsibleHostResult(models.Model):
|
||||||
task = models.ForeignKey(Task, related_name='host_results', blank=True)
|
task = models.ForeignKey(AnsibleTask, related_name='host_results', blank=True)
|
||||||
|
name = models.CharField(max_length=128, blank=True, verbose_name=_('Name'))
|
||||||
|
status = models.BooleanField(blank=True, default=False, verbose_name=_('Status'))
|
||||||
|
success = models.TextField(blank=True, verbose_name=_('Success'))
|
||||||
|
skipped = models.TextField(blank=True, verbose_name=_('Skipped'))
|
||||||
|
failed = models.TextField(blank=True, verbose_name=_('Failed'))
|
||||||
|
unreachable = models.TextField(blank=True, verbose_name=_('Unreachable'))
|
||||||
|
no_host = models.TextField(blank=True, verbose_name=_('NoHost'))
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return "AnsibleHostResult: %s<%s>" % (self.name, str(self.status))
|
||||||
|
|
||||||
|
def is_failed(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def result(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AnsibleSetup(models.Model):
|
||||||
|
task = models.ForeignKey(AnsibleTask, related_name='host_results', blank=True)
|
||||||
|
name = models.CharField(max_length=128, blank=True, verbose_name=_('Name'))
|
||||||
|
status = models.BooleanField(blank=True, default=False, verbose_name=_('Status'))
|
||||||
|
success = models.TextField(blank=True, verbose_name=_('Success'))
|
||||||
|
skipped = models.TextField(blank=True, verbose_name=_('Skipped'))
|
||||||
|
failed = models.TextField(blank=True, verbose_name=_('Failed'))
|
||||||
|
unreachable = models.TextField(blank=True, verbose_name=_('Unreachable'))
|
||||||
|
no_host = models.TextField(blank=True, verbose_name=_('NoHost'))
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return "AnsibleHostResult: %s<%s>" % (self.name, str(self.status))
|
||||||
|
|
||||||
|
def is_failed(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def result(self):
|
||||||
|
pass
|
||||||
|
|
Loading…
Reference in New Issue