mirror of https://github.com/jumpserver/jumpserver
批量上传下载
parent
e95c47ff6a
commit
0e6fd89f0b
96
connect.py
96
connect.py
|
@ -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:
|
||||||
|
|
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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'),
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue