Files
yakpanel-core/class_v2/btdockerModelV2/dkgroupModel_.py

460 lines
18 KiB
Python
Raw Normal View History

2026-04-07 02:04:22 +05:30
# coding: utf-8
# -------------------------------------------------------------------
# YakPanel
# -------------------------------------------------------------------
# Copyright (c) 2015-2099 YakPanel(www.yakpanel.com) All rights reserved.
# -------------------------------------------------------------------
# Author: zhengweibiao
# -------------------------------------------------------------------
# ------------------------------
# 容器项目编排
# ------------------------------
import os, sys, re, json, shutil, psutil, time
import datetime
import public
from btdockerModelV2.containerModel import main as docker
import subprocess
class main():
next_id = 1 # 将 next_id 设为类变量,而不是实例变量
def __init__(self):
# self.next_id = 1
pass
def load_project_data(self):
json_file = "/www/server/panel/class_v2/btdockerModelV2/docker_project_groups.json"
try:
with open(json_file, 'r') as f:
return json.load(f)
except FileNotFoundError:
data = []
with open(json_file, 'w') as f:
json.dump(data, f)
return data
except Exception as e:
return None
def write_to_json(self, data):
json_file = "/www/server/panel/class_v2/btdockerModelV2/docker_project_groups.json"
try:
with open(json_file, 'w') as f:
json.dump(data, f)
return True
except Exception as e:
print("写入失败!{}".format(e))
return False
def get_project_groups(self, get):
data = self.load_project_data()
if data is None:
return public.returnMsg(False, "获取配置文件失败")
# 获取项目列表
project_list = docker().get_list(get)
# 更新每个项目组的状态
for group in data:
# 检查项目排序是否为空
if not group['order']:
group['status'] = 0 # 如果项目排序为空,状态为停止
continue
all_running = True # 假设所有的项目都在运行
for project in group['projects']:
for p in project_list['container_list']:
if p['name'] == project['project_name']:
if p['status']!="running": # 如果项目没有运行
all_running = False
break
if not all_running:
break
if all_running:
group['status'] = 1 # 如果所有的项目都在运行,状态为启动
else:
group['status'] = 0
return public.returnMsg(True, data)
def get_group_data(self, get):
try:
data = self.load_project_data()
if data is None:
return None, public.returnMsg(False, "获取配置文件失败!")
project_list = docker().get_list(get)
for group in data:
if group['id'] == int(get.id):
for project in group['projects']:
print(project)
# print(project_list['container_list'])
for p in project_list['container_list']:
if p['name'] == project['project_name']:
print(3333)
print(p)
project['status'] = p['status']
return group, None
return None, public.ReturnMsg(False, "项目不存在!")
except Exception as e:
return None, public.returnMsg(False, "获取失败!" + str(e))
def get_project_details(self, get):
print(33333)
group, error_msg = self.get_group_data(get)
if error_msg:
return error_msg
group['projects'].sort(
key=lambda x: group['order'].index(x['project_name']))
return public.returnMsg(True, group['projects'])
def get_project_group_details(self, get):
group, error_msg = self.get_group_data(get)
if error_msg:
return error_msg
return public.returnMsg(True, group)
def add_project_group(self, get):
try:
data = self.load_project_data()
if data is None:
return public.returnMsg(False, "获取配置文件失败")
# 检查是否已存在
for group in data:
if group['group_name'] == get.group_name:
return public.returnMsg(False, "项目已存在!")
# 添加新的项目
new_group = {
"id": self.next_id, # 使用 next_id 作为新的 id
"group_name": get.group_name,
# "status": 0,
"interval": 30,
"projects": [],
"order": [],
}
data.append(new_group)
# 更新 next_id
main.next_id += 1
if not self.write_to_json(data):
return public.returnMsg(False, "写入失败!")
return public.returnMsg(True, "项目添加成功!")
except Exception as e:
return public.returnMsg(False, "添加失败!" + str(e))
def edit_project_order(self, get):
try:
data = self.load_project_data()
if data is None:
return public.returnMsg(False, "获取配置文件失败")
# 找到指定的项目组
for group in data:
if group['id']==int(get.id):
new_order=get.order.split(',')
if sorted(new_order) != sorted(group['order']):
return public.returnMsg(False, "无效的容器顺序!")
group['order']=new_order
if not self.write_to_json(data):
return public.returnMsg(False, "写入失败!")
return public.returnMsg(True,"容器顺序修改成功!")
return public.returnMsg(False,"项目不存在!")
except Exception as e:
return public.returnMsg(False,"修改失败:"+str(e))
def edit_group_interval(self, get):
try:
data = self.load_project_data()
if data is None:
return public.returnMsg(False, "获取配置文件失败")
# 找到指定的项目
for group in data:
if group['id'] == int(get.id):
# 检查新的项目顺序是否有效
group['interval'] = get.interval
break
else:
return public.returnMsg(False, "项目不存在!")
if not self.write_to_json(data):
return public.returnMsg(False, "写入失败!")
return public.returnMsg(True, "项目时间间隔修改成功!")
except Exception as e:
return public.returnMsg(False, "修改失败!" + str(e))
def start_projects_in_order(self, get):
try:
data = self.load_project_data()
if data is None:
return public.returnMsg(False, "获取配置文件失败")
project_list=docker().get_list(get)['container_list']
for group in data:
if group['id']==int(get.id):
# 如果pid存在并且进程仍在运行那么就不允许用户再次启动项目
if 'start_pid' in group and self.is_process_running(group['start_pid']):
return public.returnMsg(False,"正在依次启动容器中!")
project_order=group['order']
running_projects=[project for project in project_order if self.is_project_running(project,project_list)]
if running_projects and not get.get("force_stop",False):
return public.returnMsg(False,"以下容器正在运行:{}。是否允许先强制停止再启动?您也可以选择自己手动停止运行中的容器!".format(",".join(running_projects)))
with open('/dev/null','w') as devnull:
process=subprocess.Popen(['btpython','/www/server/panel/script/set_docker_project_groups.py','--id',str(group['id']),"--action","start"],stdout=devnull,stderr=devnull)
pid=process.pid
group['start_pid']=pid
if not self.write_to_json(data):
return public.returnMsg(False, "写入失败!")
return public.returnMsg(True, "开始依次启动容器!")
except Exception as e:
return public.returnMsg(False, "启动失败!"+str(e))
def is_process_running(self,pid):
try:
os.kill(pid,0)
except OSError:
return False
else:
return True
def is_project_running(self,project_name,project_list):
for project in project_list:
if project['name']==project_name and project['status']=="running":
return True
return False
def stop_projects_in_order(self, get):
try:
data = self.load_project_data()
if data is None:
return public.returnMsg(False, "获取配置文件失败")
for group in data:
if group['id']==int(get.id):
# 如果pid存在并且进程仍在运行那么就不允许用户再次停stop_pid止项目
if 'stop_pid' in group and self.is_process_running(group['stop_pid']):
return public.returnMsg(False,"正在依次停止容器中!")
with open("/dev/null","w") as devnull:
process=subprocess.Popen(['btpython','/www/server/panel/script/set_docker_project_groups.py','--id',str(group['id']),"--action","stop"],stdout=devnull,stderr=devnull)
pid=process.pid
group['stop_pid']=pid
if not self.write_to_json(data):
return public.returnMsg(False, "写入失败!")
return public.returnMsg(True,"容器开始按顺序停止")
except Exception as e:
return public.returnMsg(False, "停止失败!" + str(e))
def start_group(self, args_id):
try:
get = public.dict_obj()
data = self.load_project_data()
if data is None:
return public.returnMsg(False, "获取配置文件失败")
# 找到指定的项目
for group in data:
if group['id'] == int(args_id):
# 获取项目排序
project_order = group['order']
# 停止所有项目
for project_name in project_order:
container_id = None
for project in group['projects']:
if project['project_name'] == project_name:
container_id = project['project_id']
break
if container_id:
# print()
# docker().set_container_status(public.dict_obj({
# "id": container_id,
# "status": "stop"
# }))
print(33333333333333)
get.status = "stop"
get.id = container_id
docker().set_container_status(get)
# time.sleep(30)
# 依次启动项目
for project_name in project_order:
container_id = None
for project in group['projects']:
if project['project_name'] == project_name:
container_id = project['project_id']
break
if container_id:
# print()
# docker().set_container_status(public.dict_obj({
# "id": container_id,
# "status": "stop"
# }))
get.status = "start"
get.id = container_id
start_result=docker().set_container_status(get)
if not start_result['status']:
return start_result # 如果启动失败,立即返回错误信息
# 暂停指定的时间间隔
time.sleep(int(group['interval']))
if not self.is_process_running(group['pid']):
# 删除pid
del group['pid']
if not self.write_to_json(data):
return public.returnMsg(False, "写入失败!")
except Exception as e:
print("启动失败!" + str(e))
def stop_group(self, args_id):
try:
get = public.dict_obj()
data = self.load_project_data()
if data is None:
return public.returnMsg(False, "获取配置文件失败")
# 找到指定的项目
for group in data:
if group['id'] == int(args_id):
# 获取项目排序
project_order = group['order']
# 停止所有项目
for project_name in project_order:
container_id = None
for project in group['projects']:
if project['project_name'] == project_name:
container_id = project['project_id']
break
if container_id:
get.status = "stop"
get.id = container_id
docker().set_container_status(get)
except Exception as e:
print("启动失败!" + str(e))
def modify_group_status(self, get):
group_ids=[int(id) for id in get.id.split(",")]
for group_id in group_ids:
get.id=group_id
if get.status=="1":
return self.start_projects_in_order(get)
elif get.status=="0":
return self.stop_projects_in_order(get)
else:
return public.returnMsg(False,"无效的状态!")
def add_project_to_group(self, get):
try:
data = self.load_project_data()
if data is None:
return public.returnMsg(False, "获取配置文件失败")
# 检查项目是否已被其他项目组添加
for group in data:
for project in group['projects']:
if project['project_name']==get.project_name:
return public.returnMsg(False,"容器 {} 已经被项目组 {} 添加了!".format(get.project_name,group['group_name']))
for group in data:
if group['id']==int(get.id):
new_project={
"project_id":get.project_id,
"project_name":get.project_name,
}
group['projects'].append(new_project)
group['order'].append(get.project_name)
break
if not self.write_to_json(data):
return public.returnMsg(False, "写入失败!")
return public.returnMsg(True, "容器添加成功!")
except Exception as e:
return public.returnMsg(False, "添加失败!" + str(e))
def remove_project_from_group(self, get):
try:
data = self.load_project_data()
if data is None:
return public.returnMsg(False, "获取配置文件失败")
# 将 get.project_name 分割成一个列表
project_names=get.project_name.split(",")
# 找到指定的项目
for group in data:
if group['id']==int(get.id):
# 删除指定的项目组
group['projects']=[project for project in group['projects'] if project['project_name'] not in project_names]
# 同时更新order列表移除已删除的项目名称
group['order'] = [project_name for project_name in group['order'] if project_name not in project_names]
break
else:
return public.returnMsg(False,"项目不存在!")
# 将更新后的数据写回文件
if not self.write_to_json(data):
return public.returnMsg(False, "写入失败!")
return public.returnMsg(True, "容器删除成功!")
except Exception as e:
return public.returnMsg(False, "删除失败!" + str(e))
def delete_project_group(self, get):
try:
data = self.load_project_data()
if data is None:
return public.returnMsg(False, "获取配置文件失败")
# 将 get.id 分割成一个列表
group_ids=[int(id) for id in get.id.split(",")]
# 找到并删除指定的项目
data=[group for group in data if group['id'] not in group_ids]
# 将更新后的数据写回文件
if not self.write_to_json(data):
return public.returnMsg(False, "写入失败!")
return public.returnMsg(True, "项目删除成功!")
except Exception as e:
return public.returnMsg(False, "删除失败!" + str(e))