Files
djangohelper/gunicorn_tab.py

298 lines
12 KiB
Python
Raw Normal View History

import os
from loguru import logger
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
QPushButton, QComboBox, QMessageBox, QTextEdit,
QGroupBox, QGridLayout, QProgressBar)
from PySide6.QtCore import Qt
from threads import (GunicornInstallThread, GunicornTestThread,
UploadGunicornServiceThread, ManageGunicornServiceThread)
class GunicornTab(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.parent = parent
self.init_ui()
def init_ui(self):
layout = QVBoxLayout()
# Gunicorn配置组
config_group = QGroupBox("Gunicorn配置")
config_layout = QGridLayout()
config_layout.addWidget(QLabel("Django项目路径:"), 0, 0)
self.django_path_input = QLineEdit()
self.django_path_input.setPlaceholderText("/home/user/django_project")
config_layout.addWidget(self.django_path_input, 0, 1)
config_layout.addWidget(QLabel("服务名称:"), 1, 0)
self.service_name_input = QLineEdit("django_gunicorn")
config_layout.addWidget(self.service_name_input, 1, 1)
config_layout.addWidget(QLabel("端口:"), 2, 0)
self.port_input = QLineEdit("8000")
config_layout.addWidget(self.port_input, 2, 1)
config_layout.addWidget(QLabel("工作进程数:"), 3, 0)
self.workers_input = QLineEdit("3")
config_layout.addWidget(self.workers_input, 3, 1)
self.load_config_btn = QPushButton("加载配置")
self.load_config_btn.clicked.connect(self.load_gunicorn_config)
config_layout.addWidget(self.load_config_btn, 4, 1)
config_group.setLayout(config_layout)
layout.addWidget(config_group)
# Gunicorn操作组
gunicorn_group = QGroupBox("Gunicorn操作")
gunicorn_layout = QGridLayout()
self.install_gunicorn_btn = QPushButton("安装Gunicorn")
self.install_gunicorn_btn.clicked.connect(self.install_gunicorn)
gunicorn_layout.addWidget(self.install_gunicorn_btn, 0, 0)
self.test_gunicorn_btn = QPushButton("测试Gunicorn")
self.test_gunicorn_btn.clicked.connect(self.test_gunicorn)
gunicorn_layout.addWidget(self.test_gunicorn_btn, 0, 1)
self.upload_service_btn = QPushButton("上传服务文件")
self.upload_service_btn.clicked.connect(self.upload_service_file)
gunicorn_layout.addWidget(self.upload_service_btn, 1, 0)
self.start_service_btn = QPushButton("启动服务")
self.start_service_btn.clicked.connect(lambda: self.manage_service("start"))
gunicorn_layout.addWidget(self.start_service_btn, 1, 1)
self.stop_service_btn = QPushButton("停止服务")
self.stop_service_btn.clicked.connect(lambda: self.manage_service("stop"))
gunicorn_layout.addWidget(self.stop_service_btn, 2, 0)
self.restart_service_btn = QPushButton("重启服务")
self.restart_service_btn.clicked.connect(lambda: self.manage_service("restart"))
gunicorn_layout.addWidget(self.restart_service_btn, 2, 1)
self.status_service_btn = QPushButton("查看服务状态")
self.status_service_btn.clicked.connect(lambda: self.manage_service("status"))
gunicorn_layout.addWidget(self.status_service_btn, 3, 0)
self.enable_service_btn = QPushButton("启用开机自启")
self.enable_service_btn.clicked.connect(lambda: self.manage_service("enable"))
gunicorn_layout.addWidget(self.enable_service_btn, 3, 1)
gunicorn_group.setLayout(gunicorn_layout)
layout.addWidget(gunicorn_group)
# 服务文件编辑器
service_group = QGroupBox("Gunicorn服务文件")
service_layout = QVBoxLayout()
self.service_editor = QTextEdit()
self.service_editor.setPlaceholderText("Gunicorn服务文件内容将在这里显示...")
service_layout.addWidget(self.service_editor)
service_group.setLayout(service_layout)
layout.addWidget(service_group)
# 操作输出
output_group = QGroupBox("操作输出")
output_layout = QVBoxLayout()
self.output_text = QTextEdit()
self.output_text.setReadOnly(True)
self.output_text.setPlaceholderText("操作结果将在这里显示...")
output_layout.addWidget(self.output_text)
# 进度条
self.progress_bar = QProgressBar()
self.progress_bar.setVisible(False)
output_layout.addWidget(self.progress_bar)
output_group.setLayout(output_layout)
layout.addWidget(output_group)
layout.addStretch()
self.setLayout(layout)
# 加载Gunicorn配置
self.load_gunicorn_config()
def load_gunicorn_config(self):
if self.parent and hasattr(self.parent, 'server_connection_tab'):
django_path = self.parent.server_connection_tab.django_path_input.text()
self.django_path_input.setText(django_path)
# 生成默认的服务文件内容
service_name = self.service_name_input.text()
port = self.port_input.text()
workers = self.workers_input.text()
service_content = self.generate_service_file(service_name, django_path, port, workers)
self.service_editor.setText(service_content)
def generate_service_file(self, service_name, django_path, port, workers):
return f"""[Unit]
Description={service_name} daemon
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory={django_path}
ExecStart=/usr/local/bin/gunicorn --workers {workers} --bind 0.0.0.0:{port} {os.path.basename(django_path)}.wsgi:application
[Install]
WantedBy=multi-user.target
"""
def check_ssh_connection(self):
if not self.parent or not self.parent.ssh_client:
QMessageBox.warning(self, "警告", "请先连接服务器")
return False
return True
def install_gunicorn(self):
if not self.check_ssh_connection():
return
self.output_text.append("正在安装Gunicorn...")
self.install_gunicorn_btn.setEnabled(False)
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
# 获取密码
password = None
if self.parent and hasattr(self.parent, 'server_connection_tab'):
password = self.parent.server_connection_tab.password_input.text()
self.gunicorn_install_thread = GunicornInstallThread(self.parent.ssh_client, password)
self.gunicorn_install_thread.progress_updated.connect(self.update_progress)
self.gunicorn_install_thread.result_ready.connect(self.on_install_gunicorn_result)
self.gunicorn_install_thread.start()
def update_progress(self, value):
self.progress_bar.setValue(value)
def on_install_gunicorn_result(self, success, message):
self.install_gunicorn_btn.setEnabled(True)
self.progress_bar.setVisible(False)
if success:
self.output_text.append(f"Gunicorn安装成功: {message}")
logger.info(f"Gunicorn安装成功: {message}")
else:
self.output_text.append(f"Gunicorn安装失败: {message}")
logger.error(f"Gunicorn安装失败: {message}")
def test_gunicorn(self):
if not self.check_ssh_connection():
return
django_path = self.django_path_input.text().strip()
if not django_path:
QMessageBox.warning(self, "警告", "请输入Django项目路径")
return
self.output_text.append(f"正在测试Gunicorn {django_path}...")
self.test_gunicorn_btn.setEnabled(False)
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
self.gunicorn_test_thread = GunicornTestThread(self.parent.ssh_client, django_path)
self.gunicorn_test_thread.progress_updated.connect(self.update_progress)
self.gunicorn_test_thread.result_ready.connect(self.on_test_gunicorn_result)
self.gunicorn_test_thread.start()
def on_test_gunicorn_result(self, success, message):
self.test_gunicorn_btn.setEnabled(True)
self.progress_bar.setVisible(False)
if success:
self.output_text.append(f"Gunicorn测试成功: {message}")
logger.info(f"Gunicorn测试成功: {message}")
else:
self.output_text.append(f"Gunicorn测试失败: {message}")
logger.error(f"Gunicorn测试失败: {message}")
def upload_service_file(self):
if not self.check_ssh_connection():
return
service_name = self.service_name_input.text().strip()
service_content = self.service_editor.toPlainText()
if not service_name or not service_content:
QMessageBox.warning(self, "警告", "请输入服务名称并编辑服务文件内容")
return
self.output_text.append(f"正在上传服务文件 {service_name}...")
self.upload_service_btn.setEnabled(False)
# 获取密码
password = None
if self.parent and hasattr(self.parent, 'server_connection_tab'):
password = self.parent.server_connection_tab.password_input.text()
self.upload_thread = UploadGunicornServiceThread(self.parent.ssh_client, service_name, service_content, password)
self.upload_thread.result_ready.connect(self.on_upload_service_result)
self.upload_thread.start()
def on_upload_service_result(self, success, message):
self.upload_service_btn.setEnabled(True)
if success:
self.output_text.append(f"服务文件上传成功: {message}")
logger.info(f"服务文件上传成功: {message}")
else:
self.output_text.append(f"服务文件上传失败: {message}")
logger.error(f"服务文件上传失败: {message}")
def manage_service(self, action):
if not self.check_ssh_connection():
return
service_name = self.service_name_input.text().strip()
if not service_name:
QMessageBox.warning(self, "警告", "请输入服务名称")
return
self.output_text.append(f"正在执行服务 {action} 操作...")
# 禁用所有服务管理按钮
buttons = [self.start_service_btn, self.stop_service_btn, self.restart_service_btn,
self.status_service_btn, self.enable_service_btn]
for btn in buttons:
btn.setEnabled(False)
# 获取密码
password = None
if self.parent and hasattr(self.parent, 'server_connection_tab'):
password = self.parent.server_connection_tab.password_input.text()
self.manage_thread = ManageGunicornServiceThread(self.parent.ssh_client, service_name, action, password)
self.manage_thread.result_ready.connect(lambda s, m: self.on_manage_service_result(s, m, buttons))
self.manage_thread.start()
def on_manage_service_result(self, success, message, buttons):
# 重新启用所有服务管理按钮
for btn in buttons:
btn.setEnabled(True)
if success:
self.output_text.append(f"服务操作成功: {message}")
logger.info(f"服务操作成功: {message}")
else:
self.output_text.append(f"服务操作失败: {message}")
logger.error(f"服务操作失败: {message}")
def on_server_changed(self):
self.load_gunicorn_config()
def check_service_status(self):
if not self.check_ssh_connection():
return
service_name = self.service_name_input.text().strip()
if not service_name:
return
self.manage_service("status")