Files
yakpanel-core/class_v2/btdockerModelV2/dkgroupModel_.py
2026-04-07 02:04:22 +05:30

460 lines
18 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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))