mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-07-13 14:44:47 +00:00
修改exec 和 MyRUnner
This commit is contained in:
parent
255e3a043a
commit
267bb02417
142
connect.py
142
connect.py
@ -27,7 +27,8 @@ from jumpserver.api import logger, Log, TtyLog, get_role_key, CRYPTOR, bash, get
|
|||||||
from jperm.perm_api import gen_resource, get_group_asset_perm, get_group_user_perm, user_have_perm, PermRole
|
from jperm.perm_api import gen_resource, get_group_asset_perm, get_group_user_perm, user_have_perm, PermRole
|
||||||
from jumpserver.settings import LOG_DIR
|
from jumpserver.settings import LOG_DIR
|
||||||
from jperm.ansible_api import Command, MyRunner
|
from jperm.ansible_api import Command, MyRunner
|
||||||
from jlog.log_api import escapeString
|
# from jlog.log_api import escapeString
|
||||||
|
from jlog.models import ExecLog
|
||||||
|
|
||||||
login_user = get_object(User, username=getpass.getuser())
|
login_user = get_object(User, username=getpass.getuser())
|
||||||
|
|
||||||
@ -468,16 +469,6 @@ class Nav(object):
|
|||||||
Print prompt
|
Print prompt
|
||||||
打印提示导航
|
打印提示导航
|
||||||
"""
|
"""
|
||||||
msg = """\n\033[1;32m### Welcome To Use JumpServer, A Open Source System . ### \033[0m
|
|
||||||
1) Type \033[32mID\033[0m To Login.
|
|
||||||
2) Type \033[32m/\033[0m + \033[32mIP, Host Name, Host Alias or Comments \033[0mTo Search.
|
|
||||||
3) Type \033[32mP/p\033[0m To Print The Servers You Available.
|
|
||||||
4) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
|
|
||||||
5) Type \033[32mG/g\033[0m\033[0m + \033[32mGroup ID\033[0m To Print The Server Group You Available.
|
|
||||||
6) Type \033[32mE/e\033[0m To Execute Command On Several Servers.
|
|
||||||
7) Type \033[32mQ/q\033[0m To Quit.
|
|
||||||
"""
|
|
||||||
|
|
||||||
msg = """\n\033[1;32m### 欢迎使用Jumpserver开源跳板机 ### \033[0m
|
msg = """\n\033[1;32m### 欢迎使用Jumpserver开源跳板机 ### \033[0m
|
||||||
1) 输入 \033[32mID\033[0m 直接登录.
|
1) 输入 \033[32mID\033[0m 直接登录.
|
||||||
2) 输入 \033[32m/\033[0m + \033[32mIP, 主机名, 主机别名 or 备注 \033[0m搜索.
|
2) 输入 \033[32m/\033[0m + \033[32mIP, 主机名, 主机别名 or 备注 \033[0m搜索.
|
||||||
@ -542,35 +533,6 @@ class Nav(object):
|
|||||||
print '[%-3s] %-15s' % (asset_group.id, asset_group.name)
|
print '[%-3s] %-15s' % (asset_group.id, asset_group.name)
|
||||||
print
|
print
|
||||||
|
|
||||||
def get_exec_log(self, assets_name_str):
|
|
||||||
exec_log_dir = os.path.join(LOG_DIR, 'exec')
|
|
||||||
date_today = datetime.datetime.now()
|
|
||||||
date_start = date_today.strftime('%Y%m%d')
|
|
||||||
time_start = date_today.strftime('%H%M%S')
|
|
||||||
today_connect_log_dir = os.path.join(exec_log_dir, date_start)
|
|
||||||
log_file_path = os.path.join(today_connect_log_dir, '%s_%s' % (self.user.username, time_start))
|
|
||||||
|
|
||||||
try:
|
|
||||||
mkdir(os.path.dirname(today_connect_log_dir), mode=0777)
|
|
||||||
mkdir(today_connect_log_dir, mode=0777)
|
|
||||||
except OSError:
|
|
||||||
logger.debug('创建目录 %s 失败,请修改%s目录权限' % (today_connect_log_dir, exec_log_dir))
|
|
||||||
raise ServerError('Create %s failed, Please modify %s permission.' % (today_connect_log_dir, exec_log_dir))
|
|
||||||
|
|
||||||
try:
|
|
||||||
log_file_f = open(log_file_path + '.log', 'a')
|
|
||||||
log_file_f.write('Start at %s\r\n' % datetime.datetime.now())
|
|
||||||
log_time_f = open(log_file_path + '.time', 'a')
|
|
||||||
except IOError:
|
|
||||||
logger.debug('创建tty日志文件失败, 请修改目录%s权限' % today_connect_log_dir)
|
|
||||||
raise ServerError('Create logfile failed, Please modify %s permission.' % today_connect_log_dir)
|
|
||||||
|
|
||||||
remote_ip = os.popen("who -m | awk '{ print $5 }'").read().strip('()\n')
|
|
||||||
log = Log(user=self.user.username, host=assets_name_str, remote_ip=remote_ip, login_type='exec',
|
|
||||||
log_path=log_file_path, start_time=datetime.datetime.now(), pid=os.getpid())
|
|
||||||
log.save()
|
|
||||||
return log_file_f, log_time_f, log
|
|
||||||
|
|
||||||
def exec_cmd(self):
|
def exec_cmd(self):
|
||||||
"""
|
"""
|
||||||
批量执行命令
|
批量执行命令
|
||||||
@ -578,8 +540,10 @@ class Nav(object):
|
|||||||
while True:
|
while True:
|
||||||
if not self.user_perm:
|
if not self.user_perm:
|
||||||
self.user_perm = get_group_user_perm(self.user)
|
self.user_perm = get_group_user_perm(self.user)
|
||||||
print '\033[32m[%-2s] %-15s \033[0m' % ('ID', '角色')
|
|
||||||
roles = self.user_perm.get('role').keys()
|
roles = self.user_perm.get('role').keys()
|
||||||
|
if len(roles) > 1: # 授权角色数大于1
|
||||||
|
print '\033[32m[%-2s] %-15s \033[0m' % ('ID', '角色')
|
||||||
role_check = dict(zip(range(len(roles)), roles))
|
role_check = dict(zip(range(len(roles)), roles))
|
||||||
|
|
||||||
for i, r in role_check.items():
|
for i, r in role_check.items():
|
||||||
@ -591,12 +555,16 @@ class Nav(object):
|
|||||||
role_id = raw_input("\033[1;32mRole>:\033[0m ").strip()
|
role_id = raw_input("\033[1;32mRole>:\033[0m ").strip()
|
||||||
if role_id == 'q':
|
if role_id == 'q':
|
||||||
break
|
break
|
||||||
|
except (IndexError, ValueError):
|
||||||
|
color_print('错误输入')
|
||||||
else:
|
else:
|
||||||
role = role_check[int(role_id)]
|
role = role_check[int(role_id)]
|
||||||
assets = list(self.user_perm.get('role', {}).get(role).get('asset'))
|
elif len(roles) == 1: # 授权角色数为1
|
||||||
|
role = roles[0]
|
||||||
|
assets = list(self.user_perm.get('role', {}).get(role).get('asset')) # 获取该用户,角色授权主机
|
||||||
print "该角色有权限的所有主机"
|
print "该角色有权限的所有主机"
|
||||||
for asset in assets:
|
for asset in assets:
|
||||||
print asset.hostname
|
print ' %s' % asset.hostname
|
||||||
print
|
print
|
||||||
print "请输入主机名、IP或ansile支持的pattern, q退出"
|
print "请输入主机名、IP或ansile支持的pattern, q退出"
|
||||||
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
|
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
|
||||||
@ -604,78 +572,42 @@ class Nav(object):
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
res = gen_resource({'user': self.user, 'asset': assets, 'role': role}, perm=self.user_perm)
|
res = gen_resource({'user': self.user, 'asset': assets, 'role': role}, perm=self.user_perm)
|
||||||
cmd = Command(res)
|
runner = MyRunner(res)
|
||||||
logger.debug("批量执行res: %s" % res)
|
logger.debug("批量执行res: %s" % res)
|
||||||
asset_name_str = ''
|
asset_name_str = ''
|
||||||
for inv in cmd.inventory.get_hosts(pattern=pattern):
|
print "匹配主机:"
|
||||||
print inv.name
|
for inv in runner.inventory.get_hosts(pattern=pattern):
|
||||||
asset_name_str += inv.name
|
print ' %s' % inv.name
|
||||||
|
asset_name_str += '%s ' % inv.name
|
||||||
print
|
print
|
||||||
|
|
||||||
log_file_f, log_time_f, log = self.get_exec_log(asset_name_str)
|
|
||||||
pre_timestamp = time.time()
|
|
||||||
while True:
|
while True:
|
||||||
print "请输入执行的命令, 按q退出"
|
print "请输入执行的命令, 按q退出"
|
||||||
data = 'ansible> '
|
|
||||||
write_log(log_file_f, data)
|
|
||||||
now_timestamp = time.time()
|
|
||||||
write_log(log_time_f, '%s %s\n' % (round(now_timestamp-pre_timestamp, 4), len(data)))
|
|
||||||
pre_timestamp = now_timestamp
|
|
||||||
command = raw_input("\033[1;32mCmds>:\033[0m ").strip()
|
command = raw_input("\033[1;32mCmds>:\033[0m ").strip()
|
||||||
data = '%s\r\n' % command
|
ExecLog(host=asset_name_str, cmd=command).save()
|
||||||
write_log(log_file_f, data)
|
|
||||||
now_timestamp = time.time()
|
|
||||||
write_log(log_time_f, '%s %s\n' % (round(now_timestamp-pre_timestamp, 4), len(data)))
|
|
||||||
pre_timestamp = now_timestamp
|
|
||||||
TtyLog(log=log, cmd=command, datetime=datetime.datetime.now()).save()
|
|
||||||
if command == 'q':
|
if command == 'q':
|
||||||
log.is_finished = True
|
|
||||||
log.end_time = datetime.datetime.now()
|
|
||||||
log.save()
|
|
||||||
break
|
break
|
||||||
result = cmd.run(module_name='shell', command=command, pattern=pattern)
|
runner.run('shell', command, pattern=pattern)
|
||||||
for k, v in result.items():
|
for k, v in runner.results.items():
|
||||||
if k == 'ok':
|
if k == 'ok':
|
||||||
for host, output in v.items():
|
for host, output in v.items():
|
||||||
header = color_print("%s => %s" % (host, 'Ok'), 'green')
|
color_print("%s => %s" % (host, 'Ok'), 'green')
|
||||||
print output
|
print output
|
||||||
output = re.sub(r'[\r\n]', '\r\n', output)
|
|
||||||
data = '%s\r\n%s\r\n' % (header, output)
|
|
||||||
now_timestamp = time.time()
|
|
||||||
write_log(log_file_f, data)
|
|
||||||
write_log(log_time_f, '%s %s\n' % (round(now_timestamp-pre_timestamp, 4), len(data)))
|
|
||||||
pre_timestamp = now_timestamp
|
|
||||||
print
|
print
|
||||||
else:
|
else:
|
||||||
for host, output in v.items():
|
for host, output in v.items():
|
||||||
header = color_print("%s => %s" % (host, k), 'red')
|
color_print("%s => %s" % (host, k), 'red')
|
||||||
output = color_print(output, 'red')
|
color_print(output, 'red')
|
||||||
output = re.sub(r'[\r\n]', '\r\n', output)
|
|
||||||
data = '%s\r\n%s\r\n' % (header, output)
|
|
||||||
now_timestamp = time.time()
|
|
||||||
write_log(log_file_f, data)
|
|
||||||
write_log(log_time_f, '%s %s\n' % (round(now_timestamp-pre_timestamp, 4), len(data)))
|
|
||||||
pre_timestamp = now_timestamp
|
|
||||||
print
|
print
|
||||||
print "=" * 20
|
print "~o~ Task finished ~o~"
|
||||||
print
|
print
|
||||||
|
|
||||||
except (IndexError, KeyError):
|
|
||||||
color_print('ID输入错误')
|
|
||||||
continue
|
|
||||||
|
|
||||||
except EOFError:
|
|
||||||
print
|
|
||||||
break
|
|
||||||
finally:
|
|
||||||
log.is_finished = True
|
|
||||||
log.end_time = datetime.datetime.now()
|
|
||||||
|
|
||||||
def upload(self):
|
def upload(self):
|
||||||
while True:
|
while True:
|
||||||
if not self.user_perm:
|
if not self.user_perm:
|
||||||
self.user_perm = get_group_user_perm(self.user)
|
self.user_perm = get_group_user_perm(self.user)
|
||||||
try:
|
try:
|
||||||
|
print "进入批量上传模式"
|
||||||
print "请输入主机名、IP或ansile支持的pattern, q退出"
|
print "请输入主机名、IP或ansile支持的pattern, q退出"
|
||||||
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
|
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
|
||||||
if pattern == 'q':
|
if pattern == 'q':
|
||||||
@ -684,8 +616,8 @@ class Nav(object):
|
|||||||
assets = self.user_perm.get('asset').keys()
|
assets = self.user_perm.get('asset').keys()
|
||||||
res = gen_resource({'user': self.user, 'asset': assets}, perm=self.user_perm)
|
res = gen_resource({'user': self.user, 'asset': assets}, perm=self.user_perm)
|
||||||
runner = MyRunner(res)
|
runner = MyRunner(res)
|
||||||
logger.debug("Muti upload file res: %s" % res)
|
|
||||||
asset_name_str = ''
|
asset_name_str = ''
|
||||||
|
print "匹配主机:\n"
|
||||||
for inv in runner.inventory.get_hosts(pattern=pattern):
|
for inv in runner.inventory.get_hosts(pattern=pattern):
|
||||||
print inv.name
|
print inv.name
|
||||||
asset_name_str += inv.name
|
asset_name_str += inv.name
|
||||||
@ -701,16 +633,15 @@ class Nav(object):
|
|||||||
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'
|
||||||
% (tmp_dir, tmp_dir), pattern=pattern)
|
% (tmp_dir, tmp_dir), pattern=pattern)
|
||||||
ret = runner.get_result()
|
ret = runner.results
|
||||||
logger.debug(ret)
|
logger.debug('Upload file: %s' % ret)
|
||||||
if ret.get('failed'):
|
if ret.get('failed'):
|
||||||
print ret
|
|
||||||
error = '上传目录: %s \n上传失败: [ %s ] \n上传成功 [ %s ]' % (tmp_dir,
|
error = '上传目录: %s \n上传失败: [ %s ] \n上传成功 [ %s ]' % (tmp_dir,
|
||||||
', '.join(ret.get('failed').keys()),
|
', '.join(ret.get('failed').keys()),
|
||||||
', '.join(ret.get('ok')))
|
', '.join(ret.get('ok').keys()))
|
||||||
color_print(error)
|
color_print(error)
|
||||||
else:
|
else:
|
||||||
msg = '上传目录: %s \n传送成功 [ %s ]' % (tmp_dir, ', '.join(ret.get('ok')))
|
msg = '上传目录: %s \n传送成功 [ %s ]' % (tmp_dir, ', '.join(ret.get('ok').keys()))
|
||||||
color_print(msg, 'green')
|
color_print(msg, 'green')
|
||||||
print
|
print
|
||||||
|
|
||||||
@ -731,30 +662,31 @@ class Nav(object):
|
|||||||
assets = self.user_perm.get('asset').keys()
|
assets = self.user_perm.get('asset').keys()
|
||||||
res = gen_resource({'user': self.user, 'asset': assets}, perm=self.user_perm)
|
res = gen_resource({'user': self.user, 'asset': assets}, perm=self.user_perm)
|
||||||
runner = MyRunner(res)
|
runner = MyRunner(res)
|
||||||
logger.debug("Muti Muti file res: %s" % res)
|
logger.debug("Muti download file res: %s" % res)
|
||||||
|
print "匹配用户:\n"
|
||||||
for inv in runner.inventory.get_hosts(pattern=pattern):
|
for inv in runner.inventory.get_hosts(pattern=pattern):
|
||||||
print inv.name
|
print inv.name
|
||||||
print
|
print
|
||||||
|
while True:
|
||||||
tmp_dir = get_tmp_dir()
|
tmp_dir = get_tmp_dir()
|
||||||
logger.debug('Download tmp dir: %s' % tmp_dir)
|
logger.debug('Download tmp dir: %s' % tmp_dir)
|
||||||
while True:
|
|
||||||
print "请输入文件路径(不支持目录)"
|
print "请输入文件路径(不支持目录)"
|
||||||
file_path = raw_input("\033[1;32mPath>:\033[0m ").strip()
|
file_path = raw_input("\033[1;32mPath>:\033[0m ").strip()
|
||||||
if file_path == 'q':
|
if file_path == 'q':
|
||||||
break
|
break
|
||||||
runner.run('fetch', module_args='src=%s dest=%s' % (file_path, tmp_dir), pattern=pattern)
|
runner.run('fetch', module_args='src=%s dest=%s' % (file_path, tmp_dir), pattern=pattern)
|
||||||
ret = runner.get_result()
|
ret = runner.results
|
||||||
|
logger.debug('Download file result: %s' % ret)
|
||||||
os.chdir('/tmp')
|
os.chdir('/tmp')
|
||||||
tmp_dir_name = os.path.basename(tmp_dir)
|
tmp_dir_name = os.path.basename(tmp_dir)
|
||||||
bash('tar czf %s.tar.gz %s ' % (tmp_dir, tmp_dir_name))
|
bash('tar czf %s.tar.gz %s && sz %s.tar.gz' % (tmp_dir, tmp_dir_name, tmp_dir))
|
||||||
|
|
||||||
if ret.get('failed'):
|
if ret.get('failed'):
|
||||||
print ret
|
|
||||||
error = '文件名称: %s 下载失败: [ %s ] \n下载成功 [ %s ]' % \
|
error = '文件名称: %s 下载失败: [ %s ] \n下载成功 [ %s ]' % \
|
||||||
('%s.tar.gz' % tmp_dir_name, ', '.join(ret.get('failed').keys()), ', '.join(ret.get('ok')))
|
('%s.tar.gz' % tmp_dir_name, ', '.join(ret.get('failed').keys()), ', '.join(ret.get('ok').keys()))
|
||||||
color_print(error)
|
color_print(error)
|
||||||
else:
|
else:
|
||||||
msg = '文件名称: %s 下载成功 [ %s ]' % ('%s.tar.gz' % tmp_dir_name, ', '.join(ret.get('ok')))
|
msg = '文件名称: %s 下载成功 [ %s ]' % ('%s.tar.gz' % tmp_dir_name, ', '.join(ret.get('ok').keys()))
|
||||||
color_print(msg, 'green')
|
color_print(msg, 'green')
|
||||||
print
|
print
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
@ -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):
|
|||||||
|
|
||||||
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):
|
|||||||
"""
|
"""
|
||||||
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):
|
|||||||
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):
|
|||||||
"""
|
"""
|
||||||
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):
|
|||||||
pattern=pattern,
|
pattern=pattern,
|
||||||
forks=forks,
|
forks=forks,
|
||||||
)
|
)
|
||||||
self.results = hoc.run()
|
self.results_raw = hoc.run()
|
||||||
|
|
||||||
ret = {}
|
|
||||||
if self.stdout:
|
|
||||||
data['ok'] = self.stdout
|
|
||||||
if self.stderr:
|
|
||||||
data['err'] = self.stderr
|
|
||||||
if self.dark:
|
|
||||||
data['dark'] = self.dark
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def raw_results(self):
|
def result(self):
|
||||||
"""
|
result = {}
|
||||||
get the ansible raw results.
|
for k, v in self.results_raw.items():
|
||||||
"""
|
if k == 'dark':
|
||||||
return self.results
|
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:
|
||||||
|
result['ok'] = self.stdout
|
||||||
|
if self.stderr:
|
||||||
|
result['err'] = self.stderr
|
||||||
|
if self.dark:
|
||||||
|
result['dark'] = self.dark
|
||||||
|
return result
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def exec_time(self):
|
def exec_time(self):
|
||||||
@ -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):
|
|||||||
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):
|
|||||||
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):
|
|||||||
"""
|
"""
|
||||||
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):
|
|||||||
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):
|
|||||||
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):
|
|||||||
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):
|
|||||||
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):
|
|||||||
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):
|
|||||||
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
|
|||||||
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
|
|||||||
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):
|
|||||||
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,24 +238,38 @@ 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 t in self.__class__.tasks:
|
||||||
|
if t.is_alive():
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
t.setDaemon(True)
|
||||||
|
t.start()
|
||||||
|
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():
|
for host, output in v.items():
|
||||||
if k == 'ok':
|
if k == 'ok':
|
||||||
header = "<span style='color: green'>[ %s => %s]</span>\n" % (host, 'Ok')
|
header = "<span style='color: green'>[ %s => %s]</span>\n" % (host, 'Ok')
|
||||||
@ -263,8 +277,12 @@ class ExecHandler(tornado.websocket.WebSocketHandler):
|
|||||||
header = "<span style='color: red'>[ %s => %s]</span>\n" % (host, 'failed')
|
header = "<span style='color: red'>[ %s => %s]</span>\n" % (host, 'failed')
|
||||||
self.write_message(header)
|
self.write_message(header)
|
||||||
self.write_message(output)
|
self.write_message(output)
|
||||||
|
|
||||||
self.write_message('\n~o~ Task finished ~o~\n')
|
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):
|
||||||
clients = []
|
clients = []
|
||||||
|
@ -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 @@
|
|||||||
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 @@
|
|||||||
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
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user