mirror of https://github.com/jumpserver/jumpserver
pull/6/head
parent
fa0ec1e7d7
commit
9348a0deb7
|
@ -6,11 +6,13 @@ from django.template import RequestContext
|
||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
|
|
||||||
from models import IDC, Asset, BisGroup
|
from models import IDC, Asset, BisGroup
|
||||||
from juser.models import UserGroup, DEPT
|
from juser.models import UserGroup, DEPT, User
|
||||||
from connect import PyCrypt, KEY
|
from connect import PyCrypt, KEY
|
||||||
from jlog.models import Log
|
from jlog.models import Log
|
||||||
from jumpserver.views import jasset_group_add, jasset_host_edit, pages
|
from jumpserver.views import jasset_host_edit, pages
|
||||||
from jumpserver.api import asset_perm_api
|
from jumpserver.api import asset_perm_api
|
||||||
|
from jumpserver.api import user_perm_group_api, require_login, require_super_user, \
|
||||||
|
require_admin, is_group_admin, is_super_user, get_user_dept
|
||||||
|
|
||||||
cryptor = PyCrypt(KEY)
|
cryptor = PyCrypt(KEY)
|
||||||
|
|
||||||
|
@ -52,14 +54,20 @@ def f_add_host(ip, port, idc, jtype, group, dept, active, comment, username='',
|
||||||
a.save()
|
a.save()
|
||||||
|
|
||||||
|
|
||||||
|
@require_admin
|
||||||
def add_host(request):
|
def add_host(request):
|
||||||
login_types = {'L': 'LDAP', 'S': 'SSH_KEY', 'P': 'PASSWORD', 'M': 'MAP'}
|
login_types = {'L': 'LDAP', 'M': 'MAP'}
|
||||||
header_title, path1, path2 = u'添加主机', u'资产管理', u'添加主机'
|
header_title, path1, path2 = u'添加主机', u'资产管理', u'添加主机'
|
||||||
eidc = IDC.objects.all()
|
eidc = IDC.objects.all()
|
||||||
|
if is_super_user(request):
|
||||||
edept = DEPT.objects.all()
|
edept = DEPT.objects.all()
|
||||||
egroup = BisGroup.objects.all()
|
egroup = BisGroup.objects.all()
|
||||||
eusergroup = UserGroup.objects.all()
|
eusergroup = UserGroup.objects.all()
|
||||||
|
elif is_group_admin(request):
|
||||||
|
dept_id = get_user_dept(request)
|
||||||
|
user_id = request.session.get('user_id')
|
||||||
|
edept = DEPT.objects.get(id=dept_id)
|
||||||
|
egroup = edept.bisgroup_set.all()
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
j_ip = request.POST.get('j_ip')
|
j_ip = request.POST.get('j_ip')
|
||||||
j_idc = request.POST.get('j_idc')
|
j_idc = request.POST.get('j_idc')
|
||||||
|
@ -153,11 +161,14 @@ def batch_host_edit(request):
|
||||||
|
|
||||||
return render_to_response('jasset/host_list.html')
|
return render_to_response('jasset/host_list.html')
|
||||||
|
|
||||||
|
@require_admin
|
||||||
def list_host(request):
|
def list_host(request):
|
||||||
header_title, path1, path2 = u'查看主机', u'资产管理', u'查看主机'
|
header_title, path1, path2 = u'查看主机', u'资产管理', u'查看主机'
|
||||||
login_types = {'L': 'LDAP', 'S': 'SSH_KEY', 'P': 'PASSWORD', 'M': 'MAP'}
|
login_types = {'L': 'LDAP', 'M': 'MAP'}
|
||||||
keyword = request.GET.get('keyword', '')
|
keyword = request.GET.get('keyword', '')
|
||||||
|
dept_id = get_user_dept(request)
|
||||||
|
dept = DEPT.objects.get(id=dept_id)
|
||||||
|
if is_super_user(request):
|
||||||
if keyword:
|
if keyword:
|
||||||
posts = Asset.objects.filter(Q(ip__contains=keyword) | Q(idc__name__contains=keyword) |
|
posts = Asset.objects.filter(Q(ip__contains=keyword) | Q(idc__name__contains=keyword) |
|
||||||
Q(bis_group__name__contains=keyword) | Q(comment__contains=keyword)).distinct().order_by('ip')
|
Q(bis_group__name__contains=keyword) | Q(comment__contains=keyword)).distinct().order_by('ip')
|
||||||
|
@ -166,7 +177,14 @@ def list_host(request):
|
||||||
else:
|
else:
|
||||||
posts = Asset.objects.all().order_by('ip')
|
posts = Asset.objects.all().order_by('ip')
|
||||||
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
|
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
|
||||||
|
elif is_group_admin(request):
|
||||||
|
if keyword:
|
||||||
|
posts = Asset.objects.filter(Q(ip__contains=keyword) | Q(idc__name__contains=keyword) |
|
||||||
|
Q(bis_group__name__contains=keyword) | Q(comment__contains=keyword)).filter(dept=dept).distinct().order_by('ip')
|
||||||
|
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
|
||||||
|
else:
|
||||||
|
posts = Asset.objects.all().filter(dept=dept).order_by('ip')
|
||||||
|
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
|
||||||
return render_to_response('jasset/host_list.html', locals(), context_instance=RequestContext(request))
|
return render_to_response('jasset/host_list.html', locals(), context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
|
||||||
|
@ -329,10 +347,17 @@ def del_idc(request, offset):
|
||||||
return HttpResponseRedirect('/jasset/idc_list/')
|
return HttpResponseRedirect('/jasset/idc_list/')
|
||||||
|
|
||||||
|
|
||||||
|
@require_admin
|
||||||
def add_group(request):
|
def add_group(request):
|
||||||
header_title, path1, path2 = u'添加主机组', u'资产管理', u'添加主机组'
|
header_title, path1, path2 = u'添加主机组', u'资产管理', u'添加主机组'
|
||||||
|
if is_super_user(request):
|
||||||
posts = Asset.objects.all()
|
posts = Asset.objects.all()
|
||||||
edept = DEPT.objects.all()
|
edept = DEPT.objects.all()
|
||||||
|
elif is_group_admin(request):
|
||||||
|
dept_id = get_user_dept(request)
|
||||||
|
dept = DEPT.objects.get(id=dept_id)
|
||||||
|
posts = Asset.objects.filter(dept=dept)
|
||||||
|
edept = DEPT.objects.get(id=dept_id)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
j_group = request.POST.get('j_group')
|
j_group = request.POST.get('j_group')
|
||||||
j_dept = request.POST.get('j_dept')
|
j_dept = request.POST.get('j_dept')
|
||||||
|
@ -354,25 +379,41 @@ def add_group(request):
|
||||||
return render_to_response('jasset/group_add.html', locals(), context_instance=RequestContext(request))
|
return render_to_response('jasset/group_add.html', locals(), context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
|
||||||
|
@require_admin
|
||||||
def list_group(request):
|
def list_group(request):
|
||||||
header_title, path1, path2 = u'查看主机组', u'资产管理', u'查看主机组'
|
header_title, path1, path2 = u'查看主机组', u'资产管理', u'查看主机组'
|
||||||
|
dept_id = get_user_dept(request)
|
||||||
|
dept = DEPT.objects.get(id=dept_id)
|
||||||
keyword = request.GET.get('keyword', '')
|
keyword = request.GET.get('keyword', '')
|
||||||
|
if is_super_user(request):
|
||||||
if keyword:
|
if keyword:
|
||||||
posts = BisGroup.objects.filter(Q(name__contains=keyword) | Q(comment__contains=keyword))
|
posts = BisGroup.objects.filter(Q(name__contains=keyword) | Q(comment__contains=keyword))
|
||||||
else:
|
else:
|
||||||
posts = BisGroup.objects.all().order_by('id')
|
posts = BisGroup.objects.all().order_by('id')
|
||||||
|
elif is_group_admin(request):
|
||||||
|
if keyword:
|
||||||
|
posts = BisGroup.objects.filter(Q(name__contains=keyword) | Q(comment__contains=keyword)).filter(dept=dept)
|
||||||
|
else:
|
||||||
|
posts = BisGroup.objects.all().filter(dept=dept).order_by('id')
|
||||||
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
|
contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request)
|
||||||
|
|
||||||
return render_to_response('jasset/group_list.html', locals(), context_instance=RequestContext(request))
|
return render_to_response('jasset/group_list.html', locals(), context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
|
||||||
|
@require_admin
|
||||||
def edit_group(request):
|
def edit_group(request):
|
||||||
header_title, path1, path2 = u'编辑主机组', u'资产管理', u'编辑主机组'
|
header_title, path1, path2 = u'编辑主机组', u'资产管理', u'编辑主机组'
|
||||||
group_id = request.GET.get('id')
|
group_id = request.GET.get('id')
|
||||||
group = BisGroup.objects.get(id=group_id)
|
group = BisGroup.objects.get(id=group_id)
|
||||||
all = Asset.objects.all()
|
all = Asset.objects.all()
|
||||||
|
dept_id = get_user_dept(request)
|
||||||
|
edept = DEPT.objects.get(id=dept_id)
|
||||||
eposts = contact_list = Asset.objects.filter(bis_group=group).order_by('ip')
|
eposts = contact_list = Asset.objects.filter(bis_group=group).order_by('ip')
|
||||||
|
if is_super_user(request):
|
||||||
posts = [g for g in all if g not in eposts]
|
posts = [g for g in all if g not in eposts]
|
||||||
|
elif is_group_admin(request):
|
||||||
|
dept = DEPT.objects.get(id=dept_id)
|
||||||
|
all_dept = Asset.objects.filter(dept=dept)
|
||||||
|
posts = [g for g in all_dept if g not in eposts]
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
j_group = request.POST.get('j_group')
|
j_group = request.POST.get('j_group')
|
||||||
j_hosts = request.POST.getlist('j_hosts')
|
j_hosts = request.POST.getlist('j_hosts')
|
||||||
|
|
|
@ -9,7 +9,7 @@ database = jumpserver
|
||||||
|
|
||||||
[ldap]
|
[ldap]
|
||||||
ldap_enable = 1
|
ldap_enable = 1
|
||||||
host_url = ldap://127.0.0.1:389
|
host_url = ldap://192.168.8.230:389
|
||||||
base_dn = dc=fengxing, dc=com
|
base_dn = dc=fengxing, dc=com
|
||||||
root_dn = cn=admin,dc=fengxing,dc=com
|
root_dn = cn=admin,dc=fengxing,dc=com
|
||||||
root_pw = 123456
|
root_pw = 123456
|
||||||
|
|
|
@ -80,18 +80,27 @@ def require_admin(func):
|
||||||
|
|
||||||
|
|
||||||
def is_super_user(request):
|
def is_super_user(request):
|
||||||
if request.session.get('role_id') == '2':
|
if request.session.get('role_id') == 2:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def is_group_admin(request):
|
def is_group_admin(request):
|
||||||
if request.session.get('role_id') == '1':
|
print request.session.get('role_id'), type(request.session.get('role_id'))
|
||||||
|
if request.session.get('role_id') == 1:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_dept(request):
|
||||||
|
user_id = request.session.get('user_id')
|
||||||
|
if user_id:
|
||||||
|
user_dept = User.objects.get(id=user_id).dept
|
||||||
|
return user_dept.id
|
||||||
|
|
||||||
|
|
||||||
def api_user(request):
|
def api_user(request):
|
||||||
hosts = Log.objects.filter(is_finished=0).count()
|
hosts = Log.objects.filter(is_finished=0).count()
|
||||||
users = Log.objects.filter(is_finished=0).values('user').distinct().count()
|
users = Log.objects.filter(is_finished=0).values('user').distinct().count()
|
||||||
|
|
|
@ -0,0 +1,396 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import ast
|
||||||
|
import select
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
import paramiko
|
||||||
|
import struct
|
||||||
|
import fcntl
|
||||||
|
import signal
|
||||||
|
import textwrap
|
||||||
|
import django
|
||||||
|
import getpass
|
||||||
|
import fnmatch
|
||||||
|
import optparse
|
||||||
|
import readline
|
||||||
|
from multiprocessing import Pool
|
||||||
|
from ConfigParser import ConfigParser
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings'
|
||||||
|
django.setup()
|
||||||
|
from juser.models import User
|
||||||
|
from jasset.models import Asset
|
||||||
|
from jlog.models import Log
|
||||||
|
from jumpserver.views import PyCrypt
|
||||||
|
from jumpserver.api import user_perm_asset_api, user_perm_group_api
|
||||||
|
|
||||||
|
try:
|
||||||
|
import termios
|
||||||
|
import tty
|
||||||
|
except ImportError:
|
||||||
|
print '\033[1;31mOnly postfix supported.\033[0m'
|
||||||
|
time.sleep(3)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
BASE_DIR = os.path.dirname(CURRENT_DIR)
|
||||||
|
CONF = ConfigParser()
|
||||||
|
CONF.read(os.path.join(BASE_DIR, 'jumpserver.conf'))
|
||||||
|
LOG_DIR = os.path.join(BASE_DIR, 'logs')
|
||||||
|
SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys')
|
||||||
|
SERVER_KEY_DIR = os.path.join(SSH_KEY_DIR, 'server')
|
||||||
|
KEY = CONF.get('web', 'key')
|
||||||
|
LOGIN_NAME = getpass.getuser()
|
||||||
|
|
||||||
|
|
||||||
|
def color_print(msg, color='blue'):
|
||||||
|
"""Print colorful string."""
|
||||||
|
color_msg = {'blue': '\033[1;36m%s\033[0m',
|
||||||
|
'green': '\033[1;32m%s\033[0m',
|
||||||
|
'red': '\033[1;31m%s\033[0m'}
|
||||||
|
|
||||||
|
print color_msg.get(color, 'blue') % msg
|
||||||
|
|
||||||
|
|
||||||
|
def color_print_exit(msg, color='red'):
|
||||||
|
"""Print colorful string and exit."""
|
||||||
|
color_print(msg, color=color)
|
||||||
|
time.sleep(2)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
|
class ServerError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_win_size():
|
||||||
|
"""This function use to get the size of the windows!"""
|
||||||
|
if 'TIOCGWINSZ' in dir(termios):
|
||||||
|
TIOCGWINSZ = termios.TIOCGWINSZ
|
||||||
|
else:
|
||||||
|
TIOCGWINSZ = 1074295912L # Assume
|
||||||
|
s = struct.pack('HHHH', 0, 0, 0, 0)
|
||||||
|
x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s)
|
||||||
|
return struct.unpack('HHHH', x)[0:2]
|
||||||
|
|
||||||
|
|
||||||
|
def set_win_size(sig, data):
|
||||||
|
"""This function use to set the window size of the terminal!"""
|
||||||
|
try:
|
||||||
|
win_size = get_win_size()
|
||||||
|
channel.resize_pty(height=win_size[0], width=win_size[1])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_object(model, **kwargs):
|
||||||
|
try:
|
||||||
|
the_object = model.objects.get(**kwargs)
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
raise ServerError('Object get %s failed.' % str(kwargs.values()))
|
||||||
|
return the_object
|
||||||
|
|
||||||
|
|
||||||
|
def log_record(username, host):
|
||||||
|
"""Logging user command and output."""
|
||||||
|
connect_log_dir = os.path.join(LOG_DIR, 'connect')
|
||||||
|
timestamp_start = int(time.time())
|
||||||
|
today = time.strftime('%Y%m%d', time.localtime(timestamp_start))
|
||||||
|
time_now = time.strftime('%H%M%S', time.localtime(timestamp_start))
|
||||||
|
today_connect_log_dir = os.path.join(connect_log_dir, today)
|
||||||
|
log_filename = '%s_%s_%s.log' % (username, host, time_now)
|
||||||
|
log_file_path = os.path.join(today_connect_log_dir, log_filename)
|
||||||
|
pid = os.getpid()
|
||||||
|
ip_list = []
|
||||||
|
remote_ip = os.popen("who |grep `ps aux |gawk '{if ($2==%s) print $1}'` |gawk '{print $5}'|tr -d '()'" % pid).readlines()
|
||||||
|
for ip in remote_ip:
|
||||||
|
ip_list.append(ip.strip('\n'))
|
||||||
|
ip_list = ','.join(list(set(ip_list)))
|
||||||
|
|
||||||
|
if not os.path.isdir(today_connect_log_dir):
|
||||||
|
try:
|
||||||
|
os.makedirs(today_connect_log_dir)
|
||||||
|
os.chmod(today_connect_log_dir, 0777)
|
||||||
|
except OSError:
|
||||||
|
raise ServerError('Create %s failed, Please modify %s permission.' % (today_connect_log_dir, connect_log_dir))
|
||||||
|
|
||||||
|
try:
|
||||||
|
log_file = open(log_file_path, 'a')
|
||||||
|
except IOError:
|
||||||
|
raise ServerError('Create logfile failed, Please modify %s permission.' % today_connect_log_dir)
|
||||||
|
|
||||||
|
log = Log(user=username, host=host, remote_ip=ip_list, log_path=log_file_path, start_time=datetime.now(), pid=pid)
|
||||||
|
log_file.write('Starttime is %s\n' % datetime.now())
|
||||||
|
log.save()
|
||||||
|
return log_file, log
|
||||||
|
|
||||||
|
|
||||||
|
def posix_shell(chan, username, host):
|
||||||
|
"""
|
||||||
|
Use paramiko channel connect server interactive.
|
||||||
|
"""
|
||||||
|
log_file, log = log_record(username, host)
|
||||||
|
old_tty = termios.tcgetattr(sys.stdin)
|
||||||
|
try:
|
||||||
|
tty.setraw(sys.stdin.fileno())
|
||||||
|
tty.setcbreak(sys.stdin.fileno())
|
||||||
|
chan.settimeout(0.0)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
r, w, e = select.select([chan, sys.stdin], [], [])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if chan in r:
|
||||||
|
try:
|
||||||
|
x = chan.recv(1024)
|
||||||
|
if len(x) == 0:
|
||||||
|
break
|
||||||
|
sys.stdout.write(x)
|
||||||
|
sys.stdout.flush()
|
||||||
|
log_file.write(x)
|
||||||
|
log_file.flush()
|
||||||
|
except socket.timeout:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if sys.stdin in r:
|
||||||
|
x = os.read(sys.stdin.fileno(), 1)
|
||||||
|
if len(x) == 0:
|
||||||
|
break
|
||||||
|
chan.send(x)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
timestamp_end = time.time()
|
||||||
|
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
|
||||||
|
log_file.write('Endtime is %s' % datetime.now())
|
||||||
|
log_file.close()
|
||||||
|
log.is_finished = True
|
||||||
|
log.log_finished = False
|
||||||
|
log.end_time = datetime.now()
|
||||||
|
log.save()
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_host(username):
|
||||||
|
"""Get the hosts of under the user control."""
|
||||||
|
hosts_attr = {}
|
||||||
|
asset_all = user_perm_asset_api(username)
|
||||||
|
for asset in asset_all:
|
||||||
|
hosts_attr[asset.ip] = [asset.id, asset.comment]
|
||||||
|
return hosts_attr
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_hostgroup(username):
|
||||||
|
"""Get the hostgroups of under the user control."""
|
||||||
|
groups_attr = {}
|
||||||
|
group_all = user_perm_group_api(username)
|
||||||
|
for group in group_all:
|
||||||
|
groups_attr[group.name] = [group.id, group.comment]
|
||||||
|
return groups_attr
|
||||||
|
|
||||||
|
|
||||||
|
def get_connect_item(username, ip):
|
||||||
|
cryptor = PyCrypt(KEY)
|
||||||
|
|
||||||
|
asset = get_object(Asset, ip=ip)
|
||||||
|
port = asset.port
|
||||||
|
|
||||||
|
if not asset.is_active:
|
||||||
|
raise ServerError('Host %s is not active.' % ip)
|
||||||
|
|
||||||
|
user = get_object(User, username=username)
|
||||||
|
|
||||||
|
if not user.is_active:
|
||||||
|
raise ServerError('User %s is not active.' % username)
|
||||||
|
|
||||||
|
login_type_dict = {
|
||||||
|
'L': user.ldap_pwd,
|
||||||
|
}
|
||||||
|
|
||||||
|
if asset.login_type in login_type_dict:
|
||||||
|
password = cryptor.decrypt(login_type_dict[asset.login_type])
|
||||||
|
return username, password, ip, port
|
||||||
|
|
||||||
|
elif asset.login_type == 'M':
|
||||||
|
username = asset.username
|
||||||
|
password = cryptor.decrypt(asset.password)
|
||||||
|
return username, password, ip, port
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ServerError('Login type is not in ["L", "M"]')
|
||||||
|
|
||||||
|
|
||||||
|
def verify_connect(username, part_ip):
|
||||||
|
hosts_attr = get_user_host(username)
|
||||||
|
hosts = hosts_attr.keys()
|
||||||
|
ip_matched = [ip for ip in hosts if part_ip in ip]
|
||||||
|
|
||||||
|
if len(ip_matched) > 1:
|
||||||
|
for ip in ip_matched:
|
||||||
|
print '%s -- %s' % (ip, hosts_attr[ip][1])
|
||||||
|
elif len(ip_matched) < 1:
|
||||||
|
color_print('No Permission or No host.', 'red')
|
||||||
|
else:
|
||||||
|
username, password, host, port = get_connect_item(username, ip_matched[0])
|
||||||
|
print username, password, host, port
|
||||||
|
connect(username, password, host, port, LOGIN_NAME)
|
||||||
|
|
||||||
|
|
||||||
|
def print_prompt():
|
||||||
|
msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m
|
||||||
|
1) Type \033[32mIP ADDRESS\033[0m To Login.
|
||||||
|
2) Type \033[32mP/p\033[0m To Print The Servers You Available.
|
||||||
|
3) Type \033[32mG/g\033[0m To Print The Server Groups You Available.
|
||||||
|
4) Type \033[32mE/e\033[0m To Execute Command On Several Servers.
|
||||||
|
5) Type \033[32mQ/q\033[0m To Quit.
|
||||||
|
"""
|
||||||
|
print textwrap.dedent(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def print_user_host(username):
|
||||||
|
hosts_attr = get_user_host(username)
|
||||||
|
hosts = hosts_attr.keys()
|
||||||
|
hosts.sort()
|
||||||
|
for ip in hosts:
|
||||||
|
print '%s -- %s' % (ip, hosts_attr[ip][1])
|
||||||
|
|
||||||
|
|
||||||
|
def print_user_hostgroup(username):
|
||||||
|
group_attr = get_user_hostgroup(username)
|
||||||
|
groups = group_attr.keys()
|
||||||
|
for g in groups:
|
||||||
|
print '%s -- %s' % (g, group_attr[g][1])
|
||||||
|
|
||||||
|
|
||||||
|
def connect(username, password, host, port, login_name):
|
||||||
|
"""
|
||||||
|
Connect server.
|
||||||
|
"""
|
||||||
|
ps1 = "PS1='[\u@%s \W]\$ '\n" % host
|
||||||
|
login_msg = "clear;echo -e '\\033[32mLogin %s done. Enjoy it.\\033[0m'\n" % host
|
||||||
|
|
||||||
|
# Make a ssh connection
|
||||||
|
ssh = paramiko.SSHClient()
|
||||||
|
ssh.load_system_host_keys()
|
||||||
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
|
try:
|
||||||
|
ssh.connect(host, port=port, username=username, password=password, compress=True)
|
||||||
|
except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException:
|
||||||
|
raise ServerError('Authentication Error.')
|
||||||
|
except socket.error:
|
||||||
|
raise ServerError('Connect SSH Socket Port Error, Please Correct it.')
|
||||||
|
|
||||||
|
# Make a channel and set windows size
|
||||||
|
global channel
|
||||||
|
win_size = get_win_size()
|
||||||
|
channel = ssh.invoke_shell(height=win_size[0], width=win_size[1])
|
||||||
|
#channel.resize_pty(height=win_size[0], width=win_size[1])
|
||||||
|
try:
|
||||||
|
signal.signal(signal.SIGWINCH, set_win_size)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Set PS1 and msg it
|
||||||
|
channel.send(ps1)
|
||||||
|
channel.send(login_msg)
|
||||||
|
|
||||||
|
# Make ssh interactive tunnel
|
||||||
|
posix_shell(channel, login_name, host)
|
||||||
|
|
||||||
|
# Shutdown channel socket
|
||||||
|
channel.close()
|
||||||
|
ssh.close()
|
||||||
|
|
||||||
|
|
||||||
|
def remote_exec_cmd(ip, port, username, password, cmd):
|
||||||
|
try:
|
||||||
|
time.sleep(5)
|
||||||
|
ssh = paramiko.SSHClient()
|
||||||
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
|
ssh.connect(ip, port, username, password, timeout=5)
|
||||||
|
stdin, stdout, stderr = ssh.exec_command("bash -l -c '%s'" % cmd)
|
||||||
|
out = stdout.readlines()
|
||||||
|
err = stderr.readlines()
|
||||||
|
color_print('%s:' %ip, 'blue')
|
||||||
|
for i in out:
|
||||||
|
color_print(" " * 4 + i.strip(), 'green')
|
||||||
|
for j in err:
|
||||||
|
color_print(" " * 4 + j.strip(), 'red')
|
||||||
|
ssh.close()
|
||||||
|
except Exception as e:
|
||||||
|
color_print(ip + ':', 'blue')
|
||||||
|
color_print(str(e), 'red')
|
||||||
|
|
||||||
|
|
||||||
|
def multi_remote_exec_cmd(hosts, username, cmd):
|
||||||
|
pool = Pool(processes=5)
|
||||||
|
for host in hosts:
|
||||||
|
username, password, ip, port = get_connect_item(username, host)
|
||||||
|
pool.apply_async(remote_exec_cmd, (ip, port, username, password, cmd))
|
||||||
|
pool.close()
|
||||||
|
pool.join()
|
||||||
|
|
||||||
|
|
||||||
|
def exec_cmd_servers(username):
|
||||||
|
hosts = []
|
||||||
|
color_print("Input the Host IP(s),Separated by Commas, q/Q to Quit.\n \
|
||||||
|
You can choose in the following IP(s), Use Linux / Unix glob.", 'green')
|
||||||
|
print_user_host(LOGIN_NAME)
|
||||||
|
while True:
|
||||||
|
inputs = raw_input('\033[1;32mip(s)>: \033[0m')
|
||||||
|
if inputs in ['q', 'Q']:
|
||||||
|
break
|
||||||
|
get_hosts = get_user_host(username).keys()
|
||||||
|
for host in get_hosts:
|
||||||
|
if fnmatch.fnmatch(host, inputs):
|
||||||
|
hosts.append(host.strip())
|
||||||
|
if len(hosts) == 0:
|
||||||
|
color_print("Check again, Not matched any ip!", 'red')
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
print "You matched ip: %s" % hosts
|
||||||
|
color_print("Input the Command , The command will be Execute on servers, q/Q to quit.", 'green')
|
||||||
|
while True:
|
||||||
|
cmd = raw_input('\033[1;32mCmd(s): \033[0m')
|
||||||
|
if cmd in ['q', 'Q']:
|
||||||
|
break
|
||||||
|
exec_log_dir = os.path.join(LOG_DIR, 'exec_cmds')
|
||||||
|
if not os.path.isdir(exec_log_dir):
|
||||||
|
os.mkdir(exec_log_dir)
|
||||||
|
os.chmod(exec_log_dir, 0777)
|
||||||
|
filename = "%s/%s.log" % (exec_log_dir, time.strftime('%Y%m%d'))
|
||||||
|
f = open(filename, 'a')
|
||||||
|
f.write("DateTime: %s User: %s Host: %s Cmds: %s\n" %
|
||||||
|
(time.strftime('%Y/%m/%d %H:%M:%S'), username, hosts, cmd))
|
||||||
|
multi_remote_exec_cmd(hosts, username, cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def help():
|
||||||
|
global p, options, arguments
|
||||||
|
usage = "usage: %prog '' [options] arg1 [options] arg2"
|
||||||
|
p = optparse.OptionParser(usage=usage)
|
||||||
|
p.add_option('-p', '--host', help = "Print The Servers You Available.")
|
||||||
|
p.add_option('-g', '--group', help = "Print The Server Groups You Available.")
|
||||||
|
options, arguments = p.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
help()
|
||||||
|
if options.host:
|
||||||
|
pass
|
||||||
|
elif options.group:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
verify_connect(LOGIN_NAME, sys.argv[1])
|
||||||
|
except ServerError, e:
|
||||||
|
color_print(e, 'red')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -1,4 +1,5 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
{% load mytags %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% include 'nav_cat_bar.html' %}
|
{% include 'nav_cat_bar.html' %}
|
||||||
<div class="wrapper wrapper-content animated fadeInRight">
|
<div class="wrapper wrapper-content animated fadeInRight">
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
<div class="col-sm-8" name="group_id" value="{{ post.id }}"><input type="text" value="{{ group.name }}" placeholder="网站" name="j_group" class="form-control"></div>
|
<div class="col-sm-8" name="group_id" value="{{ post.id }}"><input type="text" value="{{ group.name }}" placeholder="网站" name="j_group" class="form-control"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% ifequal session_role_id 2 %}
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="j_dept" class="col-lg-2 control-label">所属部门<span class="red-fonts">*</span></label>
|
<label for="j_dept" class="col-lg-2 control-label">所属部门<span class="red-fonts">*</span></label>
|
||||||
|
@ -31,6 +33,15 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endifequal %}
|
||||||
|
|
||||||
|
{% ifequal session_role_id 1 %}
|
||||||
|
<div class="hr-line-dashed"></div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="j_dept" class="col-lg-2 control-label">所属部门<span class="red-fonts">*</span></label>
|
||||||
|
<div class="col-sm-8"><input type="text" name="j_dept" value="{{ edept.name }}" class="form-control" readonly="readonly"></div>
|
||||||
|
</div>
|
||||||
|
{% endifequal %}
|
||||||
|
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
{% load mytags %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% include 'nav_cat_bar.html' %}
|
{% include 'nav_cat_bar.html' %}
|
||||||
<div class="wrapper wrapper-content animated fadeInRight">
|
<div class="wrapper wrapper-content animated fadeInRight">
|
||||||
|
@ -84,6 +85,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{% ifequal session_role_id 2 %}
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="j_dept" class="col-lg-2 control-label">所属部门<span class="red-fonts">*</span></label>
|
<label for="j_dept" class="col-lg-2 control-label">所属部门<span class="red-fonts">*</span></label>
|
||||||
|
@ -95,6 +97,14 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endifequal %}
|
||||||
|
|
||||||
|
{% ifequal session_role_id 1 %}
|
||||||
|
<div class="hr-line-dashed"></div>
|
||||||
|
<div class="form-group"><label class="col-sm-2 control-label"> 所属部门 </label>
|
||||||
|
<div class="col-sm-8"><input type="text" name="j_dept" value="{{ edept.name }}" class="form-control" readonly="readonly"></div>
|
||||||
|
</div>
|
||||||
|
{% endifequal %}
|
||||||
|
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
|
@ -103,7 +103,6 @@
|
||||||
<li id="host_list"><a href="/jasset/host_list/">查看资产  </span><span class="label label-info pull-right">16/18</span></a></li>
|
<li id="host_list"><a href="/jasset/host_list/">查看资产  </span><span class="label label-info pull-right">16/18</span></a></li>
|
||||||
<li id="jgroup_add"><a href="/jasset/jgroup_add/">添加主机组</a></li>
|
<li id="jgroup_add"><a href="/jasset/jgroup_add/">添加主机组</a></li>
|
||||||
<li id="jgroup_list"><a href="/jasset/jgroup_list/">查看主机组</a></li>
|
<li id="jgroup_list"><a href="/jasset/jgroup_list/">查看主机组</a></li>
|
||||||
<li id="idc_add"><a href="/jasset/idc_add/">添加IDC</a></li>
|
|
||||||
<li id="idc_list"><a href="/jasset/idc_list/">查看IDC</a></li>
|
<li id="idc_list"><a href="/jasset/idc_list/">查看IDC</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
Loading…
Reference in New Issue