批量上传下载

pull/26/head
ibuler 2015-12-02 13:35:06 +08:00
parent e95c47ff6a
commit 0e6fd89f0b
7 changed files with 132 additions and 28 deletions

View File

@ -16,16 +16,17 @@ import django
import paramiko import paramiko
import struct, fcntl, signal, socket, select import struct, fcntl, signal, socket, select
from io import open as copen from io import open as copen
import uuid
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
if django.get_version() != '1.6': if django.get_version() != '1.6':
django.setup() django.setup()
from django.contrib.sessions.models import Session from django.contrib.sessions.models import Session
from jumpserver.api import ServerError, User, Asset, PermRole, AssetGroup, get_object, mkdir, get_asset_info, get_role from jumpserver.api import ServerError, User, Asset, PermRole, AssetGroup, get_object, mkdir, get_asset_info, get_role
from jumpserver.api import logger, Log, TtyLog, get_role_key, CRYPTOR from jumpserver.api import logger, Log, TtyLog, get_role_key, CRYPTOR, bash, get_tmp_dir
from jperm.perm_api import gen_resource, get_group_asset_perm, get_group_user_perm, user_have_perm from jperm.perm_api import gen_resource, get_group_asset_perm, get_group_user_perm, user_have_perm
from jumpserver.settings import LOG_DIR from jumpserver.settings import LOG_DIR
from jperm.ansible_api import Command from jperm.ansible_api import Command, MyRunner
from jlog.log_api import escapeString from jlog.log_api import escapeString
login_user = get_object(User, username=getpass.getuser()) login_user = get_object(User, username=getpass.getuser())
@ -484,6 +485,8 @@ class Nav(object):
4) 输入 \033[32mG/g\033[0m 显示您有权限的主机组. 4) 输入 \033[32mG/g\033[0m 显示您有权限的主机组.
5) 输入 \033[32mG/g\033[0m\033[0m + \033[32m组ID\033[0m 显示该组下主机. 5) 输入 \033[32mG/g\033[0m\033[0m + \033[32m组ID\033[0m 显示该组下主机.
6) 输入 \033[32mE/e\033[0m 批量执行命令. 6) 输入 \033[32mE/e\033[0m 批量执行命令.
7) 输入 \033[32mU/u\033[0m 批量上传文件.
7) 输入 \033[32mD/d\033[0m 批量下载文件.
7) 输入 \033[32mQ/q\033[0m 退出. 7) 输入 \033[32mQ/q\033[0m 退出.
""" """
print textwrap.dedent(msg) print textwrap.dedent(msg)
@ -668,6 +671,91 @@ class Nav(object):
log.is_finished = True log.is_finished = True
log.end_time = datetime.datetime.now() log.end_time = datetime.datetime.now()
def upload(self):
while True:
if not self.user_perm:
self.user_perm = get_group_user_perm(self.user)
try:
print "请输入主机名、IP或ansile支持的pattern, q退出"
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
if pattern == 'q':
break
else:
assets = self.user_perm.get('asset').keys()
res = gen_resource({'user': self.user, 'asset': assets}, perm=self.user_perm)
runner = MyRunner(res)
logger.debug("Muti upload file res: %s" % res)
asset_name_str = ''
for inv in runner.inventory.get_hosts(pattern=pattern):
print inv.name
asset_name_str += inv.name
print
tmp_dir = get_tmp_dir()
logger.debug('Upload tmp dir: %s' % tmp_dir)
os.chdir(tmp_dir)
bash('rz')
runner = MyRunner(res)
runner.run('copy', module_args='src=%s dest=%s directory_mode'
% (tmp_dir, tmp_dir), pattern=pattern)
ret = runner.get_result()
logger.debug(ret)
if ret.get('failed'):
print ret
error = '上传目录: %s \n上传失败: [ %s ] \n上传成功 [ %s ]' % (tmp_dir,
', '.join(ret.get('failed').keys()),
', '.join(ret.get('ok')))
color_print(error)
else:
msg = '上传目录: %s \n传送成功 [ %s ]' % (tmp_dir, ', '.join(ret.get('ok')))
color_print(msg, 'green')
print
except IndexError:
pass
def download(self):
while True:
if not self.user_perm:
self.user_perm = get_group_user_perm(self.user)
try:
print "进入批量下载模式"
print "请输入主机名、IP或ansile支持的pattern, q退出"
pattern = raw_input("\033[1;32mPattern>:\033[0m ").strip()
if pattern == 'q':
break
else:
assets = self.user_perm.get('asset').keys()
res = gen_resource({'user': self.user, 'asset': assets}, perm=self.user_perm)
runner = MyRunner(res)
logger.debug("Muti Muti file res: %s" % res)
for inv in runner.inventory.get_hosts(pattern=pattern):
print inv.name
print
tmp_dir = get_tmp_dir()
logger.debug('Download tmp dir: %s' % tmp_dir)
while True:
print "请输入文件路径(不支持目录)"
file_path = raw_input("\033[1;32mPath>:\033[0m ").strip()
if file_path == 'q':
break
runner.run('fetch', module_args='src=%s dest=%s' % (file_path, tmp_dir), pattern=pattern)
ret = runner.get_result()
os.chdir('/tmp')
tmp_dir_name = os.path.basename(tmp_dir)
bash('tar czf %s.tar.gz %s && sz %s.tar.gz' % (tmp_dir, tmp_dir_name, tmp_dir))
if ret.get('failed'):
print ret
error = '文件名称: %s 下载失败: [ %s ] \n下载成功 [ %s ]' % \
('%s.tar.gz' % tmp_dir_name, ', '.join(ret.get('failed').keys()), ', '.join(ret.get('ok')))
color_print(error)
else:
msg = '文件名称: %s 下载成功 [ %s ]' % ('%s.tar.gz' % tmp_dir_name, ', '.join(ret.get('ok')))
color_print(msg, 'green')
print
except IndexError:
pass
def main(): def main():
""" """
@ -701,6 +789,10 @@ def main():
elif option in ['E', 'e']: elif option in ['E', 'e']:
nav.exec_cmd() nav.exec_cmd()
continue continue
elif option in ['U', 'u']:
nav.upload()
elif option in ['D', 'd']:
nav.download()
elif option in ['Q', 'q', 'exit']: elif option in ['Q', 'q', 'exit']:
sys.exit() sys.exit()
else: else:

View File

@ -140,6 +140,22 @@ class MyRunner(MyInventory):
self.results = hoc.run() self.results = hoc.run()
return self.results return self.results
def get_result(self):
result = {'failed': {}, 'ok': []}
dark = self.results.get('dark')
contacted = self.results.get('contacted')
if dark:
for host, info in dark.items():
result['failed'][host] = info.get('msg')
if contacted:
for host, info in contacted.items():
if info.get('msg'):
result['failed'][host] = info.get('msg')
else:
result['ok'].append(host)
return result
class Command(MyInventory): class Command(MyInventory):
""" """

View File

@ -9,6 +9,7 @@ import hashlib
import datetime import datetime
import random import random
import subprocess import subprocess
import uuid
import json import json
import logging import logging
@ -482,5 +483,10 @@ def my_render(template, data, request):
return render_to_response(template, data, context_instance=RequestContext(request)) return render_to_response(template, data, context_instance=RequestContext(request))
def get_tmp_dir():
dir_name = os.path.join('/tmp', uuid.uuid4().hex)
mkdir(dir_name, mode=0777)
return dir_name
CRYPTOR = PyCrypt(KEY) CRYPTOR = PyCrypt(KEY)
logger = set_log(LOG_LEVEL) logger = set_log(LOG_LEVEL)

View File

@ -6,19 +6,13 @@ urlpatterns = patterns('',
(r'^$', 'jumpserver.views.index'), (r'^$', 'jumpserver.views.index'),
(r'^api/user/$', 'jumpserver.api.api_user'), (r'^api/user/$', 'jumpserver.api.api_user'),
(r'^skin_config/$', 'jumpserver.views.skin_config'), (r'^skin_config/$', 'jumpserver.views.skin_config'),
(r'^install/$', 'jumpserver.views.install'),
(r'^base/$', 'jumpserver.views.base'),
(r'^login/$', 'jumpserver.views.Login'), (r'^login/$', 'jumpserver.views.Login'),
(r'^logout/$', 'jumpserver.views.Logout'), (r'^logout/$', 'jumpserver.views.Logout'),
(r'^file/upload/$', 'jumpserver.views.upload'), (r'^file/upload/$', 'jumpserver.views.upload'),
(r'^file/download/$', 'jumpserver.views.download'), (r'^file/download/$', 'jumpserver.views.download'),
(r'^setting', 'jumpserver.views.setting'), (r'^setting', 'jumpserver.views.setting'),
(r'^error/$', 'jumpserver.views.httperror'),
(r'^juser/', include('juser.urls')), (r'^juser/', include('juser.urls')),
(r'^jasset/', include('jasset.urls')), (r'^jasset/', include('jasset.urls')),
(r'^jlog/', include('jlog.urls')), (r'^jlog/', include('jlog.urls')),
(r'^jperm/', include('jperm.urls')), (r'^jperm/', include('jperm.urls')),
(r'^node_auth/', 'jumpserver.views.node_auth'),
(r'download/(\d{4}/\d\d/\d\d/.*)', 'jumpserver.views.download_file'),
(r'test2', 'jumpserver.views.test2'),
) )

View File

@ -294,7 +294,7 @@ def upload(request):
upload_files = request.FILES.getlist('file[]', None) upload_files = request.FILES.getlist('file[]', None)
date_now = datetime.datetime.now().strftime("%Y%m%d%H%M%S") date_now = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
upload_dir = "/tmp/%s/%s" % (user.username, date_now) upload_dir = "/tmp/%s/%s" % (user.username, date_now)
mkdir(upload_dir) mkdir(upload_dir, mode=0777)
filenames = {} filenames = {}
for asset_id in asset_ids: for asset_id in asset_ids:
asset_select.append(get_object(Asset, id=asset_id)) asset_select.append(get_object(Asset, id=asset_id))
@ -312,24 +312,22 @@ def upload(request):
res = gen_resource({'user': user, 'asset': asset_select}) res = gen_resource({'user': user, 'asset': asset_select})
runner = MyRunner(res) runner = MyRunner(res)
ret = runner.run('copy', module_args='src=%s dest=%s directory_mode' % (upload_dir, '/tmp/hello/'), pattern='*') runner.run('copy', module_args='src=%s dest=%s directory_mode'
% (upload_dir, upload_dir), pattern='*')
ret = runner.get_result()
logger.debug(ret) logger.debug(ret)
error = '上传失败: ' if ret.get('failed'):
if ret.get('dark'): error = '上传目录: %s <br> 上传失败: [ %s ] <br>上传成功 [ %s ]' % (upload_dir,
error += ','.join(ret.get('dark').keys()) ', '.join(ret.get('failed').keys()),
', '.join(ret.get('ok')))
for asset, info in ret.get('contacted').items():
if info.get('msg'):
error += ',%s' % asset
if error:
return HttpResponse(error, status=500) return HttpResponse(error, status=500)
return HttpResponse('传送成功') msg = '上传目录: %s <br> 传送成功 [ %s ]' % (upload_dir, ', '.join(ret.get('ok')))
return HttpResponse(msg)
return my_render('upload.html', locals(), request) return my_render('upload.html', locals(), request)
@login_required(login_url='/login') @login_required(login_url='/login')
def download(request): def download(request):
documents = []
return render_to_response('download.html', locals(), context_instance=RequestContext(request)) return render_to_response('download.html', locals(), context_instance=RequestContext(request))

View File

@ -16,12 +16,6 @@
<a class="dropdown-toggle" data-toggle="dropdown" href="#"> <a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i> <i class="fa fa-wrench"></i>
</a> </a>
<ul class="dropdown-menu dropdown-user">
<li><a href="#">Config option 1</a>
</li>
<li><a href="#">Config option 2</a>
</li>
</ul>
<a class="close-link"> <a class="close-link">
<i class="fa fa-times"></i> <i class="fa fa-times"></i>
</a> </a>

View File

@ -66,6 +66,8 @@
<div class="ibox-content"> <div class="ibox-content">
<div> <div>
<form id="my-awesome-dropzone" class="dropzone" action=""> <form id="my-awesome-dropzone" class="dropzone" action="">
<div class="alert alert-warning text-center" id="error" style="display: none"></div>
<div class="alert alert-success text-center" id="msg" style="display: none"></div>
<div class="dropzone-previews"> <div class="dropzone-previews">
<div class="form-group"> <div class="form-group">
<div class="col-sm-10"> <div class="col-sm-10">
@ -111,10 +113,12 @@
this.on("sendingmultiple", function() { this.on("sendingmultiple", function() {
}); });
this.on("successmultiple", function(files, response) { this.on("successmultiple", function(files, response) {
alert(response) $('#msg').css('display', 'block');
$('#msg').html(response)
}); });
this.on("errormultiple", function(files, response) { this.on("errormultiple", function(files, response) {
console.log(response) $('#error').css('display', 'block');
$('#error').html(response)
}); });
} }