diff --git a/connect.py b/connect.py
index 9cfc7e063..a522c6446 100644
--- a/connect.py
+++ b/connect.py
@@ -16,16 +16,17 @@ import django
import paramiko
import struct, fcntl, signal, socket, select
from io import open as copen
+import uuid
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
if django.get_version() != '1.6':
django.setup()
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 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 jumpserver.settings import LOG_DIR
-from jperm.ansible_api import Command
+from jperm.ansible_api import Command, MyRunner
from jlog.log_api import escapeString
login_user = get_object(User, username=getpass.getuser())
@@ -484,6 +485,8 @@ class Nav(object):
4) 输入 \033[32mG/g\033[0m 显示您有权限的主机组.
5) 输入 \033[32mG/g\033[0m\033[0m + \033[32m组ID\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 退出.
"""
print textwrap.dedent(msg)
@@ -668,6 +671,91 @@ class Nav(object):
log.is_finished = True
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():
"""
@@ -701,6 +789,10 @@ def main():
elif option in ['E', 'e']:
nav.exec_cmd()
continue
+ elif option in ['U', 'u']:
+ nav.upload()
+ elif option in ['D', 'd']:
+ nav.download()
elif option in ['Q', 'q', 'exit']:
sys.exit()
else:
diff --git a/jperm/ansible_api.py b/jperm/ansible_api.py
index bcd64dee8..8ce990146 100644
--- a/jperm/ansible_api.py
+++ b/jperm/ansible_api.py
@@ -140,6 +140,22 @@ class MyRunner(MyInventory):
self.results = hoc.run()
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):
"""
diff --git a/jumpserver/api.py b/jumpserver/api.py
index d36b306d2..d73611d59 100644
--- a/jumpserver/api.py
+++ b/jumpserver/api.py
@@ -9,6 +9,7 @@ import hashlib
import datetime
import random
import subprocess
+import uuid
import json
import logging
@@ -482,5 +483,10 @@ def my_render(template, data, 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)
logger = set_log(LOG_LEVEL)
diff --git a/jumpserver/urls.py b/jumpserver/urls.py
index 361338fb1..3e3efede8 100644
--- a/jumpserver/urls.py
+++ b/jumpserver/urls.py
@@ -6,19 +6,13 @@ urlpatterns = patterns('',
(r'^$', 'jumpserver.views.index'),
(r'^api/user/$', 'jumpserver.api.api_user'),
(r'^skin_config/$', 'jumpserver.views.skin_config'),
- (r'^install/$', 'jumpserver.views.install'),
- (r'^base/$', 'jumpserver.views.base'),
(r'^login/$', 'jumpserver.views.Login'),
(r'^logout/$', 'jumpserver.views.Logout'),
(r'^file/upload/$', 'jumpserver.views.upload'),
(r'^file/download/$', 'jumpserver.views.download'),
(r'^setting', 'jumpserver.views.setting'),
- (r'^error/$', 'jumpserver.views.httperror'),
(r'^juser/', include('juser.urls')),
(r'^jasset/', include('jasset.urls')),
(r'^jlog/', include('jlog.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'),
)
diff --git a/jumpserver/views.py b/jumpserver/views.py
index be47d85d8..1e79c20e6 100644
--- a/jumpserver/views.py
+++ b/jumpserver/views.py
@@ -294,7 +294,7 @@ def upload(request):
upload_files = request.FILES.getlist('file[]', None)
date_now = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
upload_dir = "/tmp/%s/%s" % (user.username, date_now)
- mkdir(upload_dir)
+ mkdir(upload_dir, mode=0777)
filenames = {}
for asset_id in asset_ids:
asset_select.append(get_object(Asset, id=asset_id))
@@ -312,24 +312,22 @@ def upload(request):
res = gen_resource({'user': user, 'asset': asset_select})
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)
- error = '上传失败: '
- if ret.get('dark'):
- error += ','.join(ret.get('dark').keys())
-
- for asset, info in ret.get('contacted').items():
- if info.get('msg'):
- error += ',%s' % asset
- if error:
+ if ret.get('failed'):
+ error = '上传目录: %s
上传失败: [ %s ]
上传成功 [ %s ]' % (upload_dir,
+ ', '.join(ret.get('failed').keys()),
+ ', '.join(ret.get('ok')))
return HttpResponse(error, status=500)
- return HttpResponse('传送成功')
+ msg = '上传目录: %s
传送成功 [ %s ]' % (upload_dir, ', '.join(ret.get('ok')))
+ return HttpResponse(msg)
return my_render('upload.html', locals(), request)
@login_required(login_url='/login')
def download(request):
- documents = []
return render_to_response('download.html', locals(), context_instance=RequestContext(request))
diff --git a/templates/download.html b/templates/download.html
index b1da555cf..fb85a1ec7 100644
--- a/templates/download.html
+++ b/templates/download.html
@@ -16,12 +16,6 @@
-