Commit 267bb024 authored by ibuler's avatar ibuler

修改exec 和 MyRUnner

parent 255e3a04
This diff is collapsed.
...@@ -3,7 +3,7 @@ from django.db import models ...@@ -3,7 +3,7 @@ from django.db import models
class Log(models.Model): class Log(models.Model):
user = models.CharField(max_length=20, null=True) user = models.CharField(max_length=20, null=True)
host = models.CharField(max_length=20, null=True) host = models.CharField(max_length=200, null=True)
remote_ip = models.CharField(max_length=100) remote_ip = models.CharField(max_length=100)
login_type = models.CharField(max_length=100) login_type = models.CharField(max_length=100)
log_path = models.CharField(max_length=100) log_path = models.CharField(max_length=100)
...@@ -24,5 +24,13 @@ class Alert(models.Model): ...@@ -24,5 +24,13 @@ class Alert(models.Model):
class TtyLog(models.Model): class TtyLog(models.Model):
log = models.ForeignKey(Log) log = models.ForeignKey(Log)
datetime = models.DateTimeField() datetime = models.DateTimeField(auto_now=True)
cmd = models.CharField(max_length=200) cmd = models.CharField(max_length=200)
class ExecLog(models.Model):
user = models.CharField(max_length=100)
host = models.TextField()
cmd = models.TextField()
datetime = models.DateTimeField(auto_now=True)
...@@ -117,9 +117,9 @@ class MyRunner(MyInventory): ...@@ -117,9 +117,9 @@ class MyRunner(MyInventory):
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(MyRunner, self).__init__(*args, **kwargs) super(MyRunner, self).__init__(*args, **kwargs)
self.results = {} self.results_raw = {}
def run(self, module_name, module_args='', timeout=10, forks=10, pattern='', def run(self, module_name='shell', module_args='', timeout=10, forks=10, pattern='',
sudo=False, sudo_user='root', sudo_pass=''): sudo=False, sudo_user='root', sudo_pass=''):
""" """
run module from andible ad-hoc. run module from andible ad-hoc.
...@@ -137,23 +137,29 @@ class MyRunner(MyInventory): ...@@ -137,23 +137,29 @@ class MyRunner(MyInventory):
become_user=sudo_user, become_user=sudo_user,
become_pass=sudo_pass become_pass=sudo_pass
) )
self.results = hoc.run() self.results_raw = hoc.run()
return self.results return self.results_raw
def get_result(self): @property
result = {'failed': {}, 'ok': []} def results(self):
dark = self.results.get('dark') """
contacted = self.results.get('contacted') {'failed': {'localhost': ''}, 'ok': {'jumpserver': ''}}
"""
result = {'failed': {}, 'ok': {}}
dark = self.results_raw.get('dark')
contacted = self.results_raw.get('contacted')
if dark: if dark:
for host, info in dark.items(): for host, info in dark.items():
result['failed'][host] = info.get('msg') result['failed'][host] = info.get('msg')
if contacted: if contacted:
for host, info in contacted.items(): for host, info in contacted.items():
if info.get('msg'): if info.get('failed'):
result['failed'][host] = info.get('msg') result['failed'][host] = info.get('msg') + info.get('stderr', '')
elif info.get('stderr'):
result['failed'][host] = info.get('stderr') + str(info.get('warnings'))
else: else:
result['ok'].append(host) result['ok'][host] = info.get('stdout')
return result return result
...@@ -163,9 +169,9 @@ class Command(MyInventory): ...@@ -163,9 +169,9 @@ class Command(MyInventory):
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Command, self).__init__(*args, **kwargs) super(Command, self).__init__(*args, **kwargs)
self.results = {} self.results_raw = {}
def run(self, command, module_name="command", timeout=10, forks=10, pattern='*'): def run(self, command, module_name="command", timeout=10, forks=10, pattern=''):
""" """
run command from andible ad-hoc. run command from andible ad-hoc.
command : 必须是一个需要执行的命令字符串, 比如 command : 必须是一个需要执行的命令字符串, 比如
...@@ -183,25 +189,34 @@ class Command(MyInventory): ...@@ -183,25 +189,34 @@ class Command(MyInventory):
pattern=pattern, pattern=pattern,
forks=forks, forks=forks,
) )
self.results = hoc.run() self.results_raw = hoc.run()
ret = {} @property
def result(self):
result = {}
for k, v in self.results_raw.items():
if k == 'dark':
for host, info in v.items():
result[host] = {'dark': info.get('msg')}
elif k == 'contacted':
for host, info in v.items():
result[host] = {}
if info.get('stdout'):
result[host]['stdout'] = info.get('stdout')
elif info.get('stderr'):
result[host]['stderr'] = info.get('stderr')
return result
@property
def state(self):
result = {}
if self.stdout: if self.stdout:
data['ok'] = self.stdout result['ok'] = self.stdout
if self.stderr: if self.stderr:
data['err'] = self.stderr result['err'] = self.stderr
if self.dark: if self.dark:
data['dark'] = self.dark result['dark'] = self.dark
return result
return data
@property
def raw_results(self):
"""
get the ansible raw results.
"""
return self.results
@property @property
def exec_time(self): def exec_time(self):
...@@ -209,7 +224,7 @@ class Command(MyInventory): ...@@ -209,7 +224,7 @@ class Command(MyInventory):
get the command execute time. get the command execute time.
""" """
result = {} result = {}
all = self.results.get("contacted") all = self.results_raw.get("contacted")
for key, value in all.iteritems(): for key, value in all.iteritems():
result[key] = { result[key] = {
"start": value.get("start"), "start": value.get("start"),
...@@ -223,7 +238,7 @@ class Command(MyInventory): ...@@ -223,7 +238,7 @@ class Command(MyInventory):
get the comamnd standard output. get the comamnd standard output.
""" """
result = {} result = {}
all = self.results.get("contacted") all = self.results_raw.get("contacted")
for key, value in all.iteritems(): for key, value in all.iteritems():
result[key] = value.get("stdout") result[key] = value.get("stdout")
return result return result
...@@ -234,7 +249,7 @@ class Command(MyInventory): ...@@ -234,7 +249,7 @@ class Command(MyInventory):
get the command standard error. get the command standard error.
""" """
result = {} result = {}
all = self.results.get("contacted") all = self.results_raw.get("contacted")
for key, value in all.iteritems(): for key, value in all.iteritems():
if value.get("stderr") or value.get("warnings"): if value.get("stderr") or value.get("warnings"):
result[key] = { result[key] = {
...@@ -247,7 +262,7 @@ class Command(MyInventory): ...@@ -247,7 +262,7 @@ class Command(MyInventory):
""" """
get the dark results. get the dark results.
""" """
return self.results.get("dark") return self.results_raw.get("dark")
class Tasks(Command): class Tasks(Command):
......
...@@ -55,6 +55,6 @@ class PermPush(models.Model): ...@@ -55,6 +55,6 @@ class PermPush(models.Model):
is_public_key = models.BooleanField(default=False) is_public_key = models.BooleanField(default=False)
is_password = models.BooleanField(default=False) is_password = models.BooleanField(default=False)
success = models.BooleanField(default=False) success = models.BooleanField(default=False)
result = models.TextField() result = models.TextField(default='')
date_added = models.DateTimeField(auto_now=True) date_added = models.DateTimeField(auto_now=True)
...@@ -217,6 +217,7 @@ def gen_resource(ob, perm=None): ...@@ -217,6 +217,7 @@ def gen_resource(ob, perm=None):
for asset in ob: for asset in ob:
info = get_asset_info(asset) info = get_asset_info(asset)
res.append(info) res.append(info)
logger.debug('生成res: %s' % res)
return res return res
...@@ -295,9 +296,11 @@ def get_role_push_host(role): ...@@ -295,9 +296,11 @@ def get_role_push_host(role):
asset_all = Asset.objects.all() asset_all = Asset.objects.all()
asset_pushed = {} asset_pushed = {}
for push in pushs: for push in pushs:
print push.result
asset_pushed[push.asset] = {'success': push.success, 'key': push.is_public_key, 'password': push.is_password, asset_pushed[push.asset] = {'success': push.success, 'key': push.is_public_key, 'password': push.is_password,
'result': push.result} 'result': push.result}
asset_no_push = set(asset_all) - set(asset_pushed.keys()) asset_no_push = set(asset_all) - set(asset_pushed.keys())
print asset_no_push, asset_pushed
return asset_pushed, asset_no_push return asset_pushed, asset_no_push
......
...@@ -96,7 +96,7 @@ def get_role_key(user, role): ...@@ -96,7 +96,7 @@ def get_role_key(user, role):
with open(os.path.join(role.key_path, 'id_rsa')) as fk: with open(os.path.join(role.key_path, 'id_rsa')) as fk:
with open(user_role_key_path, 'w') as fu: with open(user_role_key_path, 'w') as fu:
fu.write(fk.read()) fu.write(fk.read())
logger.debug("创建新的用户角色key %s" % user_role_key_path) logger.debug(u"创建新的用户角色key %s" % user_role_key_path)
chown(user_role_key_path, user.username) chown(user_role_key_path, user.username)
os.chmod(user_role_key_path, 0600) os.chmod(user_role_key_path, 0600)
return user_role_key_path return user_role_key_path
......
...@@ -313,14 +313,14 @@ def upload(request): ...@@ -313,14 +313,14 @@ def upload(request):
runner = MyRunner(res) runner = MyRunner(res)
runner.run('copy', module_args='src=%s dest=%s directory_mode' runner.run('copy', module_args='src=%s dest=%s directory_mode'
% (upload_dir, upload_dir), pattern='*') % (upload_dir, upload_dir), pattern='*')
ret = runner.get_result() ret = runner.results
logger.debug(ret) logger.debug(ret)
if ret.get('failed'): if ret.get('failed'):
error = '上传目录: %s <br> 上传失败: [ %s ] <br>上传成功 [ %s ]' % (upload_dir, error = '上传目录: %s <br> 上传失败: [ %s ] <br>上传成功 [ %s ]' % (upload_dir,
', '.join(ret.get('failed').keys()), ', '.join(ret.get('failed').keys()),
', '.join(ret.get('ok'))) ', '.join(ret.get('ok').keys()))
return HttpResponse(error, status=500) return HttpResponse(error, status=500)
msg = '上传目录: %s <br> 传送成功 [ %s ]' % (upload_dir, ', '.join(ret.get('ok'))) msg = '上传目录: %s <br> 传送成功 [ %s ]' % (upload_dir, ', '.join(ret.get('ok')).keys())
return HttpResponse(msg) return HttpResponse(msg)
return my_render('upload.html', locals(), request) return my_render('upload.html', locals(), request)
...@@ -345,7 +345,7 @@ def download(request): ...@@ -345,7 +345,7 @@ def download(request):
res = gen_resource({'user': user, 'asset': asset_select}) res = gen_resource({'user': user, 'asset': asset_select})
runner = MyRunner(res) runner = MyRunner(res)
runner.run('fetch', module_args='src=%s dest=%s' % (file_path, upload_dir), pattern='*') runner.run('fetch', module_args='src=%s dest=%s' % (file_path, upload_dir), pattern='*')
logger.debug(runner.get_result()) logger.debug(runner.results)
os.chdir('/tmp') os.chdir('/tmp')
tmp_dir_name = os.path.basename(upload_dir) tmp_dir_name = os.path.basename(upload_dir)
tar_file = '%s.tar.gz' % upload_dir tar_file = '%s.tar.gz' % upload_dir
......
...@@ -8,7 +8,7 @@ import sys ...@@ -8,7 +8,7 @@ import sys
import os.path import os.path
import threading import threading
import datetime import datetime
import urllib import re
import tornado.ioloop import tornado.ioloop
import tornado.options import tornado.options
...@@ -24,7 +24,7 @@ from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE ...@@ -24,7 +24,7 @@ from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE
import select import select
from connect import Tty, User, Asset, PermRole, logger, get_object, PermRole, gen_resource from connect import Tty, User, Asset, PermRole, logger, get_object, PermRole, gen_resource
from connect import TtyLog, Log, Session, user_have_perm, get_group_user_perm, Command from connect import TtyLog, Log, Session, user_have_perm, get_group_user_perm, MyRunner, ExecLog
try: try:
import simplejson as json import simplejson as json
...@@ -218,7 +218,7 @@ class ExecHandler(tornado.websocket.WebSocketHandler): ...@@ -218,7 +218,7 @@ class ExecHandler(tornado.websocket.WebSocketHandler):
self.id = 0 self.id = 0
self.user = None self.user = None
self.role = None self.role = None
self.cmd = None self.runner = None
self.assets = [] self.assets = []
self.perm = {} self.perm = {}
super(ExecHandler, self).__init__(*args, **kwargs) super(ExecHandler, self).__init__(*args, **kwargs)
...@@ -238,32 +238,50 @@ class ExecHandler(tornado.websocket.WebSocketHandler): ...@@ -238,32 +238,50 @@ class ExecHandler(tornado.websocket.WebSocketHandler):
self.write_message('No perm that role %s' % role_name) self.write_message('No perm that role %s' % role_name)
self.close() self.close()
self.assets = self.perm.get('role').get(self.role).get('asset') self.assets = self.perm.get('role').get(self.role).get('asset')
res = gen_resource({'user': self.user, 'asset': self.assets, 'role': self.role}) res = gen_resource({'user': self.user, 'asset': self.assets, 'role': self.role})
logger.debug('Web执行命令res: %s' % res) self.runner = MyRunner(res)
self.cmd = Command(res) message = '有权限的主机: ' + ', '.join([asset.hostname for asset in self.assets])
message = '有权限的主机:' + ', '.join([asset.hostname for asset in self.assets]) self.__class__.clients.append(self)
self.write_message(message) self.write_message(message)
def on_message(self, message): def on_message(self, message):
data = json.loads(message) data = json.loads(message)
pattern = data.get('pattern', '') pattern = data.get('pattern', '')
command = data.get('command', '') command = data.get('command', '')
asset_name_str = '匹配主机: ' asset_name_str = ''
if pattern and command: if pattern and command:
for inv in self.cmd.inventory.get_hosts(pattern=pattern): for inv in self.runner.inventory.get_hosts(pattern=pattern):
asset_name_str += '\n%s' % inv.name asset_name_str += '%s ' % inv.name
self.write_message(asset_name_str) self.write_message('匹配主机: ' + asset_name_str)
self.write_message('<span style="color: yellow">Ansible> %s</span>\n\n' % command) self.write_message('<span style="color: yellow">Ansible> %s</span>\n\n' % command)
result = self.cmd.run(module_name='shell', command=command, pattern=pattern) self.__class__.tasks.append(MyThread(target=self.run_cmd, args=(command, pattern)))
for k, v in result.items(): ExecLog(host=asset_name_str, cmd=command).save()
for host, output in v.items():
if k == 'ok': for t in self.__class__.tasks:
header = "<span style='color: green'>[ %s => %s]</span>\n" % (host, 'Ok') if t.is_alive():
else: continue
header = "<span style='color: red'>[ %s => %s]</span>\n" % (host, 'failed') try:
self.write_message(header) t.setDaemon(True)
self.write_message(output) t.start()
self.write_message('\n~o~ Task finished ~o~\n') except RuntimeError:
pass
def run_cmd(self, command, pattern):
self.runner.run('shell', command, pattern=pattern)
for k, v in self.runner.results.items():
for host, output in v.items():
if k == 'ok':
header = "<span style='color: green'>[ %s => %s]</span>\n" % (host, 'Ok')
else:
header = "<span style='color: red'>[ %s => %s]</span>\n" % (host, 'failed')
self.write_message(header)
self.write_message(output)
self.write_message('\n~o~ Task finished ~o~\n')
def on_close(self):
logger.debug('关闭web_exec请求')
class WebTerminalHandler(tornado.websocket.WebSocketHandler): class WebTerminalHandler(tornado.websocket.WebSocketHandler):
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=320, initial-scale=1"> <meta name="viewport" content="width=320, initial-scale=1">
<title>Chat</title> <title>Jumpserver Exec Terminal</title>
<style type="text/css"></style> <style type="text/css"></style>
</head> </head>
......
...@@ -194,7 +194,7 @@ ...@@ -194,7 +194,7 @@
title: title, title: title,
maxmin: true, maxmin: true,
shade: false, shade: false,
area: ['800px', '700px'], area: ['800px', '600px'],
content: new_url+data+'&check_assets='+check_assets content: new_url+data+'&check_assets='+check_assets
}); });
//window.open(new_url + data, '', 'location=no, resizeable=no, height=410, width=625, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,status=no'); //window.open(new_url + data, '', 'location=no, resizeable=no, height=410, width=625, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,status=no');
...@@ -282,7 +282,7 @@ ...@@ -282,7 +282,7 @@
type: 2, type: 2,
title: title, title: title,
maxmin: true, maxmin: true,
area: ['800px', '700px'], area: ['800px', '600px'],
shade: false, shade: false,
content: new_url content: new_url
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment