Commit 69bbdab4 authored by ibuler's avatar ibuler

完成上传下载

parent 6975acfc
...@@ -565,10 +565,11 @@ class Nav(object): ...@@ -565,10 +565,11 @@ class Nav(object):
while True: while True:
print "请输入执行的命令, 按q退出" print "请输入执行的命令, 按q退出"
command = raw_input("\033[1;32mCmds>:\033[0m ").strip() command = raw_input("\033[1;32mCmds>:\033[0m ").strip()
ExecLog(host=asset_name_str, user=self.user.username, cmd=command, remote_ip=remote_ip).save()
if command == 'q': if command == 'q':
break break
runner.run('shell', command, pattern=pattern) runner.run('shell', command, pattern=pattern)
ExecLog(host=asset_name_str, user=self.user.username, cmd=command, remote_ip=remote_ip,
result=runner.results).save()
for k, v in runner.results.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():
...@@ -605,7 +606,6 @@ class Nav(object): ...@@ -605,7 +606,6 @@ class Nav(object):
if not asset_name_str: if not asset_name_str:
color_print('没有匹配主机') color_print('没有匹配主机')
print
continue continue
tmp_dir = get_tmp_dir() tmp_dir = get_tmp_dir()
logger.debug('Upload tmp dir: %s' % tmp_dir) logger.debug('Upload tmp dir: %s' % tmp_dir)
...@@ -613,15 +613,16 @@ class Nav(object): ...@@ -613,15 +613,16 @@ class Nav(object):
bash('rz') bash('rz')
filename_str = ' '.join(os.listdir(tmp_dir)) filename_str = ' '.join(os.listdir(tmp_dir))
if not filename_str: if not filename_str:
print color_print("上传文件为空") color_print("上传文件为空")
continue continue
logger.debug('上传文件: %s' % filename_str) logger.debug('上传文件: %s' % filename_str)
FileLog(user=self.user.name, host=asset_name_str, filename=filename_str,
remote_ip=remote_ip, type='upload').save()
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.results ret = runner.results
FileLog(user=self.user.name, host=asset_name_str, filename=filename_str,
remote_ip=remote_ip, type='upload', result=ret).save()
logger.debug('Upload file: %s' % ret) logger.debug('Upload file: %s' % ret)
if ret.get('failed'): if ret.get('failed'):
error = '上传目录: %s \n上传失败: [ %s ] \n上传成功 [ %s ]' % (tmp_dir, error = '上传目录: %s \n上传失败: [ %s ] \n上传成功 [ %s ]' % (tmp_dir,
...@@ -667,10 +668,10 @@ class Nav(object): ...@@ -667,10 +668,10 @@ class Nav(object):
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
FileLog(user=self.user.name, host=asset_name_str, filename=file_path, type='download',
remote_ip=remote_ip).save()
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.results ret = runner.results
FileLog(user=self.user.name, host=asset_name_str, filename=file_path, type='download',
remote_ip=remote_ip, result=ret).save()
logger.debug('Download file result: %s' % ret) 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)
......
...@@ -33,6 +33,7 @@ class ExecLog(models.Model): ...@@ -33,6 +33,7 @@ class ExecLog(models.Model):
host = models.TextField() host = models.TextField()
cmd = models.TextField() cmd = models.TextField()
remote_ip = models.CharField(max_length=100) remote_ip = models.CharField(max_length=100)
result = models.TextField(default='')
datetime = models.DateTimeField(auto_now=True) datetime = models.DateTimeField(auto_now=True)
...@@ -42,6 +43,7 @@ class FileLog(models.Model): ...@@ -42,6 +43,7 @@ class FileLog(models.Model):
filename = models.TextField() filename = models.TextField()
type = models.CharField(max_length=20) type = models.CharField(max_length=20)
remote_ip = models.CharField(max_length=100) remote_ip = models.CharField(max_length=100)
result = models.TextField(default='')
datetime = models.DateTimeField(auto_now=True) datetime = models.DateTimeField(auto_now=True)
...@@ -5,6 +5,7 @@ from jlog.views import * ...@@ -5,6 +5,7 @@ from jlog.views import *
urlpatterns = patterns('', urlpatterns = patterns('',
(r'^$', log_list), (r'^$', log_list),
(r'^log_list/(\w+)/$', log_list), (r'^log_list/(\w+)/$', log_list),
(r'^log_detail/(\w+)/$', log_detail),
(r'^history/$', log_history), (r'^history/$', log_history),
(r'^log_kill/', log_kill), (r'^log_kill/', log_kill),
(r'^record/$', log_record), (r'^record/$', log_record),
......
...@@ -129,3 +129,21 @@ def web_terminal(request): ...@@ -129,3 +129,21 @@ def web_terminal(request):
web_terminal_uri = 'ws://%s/terminal?id=%s&role=%s' % (WEB_SOCKET_HOST, asset_id, role_name) web_terminal_uri = 'ws://%s/terminal?id=%s&role=%s' % (WEB_SOCKET_HOST, asset_id, role_name)
return render_to_response('jlog/web_terminal.html', locals()) return render_to_response('jlog/web_terminal.html', locals())
@require_role('admin')
def log_detail(request, offset):
log_id = request.GET.get('id')
if offset == 'exec':
log = get_object(ExecLog, id=log_id)
assets_hostname = log.host.split(' ')
result = eval(str(log.result))
return my_render('jlog/exec_detail.html', locals(), request)
elif offset == 'file':
log = get_object(FileLog, id=log_id)
assets_hostname = log.host.split(' ')
file_list = log.filename.split(' ')
try:
result = eval(str(log.result))
except (SyntaxError, NameError):
result = {}
return my_render('jlog/file_detail.html', locals(), request)
...@@ -302,12 +302,10 @@ def upload(request): ...@@ -302,12 +302,10 @@ def upload(request):
illegal_asset = set(asset_select).issubset(set(assets)) illegal_asset = set(asset_select).issubset(set(assets))
return HttpResponse('没有权限的服务器 %s' % ','.join([asset.hostname for asset in illegal_asset])) return HttpResponse('没有权限的服务器 %s' % ','.join([asset.hostname for asset in illegal_asset]))
FileLog(user=request.user.username, host=' '.join([asset.hostname for asset in asset_select]),
filename=' '.join([f.name for f in upload_files]), type='upload', remote_ip=remote_ip).save()
for upload_file in upload_files: for upload_file in upload_files:
file_path = '%s/%s' % (upload_dir, upload_file.name) file_path = '%s/%s' % (upload_dir, upload_file.name)
# file_dict[upload_file.name] = file_path
with open(file_path, 'w') as f: with open(file_path, 'w') as f:
for chunk in upload_file.chunks(): for chunk in upload_file.chunks():
f.write(chunk) f.write(chunk)
...@@ -318,6 +316,9 @@ def upload(request): ...@@ -318,6 +316,9 @@ def upload(request):
% (upload_dir, upload_dir), pattern='*') % (upload_dir, upload_dir), pattern='*')
ret = runner.results ret = runner.results
logger.debug(ret) logger.debug(ret)
FileLog(user=request.user.username, host=' '.join([asset.hostname for asset in asset_select]),
filename=' '.join([f.name for f in upload_files]), type='upload', remote_ip=remote_ip,
result=ret).save()
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()),
...@@ -346,11 +347,11 @@ def download(request): ...@@ -346,11 +347,11 @@ def download(request):
illegal_asset = set(asset_select).issubset(set(assets)) illegal_asset = set(asset_select).issubset(set(assets))
return HttpResponse('没有权限的服务器 %s' % ','.join([asset.hostname for asset in illegal_asset])) return HttpResponse('没有权限的服务器 %s' % ','.join([asset.hostname for asset in illegal_asset]))
FileLog(user=request.user.username, host=' '.join([asset.hostname for asset in asset_select]),
filename=file_path, type='download', remote_ip=remote_ip).save()
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='*')
FileLog(user=request.user.username, host=' '.join([asset.hostname for asset in asset_select]),
filename=file_path, type='download', remote_ip=remote_ip, result=runner.results).save()
logger.debug(runner.results) 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)
......
...@@ -2822,7 +2822,9 @@ body.body-small .footer.fixed { ...@@ -2822,7 +2822,9 @@ body.body-small .footer.fixed {
.table > thead > tr > td, .table > thead > tr > td,
.table > tbody > tr > td, .table > tbody > tr > td,
.table > tfoot > tr > td { .table > tfoot > tr > td {
border-top: 1px solid #e7eaec; /*border-top: 1px solid #e7eaec;*/
border-bottom: 1px solid #e7eaec;
border-top: none;
line-height: 1.42857; line-height: 1.42857;
padding: 8px; padding: 8px;
vertical-align: top; vertical-align: top;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<div class="col-sm-4"> <div class="col-sm-4">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span class="label label-primary"><b></b></span> <span class="label label-primary"><b>{{ log.id }}</b></span>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
...@@ -28,44 +28,30 @@ ...@@ -28,44 +28,30 @@
<table class="table"> <table class="table">
<tr> <tr>
<td class="text-navy">ID</td> <td class="text-navy">ID</td>
<td>{{ user.id }}</td> <td>{{ log.id }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">用户名</td> <td class="text-navy">用户名</td>
<td>{{ user.username }}</td> <td>{{ log.user }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">来源IP</td> <td class="text-navy">来源IP</td>
<td>{{ user.name }}</td> <td>{{ log.remote_ip }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">角色</td> <td class="text-navy">日期</td>
<td>{{ user.id | get_role }}</td> <td>{{ log.datetime|date:"Y-m-d H:i:s" }}</td>
</tr> </tr>
<tr> <tr>
<td class="text-navy">Email</td> <td class="text-navy">主机</td>
<td>{{ user.email }}</td>
</tr>
<tr>
<td class="text-navy">激活</td>
<td>{{ user.is_active|bool2str }}</td>
</tr>
<tr>
<td class="text-navy">添加日期</td>
<td>{{ user.date_joined|date:"Y-m-d H:i:s" }}</td>
</tr>
<tr>
<td class="text-navy">最后登录</td>
<td>{{ user.last_login|date:"Y-m-d H:i:s" }}</td>
</tr>
<tr>
<td class="text-navy">所在用户组</td>
<td> <td>
<table class="table"> <table class="table">
{% for group in user.group.all %} {% for asset_name in assets_hostname %}
{% if asset_name %}
<tr> <tr>
<td><a href="/jperm/perm_edit/?id={{ group.id }}">{{ group.name }}</a></td> <td>{{ asset_name }}</td>
</tr> </tr>
{% endif %}
{% endfor %} {% endfor %}
</table> </table>
</td> </td>
...@@ -76,10 +62,10 @@ ...@@ -76,10 +62,10 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-4"> <div class="col-sm-8">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<h5>授权主机/组</h5> <h5>结果</h5>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
...@@ -88,102 +74,42 @@ ...@@ -88,102 +74,42 @@
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user"> <ul class="dropdown-menu dropdown-user">
<li><a href="#">Config option 1</a>
</li>
<li><a href="#">Config option 2</a>
</li>
</ul> </ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</a> </a>
</div> </div>
</div> </div>
<div class="ibox-content ibox-heading">
<h3>用户的所有授权主机</h3>
<small><i class="fa fa-map-marker"></i> 这里包含了用户所有的主机组和组下的主机.</small>
</div>
<div class="ibox-content inspinia-timeline"> <div class="ibox-content inspinia-timeline">
{# {% for group in user|get_user_asset_group %}#} <div>
{# <div class="timeline-item">#} <div class="text-left">
{# <div class="row">#} <table class="table">
{# <div class="col-xs-3 date">#} <tr>
{# <i class="fa fa-repeat"></i>#} <td class="text-navy">命令</td>
{# <b><a href="/jperm/perm_list/?uid={{ user.id }}&agid={{ group.id }}">{{ group.name }}</a></b>#} <td>{{ log.cmd }}</td>
{# <br>#} </tr>
{# <small class="text-navy">共: {{ group | group_asset_list_count }}台</small>#} {% for result, info in result.items %}
{# </div>#} {% for host, msg in info.items %}
{# <div class="col-xs-7 content no-top-border">#} {% ifequal result 'failed' %}
{# <p class="m-b-xs"><strong>{{ group.comment }}</strong></p>#} <tr>
{# <p>#} <td class="text-navy" style="color: #ed5565">{{ host }}</td>
{# {% for asset in group|group_asset_list %}#} <td>{{ msg }}</td>
{# {{ asset.ip }}<br>#} </tr>
{# {% endfor %}#} {% else %}
{# </p>#} <tr>
{# <p></p>#} <td class="text-navy">{{ host }}</td>
{# </div>#} <td>{{ msg }}</td>
{# </div>#} </tr>
{# </div>#} {% endifequal %}
{# {% endfor %}#}
{# {% if not user|get_user_asset_group %}#}
{# (无)#}
{# {% endif %}#}
</div>
</div>
</div>
<div class="col-sm-4">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>登录记录</h5>
<div class="ibox-tools">
<span class="label label-warning-light">最近登录</span>
</div>
</div>
<div class="ibox-content">
<div id="last">
<div class="feed-activity-list" >
{% for log in logs_last %}
<div class="feed-element">
<a href="profile.html" class="pull-left">
<img alt="image" class="img-circle" src="/static/img/{{ session_role_id | to_avatar }}.png">
</a>
<div class="media-body ">
{# <small class="pull-right">{{ log.start_time|time_delta }}</small>#}
<small class="pull-right">{{ log.start_time }}</small>
<strong>{{ log.user }}</strong> 登录了 <span class="text-navy">{{ log.host }}. </span><br>
<small class="text-muted">{{ log.start_time|date:"Y-m-d H:i:s" }}</small>
</div>
</div>
{% endfor %} {% endfor %}
{% if not logs_last %}
(暂无)
{% endif %}
</div>
{% if logs_num > 10 %}
<button id="show" class="btn btn-primary btn-block m-t"><i class="fa fa-arrow-down"></i> Show All</button>
{% endif %}
</div>
<div id="all" style="display: none">
<div class="feed-activity-list" >
{% for log in logs_all %}
<div class="feed-element">
<a href="profile.html" class="pull-left">
<img alt="image" class="img-circle" src="/static/img/{{ session_role_id | to_avatar }}.png">
</a>
<div class="media-body ">
<small class="pull-right">{{ log.start_time }}</small>
{# <small class="pull-right">{{ log.start_time|time_delta }}</small>#}
<strong>{{ log.user }}</strong> 登录了 <span class="text-navy">{{ log.host }}. </span><br>
<small class="text-muted">{{ log.start_time|date:"Y-m-d H:i:s" }}</small>
</div>
</div>
{% endfor %} {% endfor %}
</table>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
<td class="text-center remote_ip"> {{ post.remote_ip }} </td> <td class="text-center remote_ip"> {{ post.remote_ip }} </td>
<td class="text-center start_time"> {{ post.datetime|date:"Y-m-d H:i:s"}} </td> <td class="text-center start_time"> {{ post.datetime|date:"Y-m-d H:i:s"}} </td>
<td class="text-center"> <td class="text-center">
<a href="../user_detail/?id={{ user.id }}" class="btn btn-xs btn-primary">详情</a> <a href="/jlog/log_detail/exec/?id={{ post.id }}" class="btn btn-xs btn-primary">详情</a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-sm-10"> <div class="col-sm-12">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 上传下载日志 </h5> <h5> 上传下载日志 </h5>
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
<td class="text-center"> {{ post.remote_ip }} </td> <td class="text-center"> {{ post.remote_ip }} </td>
<td class="text-center"> {{ post.datetime|date:"Y-m-d H:i:s"}} </td> <td class="text-center"> {{ post.datetime|date:"Y-m-d H:i:s"}} </td>
<td class="text-center"> <td class="text-center">
<a href="../user_detail/?id={{ user.id }}" class="btn btn-xs btn-primary">详情</a> <a href="/jlog/log_detail/file/?id={{ post.id }}" class="btn btn-xs btn-primary">详情</a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
......
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