mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-12-21 03:26:03 +00:00
Compare commits
191 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aba3a2222d | ||
|
|
a49b944e29 | ||
|
|
333e2a20ff | ||
|
|
59c770a3bf | ||
|
|
df5227d48a | ||
|
|
8d0bf4c625 | ||
|
|
d1238efb6f | ||
|
|
8fcccbb8bc | ||
|
|
313a20d189 | ||
|
|
9c4fb88b7a | ||
|
|
3c1b1b18e4 | ||
|
|
0d7f65db1c | ||
|
|
ea39dfb415 | ||
|
|
9f9b08f6bc | ||
|
|
52a98b11e7 | ||
|
|
f6d414d903 | ||
|
|
eae5535b42 | ||
|
|
d9d3f25dfd | ||
|
|
d6b6e745b2 | ||
|
|
f903750d58 | ||
|
|
61ac985e09 | ||
|
|
22c7cb6c7d | ||
|
|
24415f5b24 | ||
|
|
931ac3dd1f | ||
|
|
99313cd2db | ||
|
|
7e6a4621c5 | ||
|
|
fa2358d22b | ||
|
|
0f63eadfc1 | ||
|
|
4844f7861b | ||
|
|
9ad9a8812f | ||
|
|
d036ef7f0a | ||
|
|
b211856394 | ||
|
|
71299df131 | ||
|
|
6bacda6a9a | ||
|
|
dc782ca5b5 | ||
|
|
4a9923db4b | ||
|
|
9d7641ad8a | ||
|
|
a7904a8d57 | ||
|
|
a4e6fef2a6 | ||
|
|
6c762b865a | ||
|
|
c424cad244 | ||
|
|
16ec34c463 | ||
|
|
44ef066ede | ||
|
|
f947a753db | ||
|
|
532cefe338 | ||
|
|
62bc814a44 | ||
|
|
dc11f34585 | ||
|
|
a5c3048a89 | ||
|
|
41b7110554 | ||
|
|
d38a963dbd | ||
|
|
b1aff5c997 | ||
|
|
f5b02265a4 | ||
|
|
21ab6cbe1e | ||
|
|
0560ccaf17 | ||
|
|
0e3c79fb79 | ||
|
|
1c9359bb4c | ||
|
|
1c4adc1e38 | ||
|
|
a5abd9d620 | ||
|
|
2ca299a31f | ||
|
|
1c930b31d9 | ||
|
|
331f029096 | ||
|
|
586e2602db | ||
|
|
83ac653637 | ||
|
|
d1ea2a6dd1 | ||
|
|
4f2bc9d402 | ||
|
|
3bee29338c | ||
|
|
26c31feb4a | ||
|
|
d8e4efe7cc | ||
|
|
fc3d13a4b1 | ||
|
|
d134b2279b | ||
|
|
f3efa9b914 | ||
|
|
9cdd62b62d | ||
|
|
271b80991a | ||
|
|
5f302866ca | ||
|
|
cce2bb5590 | ||
|
|
a01c1a40b9 | ||
|
|
c82b8f1128 | ||
|
|
862cec316f | ||
|
|
5445e5eaa1 | ||
|
|
22bcda23dc | ||
|
|
fcabb66f2e | ||
|
|
5b2911a5ed | ||
|
|
969d54050f | ||
|
|
92188f1c77 | ||
|
|
c18290c667 | ||
|
|
19b94655fb | ||
|
|
825adba39c | ||
|
|
2d28a7a0c4 | ||
|
|
4a09ce32e6 | ||
|
|
0ccb808b3f | ||
|
|
08c30e462c | ||
|
|
654c27490d | ||
|
|
06e788782b | ||
|
|
7d868c5195 | ||
|
|
2212cf24b4 | ||
|
|
d728c06851 | ||
|
|
b52420708e | ||
|
|
5bc67ebad9 | ||
|
|
a57adf9b2e | ||
|
|
aa9139c642 | ||
|
|
efbcacbec6 | ||
|
|
e5121fe7ea | ||
|
|
ac926b5fb4 | ||
|
|
44166e2653 | ||
|
|
e38fb5992f | ||
|
|
765ac5e714 | ||
|
|
f766ba340f | ||
|
|
5b060a768a | ||
|
|
54da30d93b | ||
|
|
838b10d3b6 | ||
|
|
cd84f0d5c6 | ||
|
|
641b72f3d1 | ||
|
|
63065f5c33 | ||
|
|
de2837229c | ||
|
|
596573293f | ||
|
|
93bd02017c | ||
|
|
2e1c7d2fb8 | ||
|
|
78b55f981c | ||
|
|
fb8b800fd7 | ||
|
|
67b0cd5522 | ||
|
|
68e8c4ba0f | ||
|
|
1b08c6ea88 | ||
|
|
6ae84b3334 | ||
|
|
6418033e51 | ||
|
|
f48dd46898 | ||
|
|
9020c11bd2 | ||
|
|
50b7d00683 | ||
|
|
e3078d2ac6 | ||
|
|
582418797d | ||
|
|
031b92bf03 | ||
|
|
1a529a7d7f | ||
|
|
f4591e3aad | ||
|
|
14c48bc1bf | ||
|
|
30cbf15b57 | ||
|
|
41dbfbb335 | ||
|
|
9191d3b6e5 | ||
|
|
d0a5274214 | ||
|
|
7f132e100f | ||
|
|
61fcfb80a8 | ||
|
|
046d4da45c | ||
|
|
94830a79a3 | ||
|
|
bb0a023380 | ||
|
|
c8444ef73a | ||
|
|
7c5f2d216f | ||
|
|
201ef814f9 | ||
|
|
00f6984929 | ||
|
|
f2e39f24c8 | ||
|
|
cd3f787aef | ||
|
|
86a9c46643 | ||
|
|
d639801f3c | ||
|
|
4517ec0629 | ||
|
|
9601476077 | ||
|
|
e2e067139c | ||
|
|
42d130d5c2 | ||
|
|
632b863cf7 | ||
|
|
83f8f5a150 | ||
|
|
1f272aa03c | ||
|
|
222162eaa7 | ||
|
|
102e832a58 | ||
|
|
e8ab3e45f3 | ||
|
|
ec4a9e92bf | ||
|
|
16a2d3803a | ||
|
|
4d58d9ef0e | ||
|
|
a263e50b3e | ||
|
|
6e2ebd5c79 | ||
|
|
86b8124bec | ||
|
|
c588aaea3a | ||
|
|
52e567b157 | ||
|
|
5fd15478a8 | ||
|
|
5ccffe6c1d | ||
|
|
7d32a9a9e9 | ||
|
|
0d5ff30acf | ||
|
|
a68454f7a4 | ||
|
|
d4f40feebf | ||
|
|
a25b2df453 | ||
|
|
a6f53fc99d | ||
|
|
35e74f3c10 | ||
|
|
1ea85c3b19 | ||
|
|
8756172b9b | ||
|
|
d4ef81edc6 | ||
|
|
0f18e702e8 | ||
|
|
63cdef4218 | ||
|
|
8596bc4997 | ||
|
|
e72aba98e6 | ||
|
|
8b13967570 | ||
|
|
0d842fe3ec | ||
|
|
73d61e09ed | ||
|
|
45b874fcd8 | ||
|
|
538b8c8a35 | ||
|
|
78d7255190 | ||
|
|
07ee63f04c |
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.idea
|
||||
*.pyc
|
||||
*.log
|
||||
69
README.md
69
README.md
@@ -1,36 +1,39 @@
|
||||
开源运维堡垒机(跳板机)系统
|
||||
==============================
|
||||
Jumpserver是什么?
|
||||
-----------------
|
||||
Jumpserver是用Python+Django写的一个开源的跳板机(堡垒机)项目,来集中管理服务器的账号、密码和权限。
|
||||
|
||||
介绍和文档:
|
||||
--------------
|
||||
介绍和部署: [我的博客](http://laoguang.blog.51cto.com/6013350/1540080)
|
||||
1.1版本更新
|
||||
-----------------
|
||||
更新Log见笔者blog<br>
|
||||
http://laoguang.blog.51cto.com/6013350/1576502
|
||||
|
||||
部署文档
|
||||
-----------------
|
||||
部署文档见笔者blog<br>
|
||||
http://laoguang.blog.51cto.com/6013350/1576729
|
||||
|
||||
截图:
|
||||
-------------
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
功能截图
|
||||
-----------------
|
||||
1. 安装<br>
|
||||

|
||||
2. 登陆<br>
|
||||

|
||||
3. 添加组<br>
|
||||

|
||||
4. 添加用户<br>
|
||||
5. 添加主机<br>
|
||||
6. 添加权限<br>
|
||||
7. 查看权限<br>
|
||||
8. 下载私钥<br>
|
||||
9. 登陆shell<br>
|
||||
10. 显示有权限的主机<br>
|
||||
11. 批量执行命令<br>
|
||||
12. 登陆有权限的主机<br>
|
||||
13. 查看sudo<br>
|
||||
14. 修改sudo<br>
|
||||
15. 查看实时监控<br>
|
||||
16. 结束会话<br>
|
||||
17. 查看统计日志<br>
|
||||
18. 修改密码<br>
|
||||
19. 下载文件<br>
|
||||
20. 上传文件<br>
|
||||
|
||||
21
chgpass.sh
21
chgpass.sh
@@ -1,21 +0,0 @@
|
||||
#!/bin/bash
|
||||
username=$1
|
||||
password=$2
|
||||
|
||||
cwd (){
|
||||
dir=$0
|
||||
dirname $dir
|
||||
}
|
||||
|
||||
dir=$(cwd)
|
||||
. ${dir}/shell.conf
|
||||
|
||||
id ${username} &> /dev/null
|
||||
if [ $? != 0 ];then
|
||||
echo "$username is not exist."
|
||||
exit 3
|
||||
fi
|
||||
|
||||
echo "$password" | passwd --stdin "$username"
|
||||
|
||||
#ssh -p $host2_port $host2 "echo \"$password\" | passwd --stdin \"$username\""
|
||||
37
genkey.sh
37
genkey.sh
@@ -1,37 +0,0 @@
|
||||
#!/bin/bash
|
||||
user=$1
|
||||
password=$2
|
||||
|
||||
cwd (){
|
||||
dir=$0
|
||||
dirname $dir
|
||||
}
|
||||
|
||||
dir=$(cwd)
|
||||
. ${dir}/shell.conf
|
||||
|
||||
keyfile=${dir}/keys/${user}
|
||||
rm -f ${keyfile}
|
||||
|
||||
gen_key() {
|
||||
ssh-keygen -t rsa -f ${keyfile} -P $1
|
||||
}
|
||||
|
||||
if [ -z $1 ] || [ -z $2 ];then
|
||||
echo "Usage: ./script user password"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
gen_key ${password}
|
||||
|
||||
mkdir -p /home/${user}/.ssh
|
||||
#ssh -p ${host2_port} ${host2} "mkdir -p /home/$user/.ssh"
|
||||
|
||||
cat ${keyfile}.pub > /home/${user}/.ssh/authorized_keys
|
||||
#ssh -p ${host2_port} ${host2} "cat > /home/$user/.ssh/authorized_keys" < ${keyfile}.pub
|
||||
|
||||
chmod 600 /home/${user}/.ssh/authorized_keys
|
||||
#ssh -p ${host2_port} ${host2} "chmod 600 /home/$user/.ssh/authorized_keys"
|
||||
|
||||
chown -R ${user}:${user} /home/${user}/.ssh
|
||||
#ssh -p ${host2_port} ${host2} "chown -R $user:$user /home/$user/.ssh"
|
||||
@@ -8,14 +8,9 @@ password = redhat
|
||||
db = jumpserver
|
||||
|
||||
[jumpserver]
|
||||
log_dir = /opt/jumpserver/logs/
|
||||
user_table = UserManage_user
|
||||
assets_table = Assets_assets
|
||||
assets_user_table = Assets_assetsuser
|
||||
key = 88aaaf7ffe3c6c04
|
||||
useradd_shell = /opt/jumpserver/useradd.sh
|
||||
userdel_shell = /opt/jumpserver/userdel.sh
|
||||
sudoadd_shell = /opt/jumpserver/sudoadd.sh
|
||||
sudodel_shell = /opt/jumpserver/sudodel.sh
|
||||
keygen_shell = /opt/jumpserver/genkey.sh
|
||||
chgpass_shell = /opt/jumpserver/chgpass.sh
|
||||
ldap_host = ldap://127.0.0.1:389
|
||||
ldap_base_dn = dc=yolu,dc=com
|
||||
admin_cn = cn=admin,dc=yolu,dc=com
|
||||
admin_pass = VNLqNCjpNBIetEoCA2h3
|
||||
web_socket_host = 172.10.10.9:3000
|
||||
204
jumpserver.py
204
jumpserver.py
@@ -1,11 +1,10 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import MySQLdb
|
||||
import pexpect
|
||||
import struct
|
||||
import fcntl
|
||||
import termios
|
||||
@@ -16,20 +15,28 @@ from Crypto.Cipher import AES
|
||||
from binascii import b2a_hex, a2b_hex
|
||||
import ConfigParser
|
||||
import paramiko
|
||||
import pxssh
|
||||
import pexpect
|
||||
|
||||
cur_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
sys.path.append('%s/webroot/AutoSa/' % cur_dir)
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'AutoSa.settings'
|
||||
|
||||
import django
|
||||
django.setup()
|
||||
from UserManage.models import User, Logs, Pid
|
||||
from Assets.models import Assets
|
||||
|
||||
|
||||
base_dir = "/opt/jumpserver/"
|
||||
cf = ConfigParser.ConfigParser()
|
||||
cf.read('%s/jumpserver.conf' % base_dir)
|
||||
cf.read('%s/jumpserver.conf' % cur_dir)
|
||||
|
||||
db_host = cf.get('db', 'host')
|
||||
db_port = cf.getint('db', 'port')
|
||||
db_user = cf.get('db', 'user')
|
||||
db_password = cf.get('db', 'password')
|
||||
db_db = cf.get('db', 'db')
|
||||
log_dir = cf.get('jumpserver', 'log_dir')
|
||||
user_table = cf.get('jumpserver', 'user_table')
|
||||
assets_table = cf.get('jumpserver', 'assets_table')
|
||||
assets_user_table = cf.get('jumpserver', 'assets_user_table')
|
||||
log_dir = os.path.join(cur_dir, 'logs')
|
||||
key = cf.get('jumpserver', 'key')
|
||||
|
||||
|
||||
@@ -61,7 +68,10 @@ class PyCrypt(object):
|
||||
def sigwinch_passthrough(sig, data):
|
||||
"""This function use to set the window size of the terminal!"""
|
||||
winsize = getwinsize()
|
||||
foo.setwinsize(winsize[0], winsize[1])
|
||||
try:
|
||||
foo.setwinsize(winsize[0], winsize[1])
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def getwinsize():
|
||||
@@ -69,24 +79,12 @@ def getwinsize():
|
||||
if 'TIOCGWINSZ' in dir(termios):
|
||||
TIOCGWINSZ = termios.TIOCGWINSZ
|
||||
else:
|
||||
TIOCGWINSZ = 1074295912L # Assume
|
||||
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 connect_db(user, passwd, db, host='127.0.0.1', port=3306):
|
||||
"""This function connect db and return db and cursor"""
|
||||
db = MySQLdb.connect(host=host,
|
||||
port=port,
|
||||
user=user,
|
||||
passwd=passwd,
|
||||
db=db,
|
||||
charset='utf8')
|
||||
cursor = db.cursor()
|
||||
return db, cursor
|
||||
|
||||
|
||||
def run_cmd(cmd):
|
||||
"""run command and return stdout"""
|
||||
pipe = subprocess.Popen(cmd,
|
||||
@@ -105,79 +103,75 @@ def run_cmd(cmd):
|
||||
|
||||
def connect(host, port, user, password):
|
||||
"""Use pexpect module to connect other server."""
|
||||
if not os.path.isdir(log_dir):
|
||||
os.mkdir(log_dir)
|
||||
logfile = open("%s/%s_%s_%s" % (log_dir, host, time.strftime('%Y%m%d'), user), 'a')
|
||||
logfile.write('\n\n%s\n\n' % time.strftime('%Y%m%d_%H%M%S'))
|
||||
cmd = 'ssh -p %s %s@%s' % (port, user, host)
|
||||
global foo
|
||||
foo = pexpect.spawn('/bin/bash', ['-c', cmd])
|
||||
foo.logfile = logfile
|
||||
while True:
|
||||
index = foo.expect(['continue',
|
||||
'assword',
|
||||
pexpect.EOF,
|
||||
pexpect.TIMEOUT], timeout=3)
|
||||
if index == 0:
|
||||
foo.sendline('yes')
|
||||
continue
|
||||
elif index == 1:
|
||||
foo.sendline(password)
|
||||
log_date_dir = '%s/%s' % (log_dir, time.strftime('%Y%m%d'))
|
||||
if not os.path.isdir(log_date_dir):
|
||||
os.mkdir(log_date_dir)
|
||||
os.chmod(log_date_dir, 0777)
|
||||
structtime_start = time.localtime()
|
||||
datetime_start = time.strftime('%Y%m%d%H%M%S', structtime_start)
|
||||
logtime_start = time.strftime('%Y/%m/%d %H:%M:%S', structtime_start)
|
||||
timestamp_start = int(time.mktime(structtime_start))
|
||||
logfile_name = "%s/%s_%s_%s" % (log_date_dir, host, user, datetime_start)
|
||||
|
||||
index = foo.expect(['assword',
|
||||
'.*',
|
||||
pexpect.EOF,
|
||||
pexpect.TIMEOUT], timeout=3)
|
||||
if index == 1:
|
||||
signal.signal(signal.SIGWINCH, sigwinch_passthrough)
|
||||
size = getwinsize()
|
||||
foo.setwinsize(size[0], size[1])
|
||||
print "\033[32;1mLogin %s success!\033[0m" % host
|
||||
foo.interact()
|
||||
break
|
||||
elif index == 0:
|
||||
print "Password error."
|
||||
break
|
||||
else:
|
||||
print "Login failed, please contact system administrator!"
|
||||
break
|
||||
foo.terminate(force=True)
|
||||
try:
|
||||
global foo
|
||||
foo = pxssh.pxssh()
|
||||
foo.login(host, user, password, port=port, auto_prompt_reset=False)
|
||||
log = Logs(user=user, host=host, logfile=logfile_name, start_time=timestamp_start, ppid=os.getpid()) # 日志信息记录到数据库
|
||||
log.save()
|
||||
pid = Pid(ppid=os.getpid(), cpid=foo.pid, start_time=timestamp_start, logid=log.id)
|
||||
pid.save()
|
||||
|
||||
logfile = open(logfile_name, 'a') # 记录日志文件
|
||||
logfile.write('\nDateTime:%s' % logtime_start)
|
||||
foo.logfile = logfile
|
||||
foo.sendline('')
|
||||
signal.signal(signal.SIGWINCH, sigwinch_passthrough)
|
||||
size = getwinsize()
|
||||
foo.setwinsize(size[0], size[1])
|
||||
foo.interact(escape_character=chr(28)) # 进入交互模式
|
||||
logfile.write('\nEndTime: %s' % time.strftime('%Y/%m/%d %H:%M:%S'))
|
||||
log.finish = 1
|
||||
log.end_time = int(time.time())
|
||||
log.save()
|
||||
|
||||
except pxssh.ExceptionPxssh as e:
|
||||
print('登录失败: %s' % e)
|
||||
except pexpect.EOF:
|
||||
print('登录失败: Host refuse')
|
||||
except KeyboardInterrupt:
|
||||
foo.logout()
|
||||
log.finish = 1
|
||||
log.end_time = int(time.time())
|
||||
log.save()
|
||||
|
||||
|
||||
def ip_all_select(username):
|
||||
"""select all the server of the user can control."""
|
||||
ip_all = []
|
||||
ip_all_dict = {}
|
||||
db, cursor = connect_db(db_user, db_password, db_db, db_host, db_port)
|
||||
cursor.execute('select t2.ip, t2.comment from %s t1, %s t2, %s t3 where t1.username="%s" and t1.id=t3.uid_id and t2.id = t3.aid_id;' %
|
||||
(user_table, assets_table, assets_user_table, username))
|
||||
ip_all_record = cursor.fetchall()
|
||||
if ip_all_record:
|
||||
for record in ip_all_record:
|
||||
ip_all.append(record[0])
|
||||
ip_all_dict[record[0]] = record[1]
|
||||
db.close()
|
||||
try:
|
||||
user = User.objects.get(username=username)
|
||||
except:
|
||||
return (['error'], {'error':"Don't Use Root To Do That or User isn't Exist."})
|
||||
all_assets_user = user.assetsuser_set.all()
|
||||
for assets_user in all_assets_user:
|
||||
ip_all.append(assets_user.aid.ip)
|
||||
ip_all_dict[assets_user.aid.ip] = assets_user.aid.comment
|
||||
|
||||
return ip_all, ip_all_dict
|
||||
|
||||
|
||||
def sth_select(username='', ip=''):
|
||||
"""if username: return password elif ip return port"""
|
||||
db, cursor = connect_db(db_user, db_password, db_db, db_host, db_port)
|
||||
if username:
|
||||
cursor.execute('select password from %s where username="%s"' % (user_table, username))
|
||||
try:
|
||||
password = cursor.fetchone()[0]
|
||||
except IndexError:
|
||||
password = ''
|
||||
db.close()
|
||||
return password
|
||||
user = User.objects.get(username=username)
|
||||
ldap_password = user.ldap_password
|
||||
return ldap_password
|
||||
|
||||
if ip:
|
||||
cursor.execute('select port from %s where ip="%s"' % (assets_table, ip))
|
||||
try:
|
||||
port = int(cursor.fetchone()[0])
|
||||
except IndexError:
|
||||
port = 22
|
||||
db.close()
|
||||
asset = Assets.objects.get(ip=ip)
|
||||
port = asset.port
|
||||
return port
|
||||
return None
|
||||
|
||||
@@ -247,31 +241,45 @@ def exec_cmd_servers(username):
|
||||
ip_all, ip_all_dict = ip_all_select(username)
|
||||
no_perm = set(hosts)-set(ip_all)
|
||||
if no_perm:
|
||||
print "You have no permission on %s." % list(no_perm)
|
||||
print "You have NO PERMISSION on %s..." % list(no_perm)
|
||||
continue
|
||||
print '\nInput the \033[32mCommand\033[0m , The command will be Execute on servers, q/Q to quit.\n'
|
||||
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))
|
||||
for host in hosts:
|
||||
remote_exec_cmd(host, username, cmd)
|
||||
|
||||
|
||||
def connect_one(username, option):
|
||||
ip = option.strip()
|
||||
ip_input = option.strip()
|
||||
ip_all, ip_all_dict = ip_all_select(username)
|
||||
ip_matched = match_ip(ip_all, ip)
|
||||
ip_matched = match_ip(ip_all, ip_input)
|
||||
ip_len = len(ip_matched)
|
||||
if ip_len == 1:
|
||||
ip = ip_matched[0]
|
||||
password = jm.decrypt(sth_select(username=username))
|
||||
port = sth_select(ip=ip)
|
||||
print "Connecting %s ..." % ip
|
||||
connect(ip, port, username, password)
|
||||
elif ip_len > 1:
|
||||
for ip in ip_matched:
|
||||
print ip
|
||||
ip = ''
|
||||
if ip_len >= 1:
|
||||
if ip_len == 1:
|
||||
ip = ip_matched[0]
|
||||
else:
|
||||
if ip_input in ip_matched:
|
||||
ip = ip_input
|
||||
else:
|
||||
for one_ip in ip_matched:
|
||||
print one_ip
|
||||
if ip:
|
||||
password = jm.decrypt(sth_select(username=username))
|
||||
port = sth_select(ip=ip)
|
||||
print "Connecting %s ..." % ip
|
||||
connect(ip, port, username, password)
|
||||
else:
|
||||
print '\033[31mNo permision .\033[0m'
|
||||
|
||||
@@ -282,7 +290,11 @@ if __name__ == '__main__':
|
||||
print_prompt()
|
||||
try:
|
||||
while True:
|
||||
option = raw_input("\033[1;32mOpt or IP>:\033[0m ")
|
||||
try:
|
||||
option = raw_input("\033[1;32mOpt or IP>:\033[0m ")
|
||||
except EOFError:
|
||||
print
|
||||
continue
|
||||
if option in ['P', 'p']:
|
||||
print_your_server(username)
|
||||
continue
|
||||
@@ -292,7 +304,7 @@ if __name__ == '__main__':
|
||||
sys.exit()
|
||||
else:
|
||||
connect_one(username, option)
|
||||
except (BaseException, Exception):
|
||||
#except IndexError:
|
||||
#except (BaseException, Exception):
|
||||
except IndexError:
|
||||
print "Exit."
|
||||
sys.exit()
|
||||
18
runserver
Executable file
18
runserver
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
manage_file="./webroot/AutoSa/manage.py"
|
||||
log_handler_file="./webroot/AutoSa/log_handler.py"
|
||||
websocket_file="./webroot/AutoSa/websocket/index.js"
|
||||
|
||||
which node &> /dev/null
|
||||
if [ $? != '0' ];then
|
||||
echo "Please define the node.js binary file 'node' in the PATH."
|
||||
exit
|
||||
fi
|
||||
node $websocket_file &
|
||||
if [ -f $manage_file -a -e $manage_file ] && [ -f $log_handler_file -a -e $log_handler_file ];then
|
||||
$manage_file runserver 0.0.0.0:80 &> logs/access.log &
|
||||
$log_handler_file &> logs/handler.log &
|
||||
else
|
||||
echo "manage.py or log_handler.py isn't exist or executable."
|
||||
fi
|
||||
4
jumpserver.sh → scripts/jumpserver.sh
Executable file → Normal file
4
jumpserver.sh → scripts/jumpserver.sh
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $USER = 'admin' ] || [ $USER == 'root' ];then
|
||||
if [ $USER == 'admin' ] || [ $USER == 'root' ];then
|
||||
echo ""
|
||||
else
|
||||
python /opt/jumpserver/jumpserver.py
|
||||
@@ -10,4 +10,4 @@ else
|
||||
exit 3
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
8
scripts/requirements.txt
Normal file
8
scripts/requirements.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
pexpect==3.3
|
||||
sphinx-me==0.3
|
||||
django==1.7.1
|
||||
python-ldap==2.4.18
|
||||
paramiko==1.15.1
|
||||
pycrypto==2.6.1
|
||||
ecdsa>=0.11
|
||||
MySQL-python==1.2.5
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
host=127.0.0.1
|
||||
ldapassword=VNLqNCjpNBIetEoCA2h3
|
||||
domain=dianping
|
||||
suffix=com
|
||||
#host2=172.16.2.74
|
||||
#host2_port=2001
|
||||
5
stopserver
Executable file
5
stopserver
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
pids=$(ps axu | grep -E '(manage.py|log_handler|index.js)' | grep -v 'grep' | awk '{ print $2 }')
|
||||
for pid in $pids;do
|
||||
kill -15 $pid
|
||||
done
|
||||
@@ -1,9 +0,0 @@
|
||||
dn: cn=guanghongwei,ou=Sudoers,dc=dianping,dc=com
|
||||
objectClass: top
|
||||
objectClass: sudoRole
|
||||
cn: guanghongwei
|
||||
sudoCommand: /bin/pwd
|
||||
sudoHost: ALL
|
||||
sudoOption: !authenticate
|
||||
sudoRunAsUser: ALL
|
||||
sudoUser: guanghongwei
|
||||
36
sudoadd.sh
36
sudoadd.sh
@@ -1,36 +0,0 @@
|
||||
#!/bin/bash
|
||||
username=$1
|
||||
password=$2
|
||||
|
||||
cwd (){
|
||||
dir=$0
|
||||
dirname $dir
|
||||
}
|
||||
|
||||
dir=$(cwd)
|
||||
. ${dir}/shell.conf
|
||||
|
||||
|
||||
sudo_file=${dir}/sudo.ldif
|
||||
user_sudo_file=${dir}/${username}.ldif
|
||||
|
||||
if [ -z $1 ];then
|
||||
echo
|
||||
echo "usage: ./sudoadd.sh username "
|
||||
echo
|
||||
exit 3
|
||||
fi
|
||||
|
||||
id ${username} &> /dev/null
|
||||
if [ $? != '0' ];then
|
||||
echo "$username is not exit!"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
sed -i "/guanghongwei/ s@dianping@$domain@g" ${sudo_file}
|
||||
sed -i "/guanghongwei/ s@com@$suffix@g" ${sudo_file}
|
||||
sed -e "s@guanghongwei@$username@g" ${sudo_file} > $user_sudo_file
|
||||
|
||||
|
||||
ldapadd -x -h ${host} -w ${ldapassword} -D "cn=admin,dc=$domain,dc=$suffix" -f $user_sudo_file
|
||||
rm -f $user_sudo_file
|
||||
18
sudodel.sh
18
sudodel.sh
@@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
username=$1
|
||||
password=$2
|
||||
|
||||
cwd (){
|
||||
dir=$0
|
||||
dirname $dir
|
||||
}
|
||||
dir=$(cwd)
|
||||
. ${dir}/shell.conf
|
||||
|
||||
id $username &> /dev/null
|
||||
if [ $? == '0' ];then
|
||||
userdel -r $username
|
||||
else
|
||||
echo "$username is not exist."
|
||||
fi
|
||||
ldapdelete -x -h $host -D "cn=admin,dc=$domain,dc=$suffix" -w $ldapassword "cn=$username,ou=Sudoers,dc=$domain,dc=$suffix"
|
||||
38
useradd.sh
38
useradd.sh
@@ -1,38 +0,0 @@
|
||||
#!/bin/bash
|
||||
username=$1
|
||||
password=$2
|
||||
|
||||
cwd (){
|
||||
dir=$0
|
||||
dirname $dir
|
||||
}
|
||||
|
||||
dir=$(cwd)
|
||||
. ${dir}/shell.conf
|
||||
|
||||
if [ -z $1 ] || [ -z $2 ];then
|
||||
echo
|
||||
echo "usage: ./useradd.sh username password"
|
||||
echo
|
||||
exit 3
|
||||
fi
|
||||
|
||||
id $username &> /dev/null
|
||||
if [ $? != '0' ];then
|
||||
useradd $username
|
||||
#ssh -p $host2_port $host2 "useradd $username"
|
||||
echo $password | passwd --stdin $username
|
||||
else
|
||||
echo "$username have been exits."
|
||||
exit 5
|
||||
fi
|
||||
|
||||
cd /usr/share/migrationtools/
|
||||
./migrate_passwd.pl /etc/passwd > /tmp/passwd.ldif
|
||||
./migrate_group.pl /etc/group > /tmp/group.ldif
|
||||
|
||||
grep -A15 "dn: uid=$username,ou=People,dc=$domain,dc=$suffix" /tmp/passwd.ldif > /tmp/user.ldif
|
||||
grep -A6 "dn: cn=$username,ou=Group,dc=$domain,dc=$suffix" /tmp/group.ldif > /tmp/usergroup.ldif
|
||||
|
||||
ldapadd -x -h $host -w $ldapassword -D "cn=admin,dc=$domain,dc=$suffix" -f /tmp/user.ldif
|
||||
ldapadd -x -h $host -w $ldapassword -D "cn=admin,dc=$domain,dc=$suffix" -f /tmp/usergroup.ldif
|
||||
21
userdel.sh
21
userdel.sh
@@ -1,21 +0,0 @@
|
||||
#!/bin/bash
|
||||
username=$1
|
||||
password=$2
|
||||
|
||||
cwd (){
|
||||
dir=$0
|
||||
dirname $dir
|
||||
}
|
||||
|
||||
dir=$(cwd)
|
||||
. ${dir}/shell.conf
|
||||
|
||||
id $username &> /dev/null
|
||||
if [ $? == '0' ];then
|
||||
userdel -r $username
|
||||
#ssh -p $host2_port $host2 "userdel -r $username"
|
||||
else
|
||||
echo "$username is not exist."
|
||||
fi
|
||||
ldapdelete -x -h $host -D "cn=admin,dc=$domain,dc=$suffix" -w $ldapassword "uid=$username,ou=People,dc=$domain,dc=$suffix"
|
||||
ldapdelete -x -h $host -D "cn=admin,dc=$domain,dc=$suffix" -w $ldapassword "cn=$username,ou=Group,dc=$domain,dc=$suffix"
|
||||
Binary file not shown.
@@ -2,10 +2,18 @@ from django.db import models
|
||||
from UserManage.models import User
|
||||
|
||||
|
||||
class IDC(models.Model):
|
||||
name = models.CharField(max_length=20)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Assets(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
ip = models.CharField(max_length=20)
|
||||
port = models.IntegerField(max_length=5)
|
||||
idc = models.ForeignKey(IDC)
|
||||
comment = models.CharField(max_length=100, blank=True, null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
@@ -14,4 +22,6 @@ class Assets(models.Model):
|
||||
|
||||
class AssetsUser(models.Model):
|
||||
uid = models.ForeignKey(User)
|
||||
aid = models.ForeignKey(Assets)
|
||||
aid = models.ForeignKey(Assets)
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -12,16 +12,16 @@ https://docs.djangoproject.com/en/1.6/ref/settings/
|
||||
import os
|
||||
import ConfigParser
|
||||
|
||||
base_dir = "/opt/jumpserver/"
|
||||
cf = ConfigParser.ConfigParser()
|
||||
cf.read('%s/jumpserver.conf' % base_dir)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||
CONF_DIR = os.path.dirname(os.path.dirname(BASE_DIR))
|
||||
CF = ConfigParser.ConfigParser()
|
||||
CF.read('%s/jumpserver.conf' % CONF_DIR)
|
||||
|
||||
db_host = cf.get('db', 'host')
|
||||
db_port = cf.getint('db', 'port')
|
||||
db_user = cf.get('db', 'user')
|
||||
db_password = cf.get('db', 'password')
|
||||
db_db = cf.get('db', 'db')
|
||||
DB_HOST = CF.get('db', 'host')
|
||||
DB_PORT = CF.getint('db', 'port')
|
||||
DB_USER = CF.get('db', 'user')
|
||||
DB_PASSWORD = CF.get('db', 'password')
|
||||
DB_DB = CF.get('db', 'db')
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/
|
||||
@@ -48,6 +48,7 @@ INSTALLED_APPS = (
|
||||
'django.contrib.staticfiles',
|
||||
'UserManage',
|
||||
'Assets',
|
||||
'AutoSa',
|
||||
#'RunCommand',
|
||||
)
|
||||
|
||||
@@ -71,11 +72,11 @@ WSGI_APPLICATION = 'AutoSa.wsgi.application'
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME': db_db,
|
||||
'USER': db_user,
|
||||
'PASSWORD': db_password,
|
||||
'HOST': db_host,
|
||||
'PORT': db_port,
|
||||
'NAME': DB_DB,
|
||||
'USER': DB_USER,
|
||||
'PASSWORD': DB_PASSWORD,
|
||||
'HOST': DB_HOST,
|
||||
'PORT': DB_PORT,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
12
webroot/AutoSa/AutoSa/templatetags/mytags.py
Normal file
12
webroot/AutoSa/AutoSa/templatetags/mytags.py
Normal file
@@ -0,0 +1,12 @@
|
||||
import time
|
||||
from django import template
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter(name='stamp2str')
|
||||
def stamp2str(value):
|
||||
try:
|
||||
return time.strftime('%Y/%m/%d %H:%M:%S', time.localtime(value))
|
||||
except AttributeError:
|
||||
return '0000/00/00 00:00:00'
|
||||
@@ -10,11 +10,21 @@ urlpatterns = patterns('',
|
||||
# url(r'^blog/', include('blog.urls')),
|
||||
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
(r'^install/', views.install),
|
||||
(r'^$', views.index),
|
||||
(r'^login/$', views.login),
|
||||
(r'^logout/$', views.logout),
|
||||
(r'^showUser/$', views.showUser),
|
||||
(r'^addUser/$', views.addUser),
|
||||
(r'^chgUser/$', views.chgUser),
|
||||
(r'^showGroup/$', views.showGroup),
|
||||
(r'^addGroup/$', views.addGroup),
|
||||
(r'^chgGroup/$', views.chgGroup),
|
||||
(r'^showIDC/$', views.showIDC),
|
||||
(r'^addIDC/$', views.addIDC),
|
||||
(r'^chgIDC/$', views.chgIDC),
|
||||
(r'^showSudo/$', views.showSudo),
|
||||
(r'^chgSudo/$', views.chgSudo),
|
||||
(r'^showAssets/$', views.showAssets),
|
||||
(r'^addAssets/$', views.addAssets),
|
||||
(r'^showPerm/$', views.showPerm),
|
||||
@@ -22,4 +32,9 @@ urlpatterns = patterns('',
|
||||
(r'^downKey/$', views.downKey),
|
||||
(r'^chgPass/$', views.chgPass),
|
||||
(r'^chgKey/$', views.chgKey),
|
||||
(r'^upFile/$', views.upFile),
|
||||
(r'^downFile/$', views.downFile),
|
||||
(r'^logView/$', views.logView),
|
||||
(r'^logHistory/$', views.logHistory),
|
||||
(r'^killSession/$', views.killSession),
|
||||
)
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@@ -1,3 +0,0 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
@@ -1,12 +0,0 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Server(models.Model):
|
||||
ip = models.CharField(max_length=16)
|
||||
username = models.CharField(max_length=20)
|
||||
password = models.CharField(max_length=30)
|
||||
port = models.IntegerField(max_length=5)
|
||||
sudo = models.BooleanField()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.ip
|
||||
@@ -1,2 +0,0 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
Binary file not shown.
48
webroot/AutoSa/UserManage/forms.py
Normal file
48
webroot/AutoSa/UserManage/forms.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# coding: utf-8
|
||||
|
||||
from django import forms
|
||||
from UserManage.models import Group
|
||||
|
||||
|
||||
class GroupAddForm(forms.Form):
|
||||
name = forms.CharField(max_length=30)
|
||||
|
||||
|
||||
class UserAddForm(forms.Form):
|
||||
username = forms.CharField(max_length=30,
|
||||
widget=forms.TextInput(
|
||||
attrs={'class': 'form-control', 'placeholder': '用户名'}))
|
||||
password = forms.CharField(max_length=30,
|
||||
widget=forms.PasswordInput(
|
||||
attrs={'class': 'form-control', 'placeholder': '密码'}))
|
||||
password_again = forms.CharField(max_length=30,
|
||||
widget=forms.PasswordInput(
|
||||
attrs={'class': 'form-control', 'placeholder': '确认密码'}))
|
||||
key_pass = forms.CharField(max_length=30, min_length=6,
|
||||
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '密钥密码'}))
|
||||
key_pass_again = forms.CharField(max_length=30,
|
||||
widget=forms.PasswordInput(
|
||||
attrs={'class': 'form-control', 'placeholder': '确认密码'}))
|
||||
name = forms.CharField(max_length=30,
|
||||
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '姓名'}))
|
||||
group = forms.ModelMultipleChoiceField(queryset=Group.objects.all(),
|
||||
widget=forms.SelectMultiple(attrs={'class': 'form-control'}))
|
||||
is_admin = forms.BooleanField(required=False)
|
||||
is_superuser = forms.BooleanField(required=False)
|
||||
|
||||
def clean_password_again(self):
|
||||
password = self.cleaned_data['password']
|
||||
password_again = self.cleaned_data['password_again']
|
||||
|
||||
if password != password_again:
|
||||
raise forms.ValidationError(u'密码二次输入不一致. ')
|
||||
return password_again
|
||||
|
||||
def clean_key_pass_again(self):
|
||||
key_pass = self.data['key_pass']
|
||||
key_pass_again = self.data['key_pass_again']
|
||||
if key_pass != key_pass_again:
|
||||
raise forms.ValidationError(u'密码二次输入不一致. ')
|
||||
if len(key_pass) < 6:
|
||||
raise forms.ValidationError(u'密码二次输入不一致. ')
|
||||
return key_pass_again
|
||||
@@ -1,11 +1,48 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class User(models.Model):
|
||||
username = models.CharField(max_length=50)
|
||||
password = models.CharField(max_length=100)
|
||||
name = models.CharField(max_length=50)
|
||||
email = models.EmailField(max_length=50)
|
||||
class Group(models.Model):
|
||||
name = models.CharField(max_length=50, unique=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.username
|
||||
return self.name
|
||||
|
||||
|
||||
class User(models.Model):
|
||||
username = models.CharField(max_length=50, unique=True)
|
||||
password = models.CharField(max_length=100)
|
||||
key_pass = models.CharField(max_length=100)
|
||||
name = models.CharField(max_length=50)
|
||||
group = models.ManyToManyField(Group)
|
||||
is_admin = models.BooleanField(default=False)
|
||||
is_superuser = models.BooleanField(default=False)
|
||||
ldap_password = models.CharField(max_length=100, null=False)
|
||||
email = models.EmailField(max_length=50, null=True, blank=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.username
|
||||
|
||||
|
||||
class Logs(models.Model):
|
||||
user = models.CharField(max_length=50)
|
||||
host = models.CharField(max_length=20)
|
||||
logfile = models.CharField(max_length=1000)
|
||||
finish = models.SmallIntegerField(max_length=4, default=0)
|
||||
ppid = models.IntegerField()
|
||||
start_time = models.IntegerField()
|
||||
end_time = models.IntegerField(default=0)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.logfile
|
||||
|
||||
|
||||
class Pid(models.Model):
|
||||
"""
|
||||
ppid : parent pid
|
||||
cpid: child pid
|
||||
"""
|
||||
ppid = models.IntegerField()
|
||||
cpid = models.IntegerField()
|
||||
logid = models.IntegerField()
|
||||
start_time = models.IntegerField()
|
||||
|
||||
|
||||
Binary file not shown.
96
webroot/AutoSa/log_handler.py
Executable file
96
webroot/AutoSa/log_handler.py
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/python
|
||||
#coding: utf-8
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
cur_dir = os.path.dirname(__file__)
|
||||
sys.path.append('%s/webroot/AutoSa/' % cur_dir)
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'AutoSa.settings'
|
||||
|
||||
import django
|
||||
django.setup()
|
||||
from UserManage.models import Logs, Pid
|
||||
|
||||
|
||||
def log_hanler(logid):
|
||||
log = Logs.objects.filter(id=logid)
|
||||
if log:
|
||||
log = log[0]
|
||||
filename = log.logfile
|
||||
if os.path.isfile(filename):
|
||||
ret1 = os.system('cat %s | grep "DateTime" > %s.his' % (filename, filename))
|
||||
ret2 = os.system('cat %s | grep "\[.*@.*\][\$\#]" >> %s.his' % (filename, filename))
|
||||
ret3 = os.system('cat %s | grep "EndTime" >> %s.his' % (filename, filename))
|
||||
if (ret1 + ret2 + ret3) == 0:
|
||||
print 'Handler %s ok.' % filename
|
||||
|
||||
|
||||
def set_finish(id):
|
||||
logs = Logs.objects.filter(id=id, finish=0)
|
||||
if logs:
|
||||
structtime_start = time.localtime()
|
||||
timestamp_end = int(time.mktime(structtime_start))
|
||||
log = logs[0]
|
||||
log.finish = 1
|
||||
log.end_time = timestamp_end
|
||||
log.save()
|
||||
|
||||
|
||||
def kill_pid(pid):
|
||||
try:
|
||||
os.kill(pid, 9)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def pid_exist(pid):
|
||||
pid_dir = "/proc/%s" % pid
|
||||
if os.path.isdir(pid_dir):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def del_pid(pid_id):
|
||||
pid = Pid.objects.filter(id=pid_id)
|
||||
if pid:
|
||||
pid[0].delete()
|
||||
|
||||
|
||||
def get_pids():
|
||||
pids = []
|
||||
pids_obj = Pid.objects.all()
|
||||
for pid_obj in pids_obj:
|
||||
pids.append((pid_obj.id, pid_obj.ppid, pid_obj.cpid, pid_obj.logid, pid_obj.start_time))
|
||||
return pids
|
||||
|
||||
|
||||
def run():
|
||||
for pid_id, ppid, cpid, logid, start_time in get_pids():
|
||||
if pid_exist(cpid):
|
||||
if pid_exist(ppid):
|
||||
structtime_start = time.localtime()
|
||||
timestamp_end = int(time.mktime(structtime_start))
|
||||
if timestamp_end - start_time > 7200:
|
||||
kill_pid(ppid)
|
||||
kill_pid(cpid)
|
||||
del_pid(pid_id)
|
||||
set_finish(logid)
|
||||
log_hanler(logid)
|
||||
else:
|
||||
kill_pid(cpid)
|
||||
del_pid(pid_id)
|
||||
set_finish(logid)
|
||||
log_hanler(logid)
|
||||
else:
|
||||
del_pid(pid_id)
|
||||
set_finish(logid)
|
||||
log_hanler(logid)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
while True:
|
||||
run()
|
||||
time.sleep(0.5)
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
./manage.py runserver 0.0.0.0:80
|
||||
120
webroot/AutoSa/static/css/bootstrap-dialog.css
vendored
Normal file
120
webroot/AutoSa/static/css/bootstrap-dialog.css
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
.bootstrap-dialog {
|
||||
|
||||
}
|
||||
.bootstrap-dialog .modal-header {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.bootstrap-dialog .bootstrap-dialog-title {
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
}
|
||||
.bootstrap-dialog.type-default .bootstrap-dialog-title {
|
||||
color: #333;
|
||||
}
|
||||
.bootstrap-dialog.size-normal .bootstrap-dialog-title {
|
||||
font-size: 16px;
|
||||
}
|
||||
.bootstrap-dialog.size-large .bootstrap-dialog-title {
|
||||
font-size: 24px;
|
||||
}
|
||||
.bootstrap-dialog .bootstrap-dialog-close-button {
|
||||
float: right;
|
||||
filter:alpha(opacity=90);
|
||||
-moz-opacity:0.9;
|
||||
-khtml-opacity: 0.9;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.bootstrap-dialog.size-normal .bootstrap-dialog-close-button {
|
||||
font-size: 20px;
|
||||
}
|
||||
.bootstrap-dialog.size-large .bootstrap-dialog-close-button {
|
||||
font-size: 30px;
|
||||
}
|
||||
.bootstrap-dialog .bootstrap-dialog-close-button:hover {
|
||||
cursor: pointer;
|
||||
filter: alpha(opacity=100);
|
||||
-moz-opacity: 1;
|
||||
-khtml-opacity: 1;
|
||||
opacity: 1;
|
||||
}
|
||||
.bootstrap-dialog.size-normal .bootstrap-dialog-message {
|
||||
font-size: 14px;
|
||||
}
|
||||
.bootstrap-dialog.size-large .bootstrap-dialog-message {
|
||||
font-size: 18px;
|
||||
}
|
||||
.bootstrap-dialog.type-default .modal-header {
|
||||
background-color: #fff;
|
||||
}
|
||||
.bootstrap-dialog.type-info .modal-header {
|
||||
background-color: #5bc0de;
|
||||
}
|
||||
.bootstrap-dialog.type-primary .modal-header {
|
||||
background-color: #428bca;
|
||||
}
|
||||
.bootstrap-dialog.type-success .modal-header {
|
||||
background-color: #5cb85c;
|
||||
}
|
||||
.bootstrap-dialog.type-warning .modal-header {
|
||||
background-color: #f0ad4e;
|
||||
}
|
||||
.bootstrap-dialog.type-danger .modal-header {
|
||||
background-color: #d9534f;
|
||||
}
|
||||
.bootstrap-dialog .bootstrap-dialog-button-icon {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Icon animation
|
||||
* Copied from font-awesome: http://fontawesome.io/
|
||||
**/
|
||||
.icon-spin {
|
||||
display: inline-block;
|
||||
-moz-animation: spin 2s infinite linear;
|
||||
-o-animation: spin 2s infinite linear;
|
||||
-webkit-animation: spin 2s infinite linear;
|
||||
animation: spin 2s infinite linear;
|
||||
}
|
||||
@-moz-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-o-keyframes spin {
|
||||
0% {
|
||||
-o-transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-o-transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-ms-keyframes spin {
|
||||
0% {
|
||||
-ms-transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-ms-transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
/** End of icon animation **/
|
||||
1089
webroot/AutoSa/static/js/bootstrap-dialog.js
vendored
Normal file
1089
webroot/AutoSa/static/js/bootstrap-dialog.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -12,4 +12,6 @@ function selectAll(){
|
||||
checklist[j].checked = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -25,10 +25,25 @@
|
||||
<input type="text" class="form-control" id="port" name="port" placeholder="Port">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="idc" class="col-sm-2 control-label">IDC<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<select name="idc" id="idc" class="form-control">
|
||||
{% for idc in idcs %}
|
||||
<option value="{{ idc.id }}">{{ idc.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<a href="/addIDC/">添加IDC</a>
|
||||
<a href="/showIDC/">删除IDC</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="comment" class="col-sm-2 control-label">备注<span style="color: red"></span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="comment" name="comment" placeholder="备注">
|
||||
<input type="text" class="form-control" id="comment" name="comment" placeholder="备注(最好是英文)">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
30
webroot/AutoSa/templates/addGroup.html
Normal file
30
webroot/AutoSa/templates/addGroup.html
Normal file
@@ -0,0 +1,30 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<form class="form-horizontal" role="form" method="post" action="" >
|
||||
<fieldset >
|
||||
<legend>添加属组</legend>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success">
|
||||
{{ msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="name" class="col-sm-2 control-label">属组<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="name" name="name" placeholder="属组">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-4">
|
||||
<button class="btn btn-primary">添加</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock %}
|
||||
31
webroot/AutoSa/templates/addIDC.html
Normal file
31
webroot/AutoSa/templates/addIDC.html
Normal file
@@ -0,0 +1,31 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<form class="form-horizontal" role="form" method="post" action="" >
|
||||
<fieldset >
|
||||
<legend>添加IDC</legend>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success">
|
||||
{{ msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="name" class="col-sm-2 control-label">IDC<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="name" name="name" placeholder="IDC">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-4">
|
||||
<button class="btn btn-primary">添加</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -1,41 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<form class="form-horizontal" role="form" method="post" action="" >
|
||||
<fieldset >
|
||||
<legend>添加OpenVPN用户</legend>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success">
|
||||
{{ msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="username" name="username" placeholder="用户名">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password" class="col-sm-2 control-label">密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-4">
|
||||
<button class="btn btn-primary">确认添加</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -26,7 +26,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<button class="btn btn-primary">删除</button></td>
|
||||
<button class="btn btn-success">删除</button></td>
|
||||
</form>
|
||||
|
||||
{% endblock %} %}
|
||||
@@ -1,56 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
|
||||
<form class="form-horizontal" role="form" method="post" action="" >
|
||||
<fieldset >
|
||||
<legend>添加执行命令主机</legend>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success">
|
||||
{{ msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="pub_ip" class="col-sm-2 control-label">IP<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="pub_ip" name="pub_ip" placeholder="IP">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="username" class="col-sm-2 control-label">账号<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="username" name="username" placeholder="账号">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password" class="col-sm-2 control-label">密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="port" class="col-sm-2 control-label">端口号<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="port" name="port" placeholder="端口号">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="sudo" class="col-sm-2 control-label">sudo<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="checkbox" style="margin-top: 12px;" id="sudo" name="sudo">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-4">
|
||||
<button class="btn btn-sm btn-primary">添加</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@@ -8,51 +8,85 @@
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger">
|
||||
Please correct the error{{ form.errors|pluralize }} below.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if msg %}
|
||||
<div class="alert alert-success">
|
||||
{{ msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
|
||||
{{ form.username.errors }}
|
||||
<label for="id_username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="username" name="username" placeholder="用户名">
|
||||
{{ form.username }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password" class="col-sm-2 control-label">密码<span style="color: red"> *</span></label>
|
||||
{{ form.password.errors }}
|
||||
<label for="id_password" class="col-sm-2 control-label">密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
|
||||
{{ form.password }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
|
||||
{{ form.password_again.errors }}
|
||||
<label for="id_password_again" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
|
||||
{{ form.password_again }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="keypass" class="col-sm-2 control-label">Key密码<span style="color: red"> *</span></label>
|
||||
{{ form.key_pass.errors }}
|
||||
<label for="id_keypass" class="col-sm-2 control-label">密钥密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="keypass" name="keypass" placeholder="Key密码">
|
||||
{{ form.key_pass }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="keypass_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
|
||||
{{ form.key_pass_again.errors }}
|
||||
<label for="id_keypass_again" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="keypass_confirm" name="keypass_confirm" placeholder="确认密码">
|
||||
{{ form.key_pass_again }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name" class="col-sm-2 control-label">姓名<span style="color: red"> *</span></label>
|
||||
{{ form.name.errors }}
|
||||
<label for="id_name" class="col-sm-2 control-label">姓名<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="name" name='name' placeholder="姓名">
|
||||
{{ form.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email" class="col-sm-2 control-label">E-mail</label>
|
||||
{{ form.group.errors }}
|
||||
<label for="id_group" class="col-sm-2 control-label">属组</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="email" class="form-control" id="email" name="email" placeholder="用户名">
|
||||
{{ form.group }}
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<a href="/addGroup/">添加属组</a>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<a href="/showGroup/">删除属组</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
{{ form.is_admin.errors }}
|
||||
<label for="id_is_admin" class="col-sm-2 control-label">组admin</label>
|
||||
<div class="col-sm-4">
|
||||
{{ form.is_admin }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
{{ form.is_superuser.errors }}
|
||||
<label for="id_is_superuser" class="col-sm-2 control-label">超级admin</label>
|
||||
<div class="col-sm-4">
|
||||
{{ form.is_superuser }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
@@ -1,34 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<h2 class="text-center">修改主机信息</h2>
|
||||
<form role="form" action="" method="post">
|
||||
<div class="form-group has-success">
|
||||
<label class="control-label" for="inputSuccess">编号</label>
|
||||
<input type="text" class="form-control" id="inputSuccess" name="s_num" value='{{ post.s_num }}'>
|
||||
|
||||
<label class="control-label" for="inputSuccess">IP</label>
|
||||
<input type="text" class="form-control" id="inputSuccess" name="s_ip" value='{{ post.s_ip }}'>
|
||||
|
||||
<label class="control-label" for="inputSuccess">主机名</label>
|
||||
<input type="text" class="form-control" id="inputSuccess" name="s_hostname" value='{{ post.s_hostname }}'>
|
||||
|
||||
<label class="control-label" for="inputSuccess">CPU</label>
|
||||
<input type="text" class="form-control" id="inputSuccess" name="s_cpu" value='{{ post.s_cpu }}'>
|
||||
|
||||
<label class="control-label" for="inputSuccess">内存</label>
|
||||
<input type="text" class="form-control" id="inputSuccess" name="s_mem" value='{{ post.s_mem }}'>
|
||||
|
||||
<label class="control-label" for="inputSuccess">硬盘</label>
|
||||
<input type="text" class="form-control" id="inputSuccess" name="s_disk" value='{{ post.s_disk }}'>
|
||||
|
||||
<label class="control-label" for="inputSuccess">操作系统</label>
|
||||
<input type="text" class="form-control" id="inputSuccess" name="s_system" value='{{ post.s_system }}'>
|
||||
|
||||
<div class="form-group has-success">
|
||||
<label class="control-label" for="inputSuccess">内核版本</label>
|
||||
<input type="text" class="form-control" id="inputSuccess" name="s_kernel" value='{{ post.s_kernel }}'>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success col-sm-offset-5">提交更改</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -1,58 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div>
|
||||
<div style="float:left"><h2>主机列表</h2></div>
|
||||
<div style="float:right;margin-top:16pt"><a href="/assets/add/" target="_black" class="btn btn-info">添加 <i class="glyphicon glyphicon-plus-sign"></i></a></div>
|
||||
</div>
|
||||
<table class="table table-striped table-hover table-bordered" id="sample_editable_1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">编号</th>
|
||||
<th class="text-center">IP</th>
|
||||
<th class="text-center">主机名</th>
|
||||
<th class="text-center">cpu</th>
|
||||
<th class="text-center">内存</th>
|
||||
<th class="text-center">硬盘</th>
|
||||
<th class="text-center">操作系统</th>
|
||||
<th class="text-center">详情</th>
|
||||
<th class="text-center">编辑</th>
|
||||
<th class="text-center">删除</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for post in contacts.object_list %}
|
||||
<tr class="">
|
||||
<td class="text-center">{{ post.s_num }}</td>
|
||||
<td class="text-center">{{ post.s_ip }}</td>
|
||||
<td class="text-center">{{ post.s_hostname }}</td>
|
||||
<td class="text-center">{{ post.s_cpu }}</td>
|
||||
<td class="text-center">{{ post.s_mem }}</td>
|
||||
<td class="text-center">{{ post.s_disk }}</td>
|
||||
<td class="text-center">{{ post.s_system }}</td>
|
||||
<td class="text-center"><a href="/assets/show/{{ post.s_ip }}">详情</a></td>
|
||||
<td class="text-center"><a href="/assets/edit/{{ post.s_ip }}">编辑</a></td>
|
||||
<td class="text-center"><a href="/assets/delete/{{ post.s_ip }}">删除</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
<ul class="pagination">
|
||||
{% if contacts.has_previous %}
|
||||
<li><a href="?page={{ contacts.previous_page_number }}">«</a></li>
|
||||
{% endif %}
|
||||
|
||||
{% for page in p.page_range %}
|
||||
{% ifequal offset1 page %}
|
||||
<li class="active"><a href="?page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>
|
||||
{% else %}
|
||||
<li><a href="?page={{ page }}" title="第{{ page }}页">{{ page }}</a></li>
|
||||
{% endifequal %}
|
||||
{% endfor %}
|
||||
{% if contacts.has_next %}
|
||||
<li><a href="?page={{ contacts.next_page_number }}">»</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
||||
@@ -2,26 +2,31 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>运维管理系统</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="http://img.youlu.com/web/favicon.gif" />
|
||||
<title>Jumpserver</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5js"></script>
|
||||
<![endif]-->
|
||||
<link href="/static/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="/static/css/bootstrap-dialog.css" rel="stylesheet">
|
||||
<link href="/static/css/main.css" rel="stylesheet">
|
||||
|
||||
<script src="/static/js/main.js"></script>
|
||||
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
|
||||
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
<script src="/static/js/bootstrap-dialog.js"></script>
|
||||
|
||||
<script src="/static/js/main.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{% if not admin %}
|
||||
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
|
||||
<div class="navbar-header"> <a class="navbar-brand" href="#">运维管理系统</a> </div>
|
||||
<div class="navbar-header"> <a class="navbar-brand" href="#">Jumpserver</a> </div>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="{{ index }}"><a href="/">主页</a></li>
|
||||
@@ -47,18 +52,30 @@
|
||||
<div class="row>
|
||||
<!--Sidebar content-->
|
||||
<div class="sidebar-menu">
|
||||
<div class="menu-first" ><a href="#userMenu" data-toggle="collapse"><i class="glyphicon glyphicon-th"></i> 密码管理</a></div>
|
||||
<div class="menu-first" ><a href="#userMenu" data-toggle="collapse">
|
||||
<i class="glyphicon glyphicon-th"></i> 密码管理</a>
|
||||
</div>
|
||||
<ul id="userMenu" class="nav nav-list navbar-collapse.in menu-second">
|
||||
<li><a href="/chgPass/"><i class="glyphicon glyphicon-send"></i> 登陆密码</a></li>
|
||||
<li><a href="/chgKey/"><i class="glyphicon glyphicon-send"></i> 密钥密码</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="menu-first" ><a href="#fileMenu" data-toggle="collapse">
|
||||
<i class="glyphicon glyphicon-th"></i> 文件传输</a>
|
||||
</div>
|
||||
<ul id="fileMenu" class="nav nav-list navbar-collapse.in menu-second">
|
||||
<li><a href="/upFile/"><i class="glyphicon glyphicon-send"></i> 上传文件</a></li>
|
||||
<li><a href="/downFile/"><i class="glyphicon glyphicon-send"></i> 下载文件</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
|
||||
<div class="navbar-header"> <a class="navbar-brand" href="#">运维管理系统</a> </div>
|
||||
<div class="navbar-header"> <a class="navbar-brand" href="#">Jumpserver</a> </div>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="{{ index }}"><a href="/">主页</a></li>
|
||||
@@ -107,6 +124,16 @@
|
||||
<li><a href="/showPerm/"><i class="glyphicon glyphicon-send"></i> 查看权限</a></li>
|
||||
<li><a href="/addPerm/"><i class="glyphicon glyphicon-send"></i> 添加权限</a></li>
|
||||
</ul>
|
||||
<div class="menu-first" ><a href="#logMenu" data-toggle="collapse"><i class="glyphicon glyphicon-th"></i> 日志审计</a></div>
|
||||
<ul id="logMenu" class="nav nav-list navbar-collapse menu-second">
|
||||
<li><a href="/logView/"><i class="glyphicon glyphicon-send"></i> 查看日志</a></li>
|
||||
</ul>
|
||||
<div class="menu-first" ><a href="#fileMenu" data-toggle="collapse">
|
||||
<i class="glyphicon glyphicon-th"></i> 文件传输</a>
|
||||
</div>
|
||||
<ul id="fileMenu" class="nav nav-list navbar-collapse.in menu-second">
|
||||
<li><a href="/upFile/"><i class="glyphicon glyphicon-send"></i> 上传文件</a></li>
|
||||
<li><a href="/downFile/"><i class="glyphicon glyphicon-send"></i> 下载文件</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -119,6 +146,7 @@
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<form class="form-horizontal" role="form" method="post" action="" >
|
||||
<fieldset >
|
||||
<legend>添加PPTP用户</legend>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success">
|
||||
{{ msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="username" name="username" placeholder="用户名">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password" class="col-sm-2 control-label">密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-4">
|
||||
<button class="btn btn-primary">确认添加</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<form class="form-horizontal" role="form" method="post" action="/chgGroup/" >
|
||||
<fieldset >
|
||||
<legend>修改属组信息</legend>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if msg %}
|
||||
<div class="alert alert-success">
|
||||
{{ msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4">
|
||||
<input type="text" id="id" name="id" value="{{ group.id }}" hidden="hidden">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="oldname" class="col-sm-2 control-label">原来属组<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" id="oldname" name="oldname" class="form-control" value="{{ group.name }}" readOnly="readOnly">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name" class="col-sm-2 control-label">属组<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" id="name" name="name" class="form-control" placeholder="属组">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-4">
|
||||
<button class="btn btn-primary">修改</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -1,39 +1,39 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<form class="form-horizontal" role="form" method="post" action="" >
|
||||
<form class="form-horizontal" role="form" method="post" action="/chgGroup/" >
|
||||
<fieldset >
|
||||
<legend>修改OpenVPN登陆密码</legend>
|
||||
<legend>修改IDC信息</legend>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if msg %}
|
||||
<div class="alert alert-success">
|
||||
{{ msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="oldpass" class="col-sm-2 control-label">原来密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="oldpass" name="oldpass" placeholder="用户名">
|
||||
<input type="text" id="id" name="id" value="{{ idc.id }}" hidden="hidden">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password" class="col-sm-2 control-label">新密码<span style="color: red"> *</span></label>
|
||||
<label for="oldname" class="col-sm-2 control-label">原来IDC<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
|
||||
<input type="text" id="oldname" name="oldname" class="form-control" value="{{ idc.name }}" readOnly="readOnly">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
|
||||
<label for="name" class="col-sm-2 control-label">IDC<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
|
||||
<input type="text" id="name" name="name" class="form-control" placeholder="IDC">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-4">
|
||||
<button class="btn btn-primary">确认修改</button>
|
||||
<button class="btn btn-primary">修改</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
@@ -14,11 +14,19 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="oldpass" class="col-sm-2 control-label">原来的密码<span style="color: red"> *</span></label>
|
||||
<label for="username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="oldpass" name="oldpass" placeholder="用户名">
|
||||
<input type="text" class="form-control" id="username" name="username" placeholder="用户名" value="{{ username }}" readonly="readOnly">
|
||||
</div>
|
||||
</div>
|
||||
{% if is_self %}
|
||||
<div class="form-group">
|
||||
<label for="oldpass" class="col-sm-2 control-label">原来的密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="oldpass" name="oldpass" placeholder="原来密码">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="password" class="col-sm-2 control-label">新密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
@@ -26,9 +34,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
|
||||
<label for="password_again" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
|
||||
<input type="password" class="form-control" id="password_again" name="password_again" placeholder="确认密码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
@@ -14,11 +14,19 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="oldpass" class="col-sm-2 control-label">原来密码<span style="color: red"> *</span></label>
|
||||
<label for="username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="oldpass" name="oldpass" placeholder="用户名">
|
||||
<input type="text" class="form-control" id="username" name="username" placeholder="用户名" value="{{ username }}" readonly="readOnly">
|
||||
</div>
|
||||
</div>
|
||||
{% if is_self %}
|
||||
<div class="form-group">
|
||||
<label for="oldpass" class="col-sm-2 control-label">原来的密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="oldpass" name="oldpass" placeholder="原来密码">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="password" class="col-sm-2 control-label">新密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
@@ -26,14 +34,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
|
||||
<label for="password_again" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
|
||||
<input type="password" class="form-control" id="password_again" name="password_again" placeholder="确认密码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-4">
|
||||
<button class="btn btn-primary">修改</button>
|
||||
<button class="btn btn-success">确认修改</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<form class="form-horizontal" role="form" method="post" action="" >
|
||||
<fieldset >
|
||||
<legend>修改PPTP VPN密码</legend>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success">
|
||||
{{ msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="oldpass" class="col-sm-2 control-label">原来密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="oldpass" name="oldpass" placeholder="用户名">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password" class="col-sm-2 control-label">新密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="密码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password_confirm" class="col-sm-2 control-label">确认密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="password" class="form-control" id="password_confirm" name="password_confirm" placeholder="确认密码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-4">
|
||||
<button class="btn btn-primary">确认</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock %}
|
||||
64
webroot/AutoSa/templates/chgSudo.html
Normal file
64
webroot/AutoSa/templates/chgSudo.html
Normal file
@@ -0,0 +1,64 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<fieldset >
|
||||
<legend>{{ username }}--修改sudo</legend>
|
||||
<form class="form-horizontal" role="form" method="post" action="/chgSudo/" >
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="input-group">
|
||||
<input type="text" name="username" value="{{ username }}" hidden="hidden">
|
||||
<input type="text" class="form-control" name="add_host" placeholder="主机IP,多个逗号分隔">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-success" type="submit">新增主机</button>
|
||||
</span>
|
||||
</div><!-- /input-group -->
|
||||
</div><!-- /.col-lg-6 -->
|
||||
</div><!-- /.row -->
|
||||
</form>
|
||||
<br>
|
||||
|
||||
<form class="form-horizontal" role="form" method="post" action="/chgSudo/" >
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="input-group">
|
||||
<input type="text" name="username" value="{{ username }}" hidden="hidden">
|
||||
<input type="text" class="form-control" name="del_host" placeholder="主机IP,多个逗号分隔">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary" type="submit">删除主机</button>
|
||||
</span>
|
||||
</div><!-- /input-group -->
|
||||
</div><!-- /.col-lg-6 -->
|
||||
</div><!-- /.row -->
|
||||
</form>
|
||||
<br>
|
||||
|
||||
<form class="form-horizontal" role="form" method="post" action="/chgSudo/" >
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="input-group">
|
||||
<input type="text" name="username" value="{{ username }}" hidden="hidden">
|
||||
<input type="text" class="form-control" name="add_cmd" placeholder="添加命令,多个逗号分隔">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-info" type="submit">添加命令</button>
|
||||
</span>
|
||||
</div><!-- /input-group -->
|
||||
</div><!-- /.col-lg-6 -->
|
||||
</div><!-- /.row -->
|
||||
</form>
|
||||
<br>
|
||||
|
||||
<form class="form-horizontal" role="form" method="post" action="/chgSudo/?delCMD=1" >
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="input-group">
|
||||
<input type="text" name="username" value="{{ username }}" hidden="hidden">
|
||||
<input type="text" class="form-control" name="del_cmd" placeholder="删除命令,多个逗号分隔">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-danger" type="submit">删除命令</button>
|
||||
</span>
|
||||
</div><!-- /input-group -->
|
||||
</div><!-- /.col-lg-6 -->
|
||||
</div><!-- /.row -->
|
||||
</form>
|
||||
</fieldset>
|
||||
{% endblock %}
|
||||
76
webroot/AutoSa/templates/chgUser.html
Normal file
76
webroot/AutoSa/templates/chgUser.html
Normal file
@@ -0,0 +1,76 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<form class="form-horizontal" role="form" method="post" action="/chgUser/" >
|
||||
<fieldset >
|
||||
<legend>修改用户信息</legend>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger">
|
||||
Please correct the error{{ form.errors|pluralize }} below.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if msg %}
|
||||
<div class="alert alert-success">
|
||||
{{ msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label for="username" class="col-sm-2 control-label">用户名<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" id="username" name="username" class="form-control" value="{{ user.username }}" readOnly="readOnly">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password" class="col-sm-2 control-label">密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<a href="/chgPass/?username={{ user.username }}">修改密码</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="key_pass" class="col-sm-2 control-label">密钥密码<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<a href="/chgKey/?username={{ user.username }}">修改密码</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name" class="col-sm-2 control-label">姓名<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" id="name" name="name" class="form-control" value="{{ user.name }}" >
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="group" class="col-sm-2 control-label">属组<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<select multiple name="group" id="group" class="form-control">
|
||||
{% for group in groups %}
|
||||
<option value="{{ group.name }}" >{{ group.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="is_admin" class="col-sm-2 control-label">组admin</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="radio" name="is_admin" id="is_admin" value="1">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="is_superuser" class="col-sm-2 control-label">超级admin</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="radio" name="is_superuser" id="is_superuser" value="1">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-4">
|
||||
<button class="btn btn-primary">修改</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock %}
|
||||
37
webroot/AutoSa/templates/downFile.html
Normal file
37
webroot/AutoSa/templates/downFile.html
Normal file
@@ -0,0 +1,37 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<form class="form-horizontal" enctype="multipart/form-data" role="form" method="post" action="" >
|
||||
<fieldset >
|
||||
<legend>{{ username }} -- 下载文件</legend>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success">
|
||||
{{ msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<input type="text" name="username" value="{{ username }}" hidden="hidden">
|
||||
<div class="form-group">
|
||||
<label for="host" class="col-sm-2 control-label">服务器IP<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="host" name="host" placeholder="IP">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="path" class="col-sm-2 control-label">文件path<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="path" name="path" placeholder="文件绝对位置">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-4">
|
||||
<button class="btn btn-primary">下载</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>错误页面</title>
|
||||
<title>通知</title>
|
||||
|
||||
<style type="text/css">
|
||||
body{
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
<h1 style="color: green">说明:</h1>
|
||||
<p>1. 登陆密码:可以修改登陆本系统的密码</p>
|
||||
<p>2. 密钥密码:可以修改登陆服务器时密钥的密码</p>
|
||||
<p>3. pptp密码:可以修改登陆pptp类型vpn即 111.205.130.9的vpn的密码</p>
|
||||
<p>4. Openvpn: 可以修改登陆openvpn类型vpn即 111.205.130.4的vpn的密码</p>
|
||||
|
||||
<p><b>我的密钥:</b> <a href="/downKey/">下载</a></p>
|
||||
<fieldset>
|
||||
@@ -17,8 +15,8 @@
|
||||
<th>ID</th>
|
||||
<th>IP</th>
|
||||
<th>Port</th>
|
||||
<th>IDC</th>
|
||||
<th>备注</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -28,6 +26,7 @@
|
||||
<td style="width: 5px">{{ asset.id }}</td>
|
||||
<td style="width: 90px">{{ asset.ip }}</td>
|
||||
<td style="width: 90px">{{ asset.port }}</td>
|
||||
<td style="width: 90px">{{ asset.idc }}</td>
|
||||
<td style="width: 90px">{{ asset.comment }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
54
webroot/AutoSa/templates/info.html
Normal file
54
webroot/AutoSa/templates/info.html
Normal file
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>信息</title>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
</style>
|
||||
<script language="javascript">
|
||||
var i=2;
|
||||
window.setInterval("settime()",1000);
|
||||
window.setTimeout("toload()",5000);
|
||||
function settime(){
|
||||
var divinner=document.getElementById("settime");
|
||||
divinner.innerText=i;
|
||||
i--;
|
||||
}
|
||||
function toload(){
|
||||
history.go(-1);
|
||||
}
|
||||
</script>
|
||||
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5js"></script>
|
||||
<![endif]-->
|
||||
<link href="/static/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="/static/css/main.css" rel="stylesheet">
|
||||
|
||||
<script src="/static/js/main.js"></script>
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
|
||||
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
{% if msg %}
|
||||
<div class="alert alert-success" style="margin-left: auto;margin-right: auto;margin-top: 60px;width:500px;"><b>成功:</b>{{ msg }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if error %}
|
||||
<div class="alert alert-danger" style="margin-left: auto;margin-right: auto;margin-top: 60px;width:500px;"><b>错误:</b>{{ error }}</div>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
125
webroot/AutoSa/templates/logView.html
Normal file
125
webroot/AutoSa/templates/logView.html
Normal file
@@ -0,0 +1,125 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load mytags %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form method="post" action="">
|
||||
<table class="table table-striped table-hover table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>id</th>
|
||||
<th>用户名</th>
|
||||
<th>主机</th>
|
||||
<th>监控</th>
|
||||
<th>命令统计</th>
|
||||
<th>阻断</th>
|
||||
<th>开始时间</th>
|
||||
<th>结束时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for log in logs.object_list %}
|
||||
<tr>
|
||||
<!--<td><input type="checkbox" name="selected" value="{{ log.id }}"></td>-->
|
||||
<td>{{ log.id }}</td>
|
||||
<td>{{ log.user }}</td>
|
||||
<td>{{ log.host }}</td>
|
||||
{% if log.finish %}
|
||||
<td>监控</td>
|
||||
<td><a href="/logHistory/?id={{ log.id }}" class="log_command">统计</a></td>
|
||||
<td>阻断</td>
|
||||
{% else %}
|
||||
<td><a class='monitor' filename="{{ log.logfile }}">监控</a></td>
|
||||
<td>命令统计</td>
|
||||
<td><a href="/killSession/?id={{ log.id }}">阻断</a> </td>
|
||||
{% endif %}
|
||||
<td>{{ log.start_time|stamp2str }}</td>
|
||||
<td>{{ log.end_time|stamp2str }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<script src="http://{{ web_socket_host }}/socket.io/socket.io.js"></script>
|
||||
|
||||
|
||||
<script >
|
||||
$.fn.webSocket = function(opt){
|
||||
var st = {};
|
||||
st = $.extend(st,opt);
|
||||
var message = {};
|
||||
var $this = $(this);
|
||||
|
||||
|
||||
var genUid = function(){
|
||||
return new Date().getTime()+""+Math.floor(Math.random()*899+100);
|
||||
};
|
||||
|
||||
var init = function(e){
|
||||
|
||||
var socket = io.connect('ws://'+globalConfig.SOCKET_HOST);
|
||||
var node = $(e.target);
|
||||
message.id = genUid();
|
||||
message.filename = node.attr('filename');
|
||||
BootstrapDialog.show({message:function(){
|
||||
var escapeString = function (html){
|
||||
var elem = document.createElement('div')
|
||||
var txt = document.createTextNode(html)
|
||||
elem.appendChild(txt)
|
||||
return elem.innerHTML;
|
||||
}
|
||||
var tag = $('<div id="log" style="height:300px;overflow: auto;"></div>');
|
||||
//告诉服务器端有用户登录
|
||||
socket.emit('login', {userid:message.id, filename:message.filename});
|
||||
socket.on('message',function(obj){
|
||||
//去除log中的颜色控制字符
|
||||
var regx = /\x1B\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]/g;
|
||||
tag.append('<p>'+escapeString(obj.content.replace(regx,''))+'</p>');
|
||||
tag.animate({ scrollTop: tag[0].scrollHeight}, 1);
|
||||
});
|
||||
return tag[0];
|
||||
} ,
|
||||
title:'实时监控:',
|
||||
onhide:function(){
|
||||
socket.emit('disconnect');
|
||||
}});
|
||||
}
|
||||
|
||||
|
||||
$this.on("click",function(e){
|
||||
init(e);
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
$('.log_command').on('click',function(){
|
||||
var url = $(this).attr('href');
|
||||
$.ajax({url:url,success:function(data){
|
||||
BootstrapDialog.show({title:'命令统计',message:data});
|
||||
}});
|
||||
return false;
|
||||
})
|
||||
globalConfig = {
|
||||
SOCKET_HOST: "{{ web_socket_host }}"
|
||||
}
|
||||
$(".monitor").webSocket()
|
||||
|
||||
</script>
|
||||
<!--<button class="btn btn-primary">删除</button>-->
|
||||
</form>
|
||||
<nav>
|
||||
<ul class="pager">
|
||||
{% if logs.has_previous %}
|
||||
<li><a href="?page={{ logs.previous_page_number }}">上一页</a></li>
|
||||
{% endif %}
|
||||
|
||||
<span class="current">
|
||||
Page {{ logs.number }} of {{ logs.paginator.num_pages }}.
|
||||
</span>
|
||||
|
||||
{% if logs.has_next %}
|
||||
<li><a href="?page={{ logs.next_page_number }}">下一页</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endblock %}
|
||||
@@ -1,43 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<form method="post" action="">
|
||||
<div style="float: left; width: 400px;">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="input-group">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button">IP(s)</button>
|
||||
</span>
|
||||
<input type="text" class="form-control" name="ip" placeholder="IP or IPS" value={{ old_ip }}>
|
||||
|
||||
</div><!-- /input-group -->
|
||||
<span class="help-block" style="margin-left: 20px;"> 输入一个IP,或者多个IP逗号隔开。</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="input-group">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button">CMD</button>
|
||||
</span>
|
||||
<input type="text" class="form-control" name="cmd" placeholder="Command or Commands">
|
||||
</div><!-- /input-group -->
|
||||
<span class="help-block" style="margin-left: 20px;"> 输入在执行的命令,多个命令分号隔开.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="float: left; margin-top: 74px; margin-left: 40px;">
|
||||
<button type="submit" class="btn btn-primary">执行</button>
|
||||
</div>
|
||||
<div style="clear: both;"></div>
|
||||
|
||||
</form>
|
||||
{% if stdout %}
|
||||
<div class="alert alert-success">{{ stdout }}</div>
|
||||
{% endif %}
|
||||
{% if stderr %}
|
||||
<div class="alert alert-warning">{{ stderr }}</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -13,6 +13,7 @@
|
||||
<th>ID</th>
|
||||
<th>IP</th>
|
||||
<th>Port</th>
|
||||
<th>IDC</th>
|
||||
<th>备注</th>
|
||||
|
||||
</tr>
|
||||
@@ -24,6 +25,7 @@
|
||||
<td style="width: 5px">{{ asset.id }}</td>
|
||||
<td style="width: 90px">{{ asset.ip }}</td>
|
||||
<td style="width: 90px">{{ asset.port }}</td>
|
||||
<td style="width: 90px">{{ asset.idc }}</td>
|
||||
<td style="width: 90px">{{ asset.comment }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -31,4 +33,19 @@
|
||||
</table>
|
||||
<button class="btn btn-primary">删除</button></td>
|
||||
</form>
|
||||
<nav>
|
||||
<ul class="pager">
|
||||
{% if assets.has_previous %}
|
||||
<li><a href="?page={{ assets.previous_page_number }}">上一页</a></li>
|
||||
{% endif %}
|
||||
|
||||
<span class="current">
|
||||
Page {{ assets.number }} of {{ assets.paginator.num_pages }}.
|
||||
</span>
|
||||
|
||||
{% if assets.has_next %}
|
||||
<li><a href="?page={{ assets.next_page_number }}">下一页</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endblock %}
|
||||
@@ -10,20 +10,18 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th><input onclick="selectAll()" type="checkbox" name="select_all" style="select_all" id="select_all"/></th>
|
||||
<th>ip</th>
|
||||
<th>用户名</th>
|
||||
<th>端口</th>
|
||||
<th>sudo</th>
|
||||
<th>ID</th>
|
||||
<th>属组</th>
|
||||
<th>修改</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for server in servers %}
|
||||
{% for group in groups %}
|
||||
<tr>
|
||||
<td><input type="checkbox" name="selected" value="{{ server.id }}"></td>
|
||||
<td>{{ server.ip }}</td>
|
||||
<td>{{ server.username }}</td>
|
||||
<td>{{ server.port }}</td>
|
||||
<td>{{ server.sudo }}</td>
|
||||
<td><input type="checkbox" name="selected" value="{{ group.id }}"></td>
|
||||
<td>{{ group.id }}</td>
|
||||
<td>{{ group.name }}</td>
|
||||
<td><a href="/chgGroup/?id={{ group.id }}">修改</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
31
webroot/AutoSa/templates/showIDC.html
Normal file
31
webroot/AutoSa/templates/showIDC.html
Normal file
@@ -0,0 +1,31 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<form method="post" action="">
|
||||
{% if info %}
|
||||
<p class="alert alert-success">
|
||||
{{ info }}
|
||||
</p>
|
||||
{% endif %}
|
||||
<table class="table table-striped table-hover table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><input onclick="selectAll()" type="checkbox" name="select_all" style="select_all" id="select_all"/></th>
|
||||
<th>ID</th>
|
||||
<th>IDC</th>
|
||||
<th>修改</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for idc in idcs %}
|
||||
<tr>
|
||||
<td><input type="checkbox" name="selected" value="{{ idc.id }}"></td>
|
||||
<td>{{ idc.id }}</td>
|
||||
<td>{{ idc.name }}</td>
|
||||
<td><a href="/chgIDC/?id={{ idc.id }}">修改</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<button class="btn btn-primary">删除</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
19
webroot/AutoSa/templates/showSudo.html
Normal file
19
webroot/AutoSa/templates/showSudo.html
Normal file
@@ -0,0 +1,19 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<fieldset >
|
||||
<legend>{{ username }}</legend>
|
||||
<b>允许sudo的主机:</b>
|
||||
<ul class="list-group">
|
||||
{% for host in sudoHost %}
|
||||
<li class="list-group-item">{{ host }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<br />
|
||||
<b>允许的sudo命令:</b>
|
||||
<ul class="list-group">
|
||||
{% for cmd in sudoCommand %}
|
||||
<li class="list-group-item">{{ cmd }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</fieldset>
|
||||
{% endblock %}
|
||||
@@ -13,8 +13,14 @@
|
||||
<th>ID</th>
|
||||
<th>用户名</th>
|
||||
<th>姓名</th>
|
||||
<th>属组</th>
|
||||
<th>is_admin</th>
|
||||
<th>is_superuser</th>
|
||||
<th>Email</th>
|
||||
<th>Key</th>
|
||||
<th>密钥</th>
|
||||
<th>用户信息</th>
|
||||
<th>sudo</th>
|
||||
<th>sudo</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -24,8 +30,18 @@
|
||||
<td>{{ user.id }}</td>
|
||||
<td>{{ user.username }}</td>
|
||||
<td>{{ user.name }}</td>
|
||||
<td>
|
||||
{% for group in user.group.all %}
|
||||
{{ group.name }}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td>{{ user.is_admin }}</td>
|
||||
<td>{{ user.is_superuser }}</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td><a href="/downKey/">下载</a></td>
|
||||
<td><a href="/downKey/?username={{ user.username }}">下载</a></td>
|
||||
<td><a href="/chgUser/?username={{ user.username }}">修改</a></td>
|
||||
<td><a href="/showSudo/?username={{ user.username }}">查看</a></td>
|
||||
<td><a href="/chgSudo/?username={{ user.username }}">修改</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>运维管理系统</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="http://img.youlu.com/web/favicon.gif" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5js"></script>
|
||||
<![endif]-->
|
||||
<link href="/static/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="/static/css/main.css" rel="stylesheet">
|
||||
|
||||
<script src="/static/js/main.js"></script>
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
|
||||
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
|
||||
<div class="navbar-header"> <a class="navbar-brand" href="#">运维管理系统</a> </div>
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="/">主页</a></li>
|
||||
<li><a href="#">用户管理</a></li>
|
||||
<li><a href="#">命令执行</a></li>
|
||||
<li><a href="#">主机管理</a></li>
|
||||
</ul>
|
||||
<div class="btn-group navbar-right">
|
||||
<button type="button" class="btn btn-primary dropdown-toggle " data-toggle="dropdown">
|
||||
{{ name }}<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-logout">
|
||||
<li class="dropdown-logout"><a href="/logout/">退出</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<div class="row row-offcanvas row-offcanvas-right">
|
||||
<div class="col-xs-12 col-sm-3 sidebar-offcanvas" id="sidebar" role="navigation">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="row>
|
||||
<!--Sidebar content-->
|
||||
<div class="sidebar-menu">
|
||||
<div class="menu-first" ><a href="#userMenu" data-toggle="collapse"><i class="glyphicon glyphicon-th"></i> 用户管理</a></div>
|
||||
<ul id="userMenu" class="nav nav-list navbar-collapse.in menu-second">
|
||||
<li><a href="/showUser/"><i class="glyphicon glyphicon-send"></i> 查看用户</a></li>
|
||||
<li><a href="/addUser/"><i class="glyphicon glyphicon-send"></i> 添加用户</a></li>
|
||||
</ul>
|
||||
<div class="menu-first" ><a href="#monitorMenu" data-toggle="collapse"><i class="glyphicon glyphicon-th"></i> 执行命令</a></div>
|
||||
<ul id="monitorMenu" class="nav nav-list navbar-collapse.in menu-second">
|
||||
<li><a href="/runCommand/"><i class="glyphicon glyphicon-send"></i> 执行命令</a></li>
|
||||
<li><a href="/addServer/"><i class="glyphicon glyphicon-send"></i> 添加主机</a></li>
|
||||
<li><a href="#"><i class="glyphicon glyphicon-send"></i> 环境</a></li>
|
||||
</ul>
|
||||
<div class="menu-first" ><a href="#articleMenu" data-toggle="collapse"><i class="glyphicon glyphicon-th"></i> 主机管理</a></div>
|
||||
<ul id="articleMenu" class="nav nav-list navbar-collapse menu-second">
|
||||
<li><a href="/showAssets/"><i class="glyphicon glyphicon-send"></i> 主机列表</a></li>
|
||||
<li><a href="/addAssets/"><i class="glyphicon glyphicon-send"></i> 添加主机</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button">Go!</button>
|
||||
</span>
|
||||
<input type="text" class="form-control">
|
||||
</div><!-- /input-group -->
|
||||
</div><!-- /.col-lg-6 -->
|
||||
<div class="col-lg-6">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button">Go!</button>
|
||||
</span>
|
||||
</div><!-- /input-group -->
|
||||
</div><!-- /.col-lg-6 -->
|
||||
</div><!-- /.row -->
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
43
webroot/AutoSa/templates/upFile.html
Normal file
43
webroot/AutoSa/templates/upFile.html
Normal file
@@ -0,0 +1,43 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<form class="form-horizontal" enctype="multipart/form-data" role="form" method="post" action="" >
|
||||
<fieldset >
|
||||
<legend>{{ username }} -- 上传文件</legend>
|
||||
{% if error %}
|
||||
<div class="alert alert-danger">
|
||||
{{ error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success">
|
||||
{{ msg }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<input type="text" name="username" value="{{ username }}" hidden="hidden">
|
||||
<div class="form-group">
|
||||
<label for="host" class="col-sm-2 control-label">服务器IP<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="host" name="host" placeholder="IP">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="path" class="col-sm-2 control-label">上传目录<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control" id="path" name="path" placeholder="服务器目录">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="file" class="col-sm-2 control-label">选择文件<span style="color: red"> *</span></label>
|
||||
<div class="col-sm-4">
|
||||
<input type="file" class="form-control" id="file" name="file" placeholder="点击添加">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-4">
|
||||
<button class="btn btn-primary">上传</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% endblock %}
|
||||
92
webroot/AutoSa/websocket/index.js
Normal file
92
webroot/AutoSa/websocket/index.js
Normal file
@@ -0,0 +1,92 @@
|
||||
var app = require('express')();
|
||||
var http = require('http').Server(app);
|
||||
var io = require('socket.io')(http);
|
||||
var spawn = require('child_process').spawn;
|
||||
|
||||
|
||||
|
||||
var Tail = require('tail').Tail;
|
||||
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send('<h1>Welcome Realtime Server</h1>');
|
||||
});
|
||||
|
||||
//在线用户
|
||||
var onlineUsers = {};
|
||||
//当前在线人数
|
||||
var onlineCount = 0;
|
||||
|
||||
io.on('connection', function(socket){
|
||||
//console.log('a user connected');
|
||||
|
||||
//监听新用户加入
|
||||
socket.on('login', function(obj){
|
||||
//将新加入用户的唯一标识当作socket的名称,后面退出的时候会用到
|
||||
socket.name = obj.userid;
|
||||
socket.fileName = obj.filename;
|
||||
var tail = new Tail(obj.filename);
|
||||
//console.log(obj.filename);
|
||||
tail.on('line',function(data) {
|
||||
//console.log(data);
|
||||
var newData = {userid:obj.userid,username:obj.username,content:data};
|
||||
socket.emit('message',newData);
|
||||
});
|
||||
// var tail = spawn("tail", ['-f', obj.filename]);
|
||||
// tail.stdout.on('data',function(data){
|
||||
// var content = data.toString();
|
||||
// //console.log(content);
|
||||
// var newData = {userid:obj.userid,username:obj.username,content:content};
|
||||
// socket.emit('message',newData);
|
||||
// });
|
||||
|
||||
|
||||
socket.tail = tail;
|
||||
|
||||
//检查在线列表,如果不在里面就加入
|
||||
if(!onlineUsers.hasOwnProperty(obj.userid)) {
|
||||
onlineUsers[obj.userid] = obj.username;
|
||||
//在线人数+1
|
||||
onlineCount++;
|
||||
}
|
||||
|
||||
//向所有客户端广播用户加入
|
||||
//io.emit('login', {onlineUsers:onlineUsers, onlineCount:onlineCount, user:obj});
|
||||
//console.log(obj.username+'加入了聊天室');
|
||||
});
|
||||
|
||||
//监听用户退出
|
||||
socket.on('disconnect', function(){
|
||||
//将退出的用户从在线列表中删除
|
||||
if(onlineUsers.hasOwnProperty(socket.name)) {
|
||||
//退出用户的信息
|
||||
var obj = {userid:socket.name, username:onlineUsers[socket.name]};
|
||||
|
||||
if( socket.tail){
|
||||
socket.tail.unwatch();
|
||||
}
|
||||
|
||||
//删除
|
||||
delete onlineUsers[socket.name];
|
||||
//在线人数-1
|
||||
onlineCount--;
|
||||
|
||||
//向所有客户端广播用户退出
|
||||
//io.emit('logout', {onlineUsers:onlineUsers, onlineCount:onlineCount, user:obj});
|
||||
////console.log(obj.username+'退出了聊天室');
|
||||
}
|
||||
});
|
||||
|
||||
//监听用户发布聊天内容
|
||||
socket.on('message', function(obj){
|
||||
//向所有客户端广播发布的消息
|
||||
//io.emit('message', obj);
|
||||
socket.emit('message',obj);
|
||||
////console.log(obj.username+'说:'+obj.content);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
http.listen(3000, function(){
|
||||
console.log('listening on *:3000');
|
||||
});
|
||||
11
webroot/AutoSa/websocket/package.json
Normal file
11
webroot/AutoSa/websocket/package.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "web-socket",
|
||||
"version": "0.0.1",
|
||||
"description": "my first realtime server",
|
||||
"dependencies": {
|
||||
"express": "~4.10.1",
|
||||
"socket.io": "~1.2.0",
|
||||
"node-tail": "0.0.4",
|
||||
"tail": "~0.4.0"
|
||||
}
|
||||
}
|
||||
1
webroot/__init__.py
Normal file
1
webroot/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
__author__ = 'Hudie'
|
||||
Reference in New Issue
Block a user