系统设置-存储设置功能完成,存储空间清理功能完成。

pull/105/head
Apex Liu 2017-11-05 15:08:26 +08:00
parent e686a583de
commit f0e1c2afc8
7 changed files with 538 additions and 477 deletions

View File

@ -3,18 +3,39 @@
$app.on_init = function (cb_stack) {
console.log($app.options);
//=========================================
// 邮件系统配置相关
//=========================================
$app.dlg_result = $app.create_dlg_result();
// cb_stack.add($app.dlg_result.init);
$app.smtp = $app.create_config_smtp();
cb_stack.add($app.smtp.init);
$app.sec = $app.create_config_sec();
cb_stack.add($app.sec.init);
$app.storage = $app.create_config_storage();
cb_stack.add($app.storage.init);
cb_stack.exec();
};
$app.create_dlg_result = function () {
var _dlg = {};
_dlg.dom = {
dlg: $('#dlg-result'),
title: $('#dlg-result-title'),
msg: $('#dlg-result-msg')
};
_dlg.show = function(title, msg) {
_dlg.dom.title.text(title);
_dlg.dom.msg.html(msg);
_dlg.dom.dlg.modal();
};
return _dlg;
};
$app.create_config_smtp = function () {
var _smtp = {};
@ -25,7 +46,7 @@ $app.create_config_smtp = function () {
sender: $('#smtp-sender-info'),
btn_edit: $('#btn-edit-mail-config'),
dlg_edit: $('#dlg-edit-mail-config'),
dlg_edit: $('#dlg-edit-smtp-config'),
input_server: $('#edit-smtp-server'),
input_port: $('#edit-smtp-port'),
input_ssl: $('#edit-smtp-ssl'),
@ -361,3 +382,142 @@ $app.create_config_sec = function () {
return _sec;
};
$app.create_config_storage = function () {
var _sto = {};
_sto.dom = {
storage_size: $('#storage-size'),
btn_save: $('#btn-save-storage-config'),
btn_cleanup: $('#btn-clear-storage'),
input_keep_log: $('#storage-keep-log'),
input_keep_record: $('#storage-keep-record'),
select_cleanup_hour: $('#select-cleanup-storage-hour'),
select_cleanup_minute: $('#select-cleanup-storage-minute')
};
_sto.init = function (cb_stack) {
// 当前会话录像存储空间:总 123.35GB,可用空间 85.17GB。
var _info = [];
if (!$app.options.core_cfg.detected) {
_sto.dom.storage_size.removeClass().addClass('alert alert-danger');
_info.push('未能连接到核心服务,无法获取存储空间信息!');
} else {
_sto.dom.storage_size.removeClass().addClass('alert alert-info');
_info.push('<p>会话录像存储路径:<code>' + $app.options.core_cfg.replay_path + '</code></p>');
_info.push('<p>会话录像存储空间:总 ' + tp_size2str($app.options.total_size, 2) + '' + '可用 ' + tp_size2str($app.options.free_size, 2) + '。</p>');
}
_sto.dom.storage_size.html(_info.join(''));
_sto.update_dom($app.options.sys_cfg.storage);
_sto.dom.btn_save.click(function () {
_sto.on_btn_save();
});
_sto.dom.btn_cleanup.click(function () {
_sto.on_btn_cleanup();
});
cb_stack.exec();
};
_sto.update_dom = function (storage) {
_sto.dom.input_keep_log.val(storage.keep_log);
_sto.dom.input_keep_record.val(storage.keep_record);
_sto.dom.select_cleanup_hour.val(storage.cleanup_hour);
_sto.dom.select_cleanup_minute.val(storage.cleanup_minute);
};
_sto.on_btn_save = function () {
var _keep_log = parseInt(_sto.dom.input_keep_log.val());
var _keep_record = parseInt(_sto.dom.input_keep_record.val());
var _cleanup_hour = parseInt(_sto.dom.select_cleanup_hour.val());
var _cleanup_minute = parseInt(_sto.dom.select_cleanup_minute.val());
if (!(_keep_log === 0 || (_keep_log >= 30 && _keep_log <= 180))) {
$tp.notify_error('日志保留时间超出范围!');
_sto.dom.input_keep_log.focus();
return;
}
if (!(_keep_record === 0 || (_keep_record >= 30 && _keep_record <= 180))) {
$tp.notify_error('会话录像保留时间超出范围!');
_sto.dom.input_keep_record.focus();
return;
}
_sto.dom.btn_save.attr('disabled', 'disabled');
$tp.ajax_post_json('/system/save-cfg',
{
storage: {
keep_log: _keep_log,
keep_record: _keep_record,
cleanup_hour: _cleanup_hour,
cleanup_minute: _cleanup_minute
}
},
function (ret) {
_sto.dom.btn_save.removeAttr('disabled');
if (ret.code === TPE_OK) {
$tp.notify_success('存储设置更新成功!');
// 更新一下界面上显示的配置信息
$app.options.sys_cfg.storage.keep_log = _keep_log;
$app.options.sys_cfg.storage.keep_record = _keep_record;
$app.options.sys_cfg.storage.cleanup_hour = _cleanup_hour;
$app.options.sys_cfg.storage.cleanup_minute = _cleanup_minute;
_sto.update_dom($app.options.sys_cfg.storage);
} else {
$tp.notify_error('存储设置更新失败:' + tp_error_msg(ret.code, ret.message));
}
},
function () {
_sto.dom.btn_save.removeAttr('disabled');
$tp.notify_error('网路故障,存储设置更新失败!');
}
);
};
_sto.on_btn_cleanup = function () {
var _keep_log = parseInt(_sto.dom.input_keep_log.val());
var _keep_record = parseInt(_sto.dom.input_keep_record.val());
if($app.options.sys_cfg.storage.keep_log !== _keep_log || $app.options.sys_cfg.storage.keep_record !== _keep_record) {
$tp.notify_error('您已经修改了设置,请先保存设置,再进行清理!');
return;
}
if($app.options.sys_cfg.storage.keep_log === 0 && $app.options.sys_cfg.storage.keep_record === 0) {
$tp.notify_error('根据设置,没有需要清理的内容!');
return;
}
_sto.dom.btn_cleanup.attr('disabled', 'disabled');
$tp.ajax_post_json('/system/cleanup-storage', {},
function (ret) {
_sto.dom.btn_cleanup.removeAttr('disabled');
if (ret.code === TPE_OK) {
console.log(ret);
$tp.notify_success('清理存储空间成功!');
var msg = [];
for(var i = 0; i < ret.data.length; ++i) {
msg.push('<p>'+ret.data[i]+'</p>');
}
$app.dlg_result.show('清理存储空间', msg.join(''));
} else {
$tp.notify_error('清理存储空间失败:' + tp_error_msg(ret.code, ret.message));
}
},
function () {
_sto.dom.btn_cleanup.removeAttr('disabled');
$tp.notify_error('网路故障,清理存储空间失败!');
},
120000
);
};
return _sto;
};

View File

@ -20,7 +20,7 @@
<li class="active"><a href="#tab-security" data-toggle="tab">安全</a></li>
<li><a href="#tab-smtp" data-toggle="tab">邮件系统</a></li>
<li><a href="#tab-storage" data-toggle="tab">存储</a></li>
## <li><a href="#tab-backup" data-toggle="tab">备份</a></li>
## <li><a href="#tab-backup" data-toggle="tab">备份</a></li>
</ul>
<div class="tab-content">
@ -137,7 +137,7 @@
<!-- panel for storage config -->
<div class="tab-pane" id="tab-storage">
<div class="alert alert-info">当前会话录像存储空间:总 123.35GB,可用空间 85.17GB。</div>
<div id="storage-size" class="alert alert-info">-</div>
<table class="table table-config-list">
<tr>
<td colspan="2" class="title">系统日志</td>
@ -171,46 +171,46 @@
<tr>
<td class="key">时间点</td>
<td class="value">
<select id="select-backup-hour">
<option>00</option>
<option>01</option>
<option>02</option>
<option selected="selected">04</option>
<option>04</option>
<option>05</option>
<option>06</option>
<option>07</option>
<option>08</option>
<option>09</option>
<option>10</option>
<option>11</option>
<option>12</option>
<option>13</option>
<option>14</option>
<option>15</option>
<option>16</option>
<option>17</option>
<option>18</option>
<option>19</option>
<option>20</option>
<option>21</option>
<option>22</option>
<option>23</option>
<select id="select-cleanup-storage-hour">
<option value="0">00</option>
<option value="1">01</option>
<option value="2">02</option>
<option value="3">03</option>
<option value="4">04</option>
<option value="5">05</option>
<option value="6">06</option>
<option value="7">07</option>
<option value="8">08</option>
<option value="9">09</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
</select>
<select id="select-backup-min">
<option selected="selected">00</option>
<option>05</option>
<option>10</option>
<option>15</option>
<option>20</option>
<option>25</option>
<option>30</option>
<option>35</option>
<option>40</option>
<option>45</option>
<option>50</option>
<option>55</option>
<select id="select-cleanup-storage-minute">
<option value="0">00</option>
<option value="5">05</option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="25">25</option>
<option value="30">30</option>
<option value="35">35</option>
<option value="40">40</option>
<option value="45">45</option>
<option value="50">50</option>
<option value="55">55</option>
</select>
<span class="desc">每天在指定时间点清理存储。</span>
@ -219,122 +219,122 @@
<tr>
<td class="key"></td>
<td class="value">
<button id="btn-clear-storage" class="btn btn-sm btn-success"><i class="fa fa-leaf fa-fw"></i> 现在立即清理</button>
<button id="btn-clear-storage" class="btn btn-sm btn-success"><i class="fa fa-leaf fa-fw"></i> 现在立即清理</button>
</td>
</tr>
</table>
<hr/>
<button id="btn-save-storage-config" class="btn btn-sm btn-primary"><i class="fa fa-check-circle fa-fw"></i> 保存存储设置</button>
## <button id="btn-clear-storage" class="btn btn-sm btn-danger"><i class="fa fa-edit fa-fw"></i> 立即清理</button>
## <button id="btn-clear-storage" class="btn btn-sm btn-danger"><i class="fa fa-edit fa-fw"></i> 立即清理</button>
</div>
<!-- panel for backup config -->
## <div class="tab-pane" id="tab-backup">
## <div class="alert alert-danger">备份功能尚未实现</div>
##
## <table class="table table-config-list">
## <tr>
## <td colspan="2" class="title">数据库备份</td>
## </tr>
## <tr>
## <td class="key">备份范围</td>
## <td class="value">
## <div id="btn-bak-syslog" class="tp-checkbox tp-editable">包括系统日志</div>
## </td>
## </tr>
## <tr>
## <td class="key"></td>
## <td class="value">
## <div id="btn-backup-alert" class="tp-checkbox tp-editable">包括报警日志</div>
## </td>
## </tr>
## <tr>
## <td class="key"></td>
## <td class="value">
## <div id="btn-backup-ops" class="tp-checkbox tp-editable">包括运维记录</div>
## </td>
## </tr>
## <tr>
## <td class="key">自动备份</td>
## <td class="value">
## <div id="btn-auto-backup" class="tp-checkbox tp-editable tp-selected">在指定时间点自动备份数据库</div>
## </td>
## </tr>
## <tr>
## <td class="key">备份时间点</td>
## <td class="value">
## <select id="select-backup-hour">
## <option>00</option>
## <option>01</option>
## <option>02</option>
## <option selected="selected">03</option>
## <option>04</option>
## <option>05</option>
## <option>06</option>
## <option>07</option>
## <option>08</option>
## <option>09</option>
## <option>10</option>
## <option>11</option>
## <option>12</option>
## <option>13</option>
## <option>14</option>
## <option>15</option>
## <option>16</option>
## <option>17</option>
## <option>18</option>
## <option>19</option>
## <option>20</option>
## <option>21</option>
## <option>22</option>
## <option>23</option>
## </select>
## 时
## <select id="select-backup-min">
## <option selected="selected">00</option>
## <option>05</option>
## <option>10</option>
## <option>15</option>
## <option>20</option>
## <option>25</option>
## <option>30</option>
## <option>35</option>
## <option>40</option>
## <option>45</option>
## <option>50</option>
## <option>55</option>
## </select>
## 分
## <span class="desc">每天在指定时间点备份数据库。</span>
## </td>
## </tr>
## <tr>
## <td class="key">备份保留时长</td>
## <td class="value">
## <input id="backup-keep-timeout" type="text" value="7"/><span class="unit">天</span><span class="desc">1~7。超过设定时间的备份将自动删除默认为7天。</span>
## </td>
## </tr>
## <tr>
## <td class="key"></td>
## <td class="value">
## <a href="javascript:;"><i class="fa fa-download"></i> 下载自动备份文件</a>
## </td>
## </tr>
##
## </table>
## <hr/>
## <button id="btn-save-storage-config" class="btn btn-sm btn-primary"><i class="fa fa-edit fa-fw"></i> 保存存储设置</button>
## <button id="btn-do-backup" class="btn btn-sm btn-success"><i class="fa fa-edit fa-fw"></i> 立即备份</button>
## <button id="btn-import-backup" class="btn btn-sm btn-danger"><i class="fa fa-edit fa-fw"></i> 导入备份</button>
## </div>
## <div class="tab-pane" id="tab-backup">
## <div class="alert alert-danger">备份功能尚未实现</div>
##
## <table class="table table-config-list">
## <tr>
## <td colspan="2" class="title">数据库备份</td>
## </tr>
## <tr>
## <td class="key">备份范围</td>
## <td class="value">
## <div id="btn-bak-syslog" class="tp-checkbox tp-editable">包括系统日志</div>
## </td>
## </tr>
## <tr>
## <td class="key"></td>
## <td class="value">
## <div id="btn-backup-alert" class="tp-checkbox tp-editable">包括报警日志</div>
## </td>
## </tr>
## <tr>
## <td class="key"></td>
## <td class="value">
## <div id="btn-backup-ops" class="tp-checkbox tp-editable">包括运维记录</div>
## </td>
## </tr>
## <tr>
## <td class="key">自动备份</td>
## <td class="value">
## <div id="btn-auto-backup" class="tp-checkbox tp-editable tp-selected">在指定时间点自动备份数据库</div>
## </td>
## </tr>
## <tr>
## <td class="key">备份时间点</td>
## <td class="value">
## <select id="select-backup-hour">
## <option>00</option>
## <option>01</option>
## <option>02</option>
## <option selected="selected">03</option>
## <option>04</option>
## <option>05</option>
## <option>06</option>
## <option>07</option>
## <option>08</option>
## <option>09</option>
## <option>10</option>
## <option>11</option>
## <option>12</option>
## <option>13</option>
## <option>14</option>
## <option>15</option>
## <option>16</option>
## <option>17</option>
## <option>18</option>
## <option>19</option>
## <option>20</option>
## <option>21</option>
## <option>22</option>
## <option>23</option>
## </select>
## 时
## <select id="select-backup-min">
## <option selected="selected">00</option>
## <option>05</option>
## <option>10</option>
## <option>15</option>
## <option>20</option>
## <option>25</option>
## <option>30</option>
## <option>35</option>
## <option>40</option>
## <option>45</option>
## <option>50</option>
## <option>55</option>
## </select>
## 分
## <span class="desc">每天在指定时间点备份数据库。</span>
## </td>
## </tr>
## <tr>
## <td class="key">备份保留时长</td>
## <td class="value">
## <input id="backup-keep-timeout" type="text" value="7"/><span class="unit">天</span><span class="desc">1~7。超过设定时间的备份将自动删除默认为7天。</span>
## </td>
## </tr>
## <tr>
## <td class="key"></td>
## <td class="value">
## <a href="javascript:;"><i class="fa fa-download"></i> 下载自动备份文件</a>
## </td>
## </tr>
##
## </table>
## <hr/>
## <button id="btn-save-storage-config" class="btn btn-sm btn-primary"><i class="fa fa-edit fa-fw"></i> 保存存储设置</button>
## <button id="btn-do-backup" class="btn btn-sm btn-success"><i class="fa fa-edit fa-fw"></i> 立即备份</button>
## <button id="btn-import-backup" class="btn btn-sm btn-danger"><i class="fa fa-edit fa-fw"></i> 导入备份</button>
## </div>
</div>
</div>
</div>
<%block name="extend_content">
<!-- dialog for edit mail config -->
<div class="modal fade" id="dlg-edit-mail-config" tabindex="-1" role="dialog">
<!-- dialog for edit smtp config -->
<div class="modal fade" id="dlg-edit-smtp-config">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
@ -411,4 +411,22 @@
</div>
</div>
<!-- dialog for show storage cleanup result -->
<div class="modal fade" id="dlg-result">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fa fa-times-circle fa-fw"></i></button>
<h3 id="dlg-result-title" class="modal-title">-</h3>
</div>
<div class="modal-body">
<div id="dlg-result-msg"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal"><i class="fa fa-close fa-fw"></i> 关闭</button>
</div>
</div>
</div>
</div>
</%block>

View File

@ -533,6 +533,10 @@ class AppConfig(BaseAppConfig):
self.sys.storage.keep_log = 0
if not self.sys.storage.is_exists('keep_record'):
self.sys.storage.keep_record = 0
if not self.sys.storage.is_exists('cleanup_hour'):
self.sys.storage.cleanup_hour = 4
if not self.sys.storage.is_exists('cleanup_minute'):
self.sys.storage.cleanup_minute = 30
self.sys.loaded = True

View File

@ -217,10 +217,12 @@ controllers = [
(r'/system/get-logs', system.DoGetLogsHandler),
# - 系统配置页面
(r'/system/config', system.ConfigHandler),
# - [json] 系统配置-发送测试邮件
(r'/system/send-test-mail', system.DoSendTestMailHandler),
# - [json] 系统配置-保存配置
(r'/system/save-cfg', system.DoSaveCfgHandler),
# - [json] 系统配置-发送测试邮件
(r'/system/send-test-mail', system.DoSendTestMailHandler),
# - [json] 系统配置-清理存储空间
(r'/system/cleanup-storage', system.DoCleanupStorageHandler),
# - [json] 获取服务器时间
(r'/system/get-time', system.DoGetTimeHandler),

View File

@ -1,238 +0,0 @@
# -*- coding: utf-8 -*-
import ctypes
import json
import os
import platform
from app.base.configs import get_cfg
from app.module import record
from app.module import user
from app.base.controller import TPBaseAdminAuthHandler, TPBaseAdminAuthJsonHandler
import tornado.web
def get_free_space_bytes(folder):
""" Return folder/drive free space (in bytes)
"""
if platform.system() == 'Windows':
_free_bytes = ctypes.c_ulonglong(0)
_total_bytes = ctypes.c_ulonglong(0)
ctypes.windll.kernel32.GetDiskFreeSpaceExW(folder, None, ctypes.pointer(_total_bytes), ctypes.pointer(_free_bytes))
total_bytes = _total_bytes.value
free_bytes = _free_bytes.value
else:
try:
st = os.statvfs(folder)
total_bytes = st.f_blocks * st.f_frsize
free_bytes = st.f_bavail * st.f_frsize
except:
total_bytes = 0
free_bytes = 0
return total_bytes, free_bytes
class LogHandler(TPBaseAdminAuthHandler):
def get(self):
if not get_cfg().core.detected:
total_size = 0
free_size = 0
else:
total_size, free_size = get_free_space_bytes(get_cfg().core.replay_path)
param = {
'user_list': user.get_user_list(with_admin=True),
'total_size': total_size,
'free_size': free_size,
}
self.render('log/index.mako', page_param=json.dumps(param))
class RecordHandler(TPBaseAdminAuthHandler):
def get(self, protocol, record_id):
protocol = int(protocol)
if protocol == 1:
return
elif protocol == 2:
self.render('log/record.mako', record_id=record_id)
# class PlayRdpHandler(TPBaseAdminAuthHandler):
# def get(self, ip, record_id):
# # protocol = int(protocol)
# # if protocol == 1:
# # return
# # elif protocol == 2:
# # self.render('log/record.mako', record_id=record_id)
# # return
# # pass
# filename = os.path.join(cfg.base.replay_path, 'replay', 'rdp', '{}'.format(record_id), 'tp-rdp.tpr')
class ReplayStaticFileHandler(tornado.web.StaticFileHandler):
def initialize(self, path, default_filename=None):
super().initialize(path, default_filename)
self.root = get_cfg().core.replay_path
# self.default_filename = default_filename
class ComandLogHandler(TPBaseAdminAuthHandler):
def get(self, protocol, record_id):
header = record.read_record_head(record_id)
if header is None:
return self.write_json(-3, '操作失败')
# ret = dict()
# ret['header'] = header
# return self.write_json(0, data=ret)
param = dict()
param['header'] = header
param['count'] = 0
param['op'] = list()
cmd_type = 0 # 0 = ssh, 1 = sftp
protocol = int(protocol)
if protocol == 1:
pass
elif protocol == 2:
record_path = os.path.join(get_cfg().core.replay_path, 'ssh', '{:06d}'.format(int(record_id)))
file_info = os.path.join(record_path, 'tp-ssh-cmd.txt')
try:
file = open(file_info, 'r')
data = file.readlines()
for i in range(len(data)):
if 0 == i:
cmd = data[i][22:-1]
if 'SFTP INITIALIZE' == cmd:
cmd_type = 1
continue
if cmd_type == 0:
param['op'].append({'t': data[i][1:20], 'c': data[i][22:-1]})
else:
cmd_info = data[i][22:-1].split(':')
if len(cmd_info) != 4:
continue
param['op'].append({'t': data[i][1:20], 'c': cmd_info[0], 'p1': cmd_info[2], 'p2': cmd_info[3]})
except:
pass
param['count'] = len(param['op'])
if cmd_type == 0:
self.render('log/record-ssh-cmd.mako', page_param=json.dumps(param))
else:
self.render('log/record-sftp-cmd.mako', page_param=json.dumps(param))
class RecordGetHeader(TPBaseAdminAuthJsonHandler):
def post(self):
args = self.get_argument('args', None)
if args is not None:
args = json.loads(args)
else:
return self.write_json(-1, '参数错误')
record_id = args['id']
header = record.read_record_head(record_id)
if header is None:
return self.write_json(-3, '操作失败')
ret = dict()
ret['header'] = header
return self.write_json(0, data=ret)
class RecordGetInfo(TPBaseAdminAuthJsonHandler):
def post(self):
args = self.get_argument('args', None)
if args is not None:
args = json.loads(args)
else:
return self.write_json(-1, '参数错误')
record_id = args['id']
file_id = args['file_id']
data = record.read_record_info(record_id, file_id)
if data is None:
return self.write_json(-3, '操作失败')
return self.write_json(0, data=data)
class DeleteLog(TPBaseAdminAuthJsonHandler):
# TODO: 用户可能会批量删除大量录像文件因此io操作可能会比较耗时这里应该改为异步方式。
def post(self):
args = self.get_argument('args', None)
if args is not None:
args = json.loads(args)
else:
return self.write_json(-1, '参数错误')
log_list = args['log_list']
if not record.delete_log(log_list):
return self.write_json(-3, '操作失败')
return self.write_json(0)
class LogList(TPBaseAdminAuthJsonHandler):
def post(self):
filter = dict()
order = dict()
order['name'] = 'host_id'
order['asc'] = True
limit = dict()
limit['page_index'] = 0
limit['per_page'] = 25
args = self.get_argument('args', None)
if args is not None:
args = json.loads(args)
tmp = list()
_filter = args['filter']
if _filter is not None:
for i in _filter:
if i == 'user_name':
_x = _filter[i].strip()
if _x == '全部':
tmp.append(i)
if i == 'search':
_x = _filter[i].strip()
if len(_x) == 0:
tmp.append(i)
continue
for i in tmp:
del _filter[i]
filter.update(_filter)
_limit = args['limit']
if _limit['page_index'] < 0:
_limit['page_index'] = 0
if _limit['per_page'] < 10:
_limit['per_page'] = 10
if _limit['per_page'] > 100:
_limit['per_page'] = 100
limit.update(_limit)
_order = args['order']
if _order is not None:
order['name'] = _order['k']
order['asc'] = _order['v']
total, log_list = user.get_log_list(filter, _limit)
ret = dict()
ret['page_index'] = limit['page_index']
ret['total'] = total
ret['data'] = log_list
return self.write_json(0, data=ret)

View File

@ -12,6 +12,8 @@ from app.base.controller import TPBaseHandler, TPBaseJsonHandler
from app.base.logger import *
from app.const import *
from app.model import syslog
from app.model import record
from app.base.core_server import core_service_async_post_http
class DoGetTimeHandler(TPBaseJsonHandler):
@ -21,16 +23,27 @@ class DoGetTimeHandler(TPBaseJsonHandler):
class ConfigHandler(TPBaseHandler):
@tornado.gen.coroutine
def get(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
if ret != TPE_OK:
return
cfg = get_cfg()
# core_detected = False
req = {'method': 'get_config', 'param': []}
_yr = core_service_async_post_http(req)
code, ret_data = yield _yr
if code != TPE_OK:
cfg.update_core(None)
else:
cfg.update_core(ret_data)
if not get_cfg().core.detected:
total_size = 0
free_size = 0
else:
# total_size, free_size = get_free_space_bytes(get_cfg().core.replay_path)
total_size, _, free_size = shutil.disk_usage(get_cfg().core.replay_path)
param = {
@ -182,46 +195,6 @@ class DoGetLogsHandler(TPBaseJsonHandler):
return self.write_json(0, data=ret)
class DoSendTestMailHandler(TPBaseJsonHandler):
@tornado.gen.coroutine
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
if ret != TPE_OK:
return
args = self.get_argument('args', None)
if args is None:
return self.write_json(TPE_PARAM)
try:
args = json.loads(args)
except:
return self.write_json(TPE_JSON_FORMAT)
try:
_server = args['server']
_port = int(args['port'])
_ssl = args['ssl']
_sender = args['sender']
_password = args['password']
_recipient = args['recipient']
except:
return self.write_json(TPE_PARAM)
code, msg = yield mail.tp_send_mail(
_recipient,
'您好!\n\n这是一封测试邮件,仅用于验证系统的邮件发送模块工作是否正常。\n\n请忽略本邮件。',
subject='测试邮件',
sender='Teleport Server <{}>'.format(_sender),
server=_server,
port=_port,
use_ssl=_ssl,
username=_sender,
password=_password
)
self.write_json(code, message=msg)
class DoSaveCfgHandler(TPBaseJsonHandler):
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
@ -285,7 +258,74 @@ class DoSaveCfgHandler(TPBaseJsonHandler):
else:
return self.write_json(err)
if 'storage' in args:
_cfg = args['storage']
_keep_log = _cfg['keep_log']
_keep_record = _cfg['keep_record']
_cleanup_hour = _cfg['cleanup_hour']
_cleanup_minute = _cfg['cleanup_minute']
err = system_model.save_config(self, '更新存储策略设置', 'storage', _cfg)
if err == TPE_OK:
get_cfg().sys.storage.keep_log = _keep_log
get_cfg().sys.storage.keep_record = _keep_record
get_cfg().sys.storage.cleanup_hour = _cleanup_hour
get_cfg().sys.storage.cleanup_minute = _cleanup_minute
else:
return self.write_json(err)
return self.write_json(TPE_OK)
except:
log.e('\n')
self.write_json(TPE_FAILED)
class DoSendTestMailHandler(TPBaseJsonHandler):
@tornado.gen.coroutine
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
if ret != TPE_OK:
return
args = self.get_argument('args', None)
if args is None:
return self.write_json(TPE_PARAM)
try:
args = json.loads(args)
except:
return self.write_json(TPE_JSON_FORMAT)
try:
_server = args['server']
_port = int(args['port'])
_ssl = args['ssl']
_sender = args['sender']
_password = args['password']
_recipient = args['recipient']
except:
return self.write_json(TPE_PARAM)
code, msg = yield mail.tp_send_mail(
_recipient,
'您好!\n\n这是一封测试邮件,仅用于验证系统的邮件发送模块工作是否正常。\n\n请忽略本邮件。',
subject='测试邮件',
sender='Teleport Server <{}>'.format(_sender),
server=_server,
port=_port,
use_ssl=_ssl,
username=_sender,
password=_password
)
self.write_json(code, message=msg)
class DoCleanupStorageHandler(TPBaseJsonHandler):
@tornado.gen.coroutine
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
if ret != TPE_OK:
return
code, msg = yield record.cleanup_storage(self)
self.write_json(code, data=msg)

View File

@ -11,6 +11,7 @@ from app.base.configs import get_cfg
from app.base.db import get_db, SQL
from app.base.logger import log
from app.base.utils import tp_timestamp_utc_now
import tornado.gen
def get_records(sql_filter, sql_order, sql_limit, sql_restrict, sql_exclude):
@ -253,66 +254,140 @@ def delete_log(log_list):
def session_fix():
try:
db = get_db()
db = get_db()
sql_list = []
sql_list = []
sql = 'UPDATE `{dbtp}record` SET state={new_state}, time_end={time_end} WHERE state={old_state};' \
''.format(dbtp=db.table_prefix, new_state=TP_SESS_STAT_ERR_RESET, old_state=TP_SESS_STAT_RUNNING, time_end=tp_timestamp_utc_now())
sql_list.append(sql)
sql = 'UPDATE `{dbtp}record` SET state={new_state}, time_end={time_end} WHERE state={old_state};' \
''.format(dbtp=db.table_prefix, new_state=TP_SESS_STAT_ERR_RESET, old_state=TP_SESS_STAT_RUNNING, time_end=tp_timestamp_utc_now())
sql_list.append(sql)
# if not db.exec(sql):
# ret = False
sql = 'UPDATE `{dbtp}record` SET state={new_state},time_end={time_end} WHERE state={old_state};' \
''.format(dbtp=db.table_prefix, new_state=TP_SESS_STAT_ERR_START_RESET, old_state=TP_SESS_STAT_STARTED, time_end=tp_timestamp_utc_now())
sql_list.append(sql)
return db.transaction(sql_list)
# if not db.exec(sql):
# ret = False
# return ret
except:
log.e('\n')
return False
sql = 'UPDATE `{dbtp}record` SET state={new_state},time_end={time_end} WHERE state={old_state};' \
''.format(dbtp=db.table_prefix, new_state=TP_SESS_STAT_ERR_START_RESET, old_state=TP_SESS_STAT_STARTED, time_end=tp_timestamp_utc_now())
sql_list.append(sql)
return db.transaction(sql_list)
def session_begin(sid, user_id, host_id, acc_id, user_username, acc_username, host_ip, conn_ip, conn_port, client_ip, auth_type, protocol_type, protocol_sub_type):
try:
db = get_db()
sql = 'INSERT INTO `{}record` (sid,user_id,host_id,acc_id,state,user_username,host_ip,conn_ip,conn_port,client_ip,acc_username,auth_type,protocol_type,protocol_sub_type,time_begin,time_end) ' \
'VALUES ("{sid}",{user_id},{host_id},{acc_id},0,"{user_username}","{host_ip}","{conn_ip}",{conn_port},"{client_ip}","{acc_username}",{auth_type},{protocol_type},{protocol_sub_type},{time_begin},0)' \
';'.format(db.table_prefix,
sid=sid, user_id=user_id, host_id=host_id, acc_id=acc_id, user_username=user_username, host_ip=host_ip, conn_ip=conn_ip, conn_port=conn_port,
client_ip=client_ip, acc_username=acc_username, auth_type=auth_type, protocol_type=protocol_type, protocol_sub_type=protocol_sub_type,
time_begin=tp_timestamp_utc_now())
db = get_db()
sql = 'INSERT INTO `{}record` (sid,user_id,host_id,acc_id,state,user_username,host_ip,conn_ip,conn_port,client_ip,acc_username,auth_type,protocol_type,protocol_sub_type,time_begin,time_end) ' \
'VALUES ("{sid}",{user_id},{host_id},{acc_id},0,"{user_username}","{host_ip}","{conn_ip}",{conn_port},"{client_ip}","{acc_username}",{auth_type},{protocol_type},{protocol_sub_type},{time_begin},0)' \
';'.format(db.table_prefix,
sid=sid, user_id=user_id, host_id=host_id, acc_id=acc_id, user_username=user_username, host_ip=host_ip, conn_ip=conn_ip, conn_port=conn_port,
client_ip=client_ip, acc_username=acc_username, auth_type=auth_type, protocol_type=protocol_type, protocol_sub_type=protocol_sub_type,
time_begin=tp_timestamp_utc_now())
ret = db.exec(sql)
if not ret:
return TPE_DATABASE, 0
record_id = db.last_insert_id()
if record_id == -1:
return TPE_DATABASE, 0
else:
return TPE_OK, record_id
except:
log.e('\n')
ret = db.exec(sql)
if not ret:
return TPE_DATABASE, 0
record_id = db.last_insert_id()
if record_id == -1:
return TPE_DATABASE, 0
else:
return TPE_OK, record_id
def session_update(record_id, state):
try:
db = get_db()
sql = 'UPDATE `{}record` SET state={} WHERE id={};'.format(db.table_prefix, int(state), int(record_id))
return db.exec(sql)
except:
return False
db = get_db()
sql = 'UPDATE `{}record` SET state={} WHERE id={};'.format(db.table_prefix, int(state), int(record_id))
return db.exec(sql)
def session_end(record_id, ret_code):
try:
db = get_db()
sql = 'UPDATE `{}record` SET state={}, time_end={} WHERE id={};'.format(db.table_prefix, int(ret_code), tp_timestamp_utc_now(), int(record_id))
return db.exec(sql)
except:
return False
db = get_db()
sql = 'UPDATE `{}record` SET state={}, time_end={} WHERE id={};'.format(db.table_prefix, int(ret_code), tp_timestamp_utc_now(), int(record_id))
return db.exec(sql)
@tornado.gen.coroutine
def cleanup_storage(handler):
# storage config
sto = get_cfg().sys.storage
db = get_db()
_now = tp_timestamp_utc_now()
msg = []
have_error = False
sto.keep_log = 5
sto.keep_record = 5
s = SQL(db)
chk_time = _now - sto.keep_log * 24 * 60 * 60
if sto.keep_log > 0:
# find out all sys-log to be remove
s.select_from('syslog', ['id'], alt_name='s')
s.where('s.log_time<{chk_time}'.format(chk_time=chk_time))
err = s.query()
if err != TPE_OK:
have_error = True
msg.append('清理系统日志时发生错误:无法获取系统日志信息!')
# return err, msg
else:
removed_log = len(s.recorder)
if 0 == removed_log:
msg.append('没有满足条件的系统日志需要清除!')
else:
s.reset().delete_from('syslog').where('log_time<{chk_time}'.format(chk_time=chk_time))
err = s.query()
if err != TPE_OK:
have_error = True
msg.append('清理系统日志时发生错误:无法清除指定的系统日志!')
else:
msg.append('{} 条系统日志已清除!'.format(removed_log))
if sto.keep_record > 0:
core_cfg = get_cfg().core
if not core_cfg.detected:
have_error = True
msg.append('清除指定会话录像失败:未能检测到核心服务!')
else:
replay_path = core_cfg.replay_path
if not os.path.exists(replay_path):
have_error = True
msg.append('清除指定会话录像失败:会话录像路径不存在({}'.format(replay_path))
else:
# find out all record to be remove
s.reset().select_from('record', ['id', 'protocol_type'], alt_name='r')
s.where('r.time_begin<{chk_time}'.format(chk_time=chk_time))
err = s.query()
if err != TPE_OK:
have_error = True
msg.append('清除指定会话录像失败:无法获取会话录像信息!')
elif len(s.recorder) == 0:
msg.append('没有满足条件的会话录像需要清除!')
else:
record_removed = 0
for r in s.recorder:
if r.protocol_type == TP_PROTOCOL_TYPE_RDP:
path_remove = os.path.join(replay_path, 'rdp', '{:09d}'.format(r.id))
elif r.protocol_type == TP_PROTOCOL_TYPE_SSH:
path_remove = os.path.join(replay_path, 'ssh', '{:09d}'.format(r.id))
elif r.protocol_type == TP_PROTOCOL_TYPE_TELNET:
path_remove = os.path.join(replay_path, 'telnet', '{:09d}'.format(r.id))
else:
have_error = True
msg.append('会话录像记录编号 {},未知远程访问协议!'.format(r.id))
continue
if os.path.exists(path_remove):
print('remove path', path_remove)
try:
shutil.rmtree(path_remove)
except:
have_error = True
msg.append('会话录像记录 {} 清除失败,无法删除目录 {}'.format(r.id, path_remove))
ss = SQL(db)
ss.delete_from('record').where('id={rid}'.format(rid=r.id))
ss.exec()
record_removed += 1
msg.append('{} 条会话录像数据已清除!'.format(record_removed))
if have_error:
return TPE_FAILED, msg
else:
return TPE_OK, msg