# coding: utf-8 # ------------------------------------------------------------------- # YakPanel # ------------------------------------------------------------------- # Copyright (c) 2015-2099 YakPanel(www.yakpanel.com) All rights reserved. # ------------------------------------------------------------------- # Author: # ------------------------------------------------------------------- # ------------------------------ # 容器启动顺序 # ------------------------------ import copy import json import os.path import sys import time import subprocess import psutil if "/www/server/panel/class" not in sys.path: sys.path.insert(0, "/www/server/panel/class") import public from btdockerModelV2.containerModel import main as docker from btdockerModelV2.dockerSock import container from btdockerModelV2 import dk_public as dp class main(): GROUP_PATH = "/www/server/panel/data/docker_groups.json" def __init__(self): if not os.path.exists(self.GROUP_PATH): public.WriteFile(self.GROUP_PATH, "[]") # 添加组信息 def add_group(self, get): try: if not hasattr(get, "group_name"): return public.return_message(-1, 0, public.lang("Missing parameters name")) if not hasattr(get, "container_info"): return public.return_message(-1, 0, public.lang("Missing parameters container_info")) interval = 30 if not get.interval else int(get.interval) container_info = get.container_info.split(',') if get.container_info else [] from uuid import uuid4 group_id = uuid4().hex[::2] file_data = self.__readFile() for group in file_data: if group["group_name"] == get.group_name.strip(): return public.return_message(-1, 0, public.lang("The grouping already exists")) for temp in container_info: if temp in group["order"]: return public.return_message(-1, 0, public.lang("Container {} has been added by group {}!",temp, group['group_name'])) pdata = { "id": group_id, "group_name": get.group_name.strip(), "interval": interval, "order": container_info, } file_data.append(pdata) public.writeFile(self.GROUP_PATH, json.dumps(file_data)) return public.return_message(0, 0, public.lang("Added successfully")) except Exception as e: return public.return_message(-1, 0, public.lang("Add failed:{}",e)) # 编辑组信息 def update_group(self, get): try: if not hasattr(get, "id"): return public.return_message(-1, 0, public.lang("Missing parameters id")) interval = 30 if not get.interval else int(get.interval) container_info = get.container_info.split(",") if get.container_info else [] file_data = self.__readFile() for group in file_data: if group["id"] == get.id.strip(): group["group_name"] = get.group_name.strip() group["interval"] = interval group["order"] = container_info break public.writeFile(self.GROUP_PATH, json.dumps(file_data)) return public.return_message(0, 0, public.lang("Edit Success")) except Exception as e: return public.return_message(-1, 0, public.lang("Edit failed:{}",e)) # 删除组信息 def del_group(self, get): try: if not hasattr(get, "id"): return public.return_message(-1, 0, public.lang("Missing parameters id")) file_data = self.__readFile() for index, data in enumerate(file_data): if data["id"] == get.id.strip(): del file_data[index] break public.writeFile(self.GROUP_PATH, json.dumps(file_data)) return public.return_message(0, 0, public.lang("Deleted successfully")) except Exception as e: return public.return_message(-1, 0, public.lang("Deletion failed:{}",e)) # 获取组信息 def get_group(self, get): file_data = self.__readFile() # 拿配置文件数据 for group in file_data: group["status"] = 0 # 标记文件 status_file = "/tmp/{}.json".format(group["id"]) try: info = json.loads(public.readFile(status_file)) except: info = { "group_id": group["id"], "status": 0, "start_failed": "" } group["status"] = info["status"] group["start_failed"] = info["start_failed"] return public.returnResult(True, data=file_data) # 从组启动/停止容器 def group_status(self, group_id, status): sk_container = container.dockerContainer() container_list = sk_container.get_container() if status not in ["start", "stop"]: return public.return_message(-1, 0, public.lang("status Parameter error")) # 状态启动中 status_file = "/tmp/{}.json".format(group_id) group_data = { "group_id": group_id, "status": 0, "start_failed": "" } if status == "start": group_data["status"] = 2 else: group_data["status"] = 4 public.writeFile(status_file, json.dumps(group_data)) try: get = public.dict_obj() file_data = self.__readFile() # 获取对应ID的信息 group_info = self.__group_info(group_id, file_data) if group_info: # 获取容器列表名称列表 container_order = group_info["order"] # 依次启动容器 for containers in container_order: get.id = containers get.status = status # 顺序开启并且容器已经开启了 if status == "start" and self.__is_running(containers, container_list): continue result = docker().set_container_status(get) if result["status"] == -1 and status == "start": # 写入失败标记文件 # 启动失败直接返回 group_data["status"] = 3 # 用于记录启动失败的容器 group_data["start_failed"] = containers public.writeFile(status_file, json.dumps(group_data)) return public.return_message(-1, 0, public.lang("Container [{}] operation failed",containers)) # 启动时间间隔 if len(container_order) > 1: time.sleep(int(group_info["interval"])) if status == "start": group_data["status"] = 1 elif status == "stop": group_data["status"] = 0 public.writeFile(status_file, json.dumps(group_data)) return public.return_message(0, 0, public.lang("Operation successful")) except Exception as e: return public.return_message(-1, 0, public.lang("Operation failed:{}",e)) # 脚本调用 def script_group(self, get): pid_file = "/tmp/docker_groups.pid" try: p = psutil.Process(public.readFile(pid_file)) if p.is_running(): return "The operation is running. Please wait for the previous operation to complete." except: pass if os.path.exists(pid_file): os.remove(pid_file) file_data = self.__readFile() for group in file_data: if group['id'] == get.id.strip(): public.ExecShell( "nohup /www/server/panel/pyenv/bin/python3 /www/server/panel/script/set_docker_groups.py {} {} &> /tmp/docker_groups.log & \n" "echo $! > {} ".format(group['id'], get.status, pid_file) ) return public.return_message(0, 0, public.lang("Container start order {}",get.status)) # 顺序启动 / 停止 分组 def modify_group_status(self, get): try: group_ids = [i for i in get.id.split(",")] status = get.status.strip() if status not in ["start", "stop"]: return public.return_message(-1, 0, public.lang("Invalid state!")) for group_id in group_ids: get.id = group_id return self.script_group(get) except Exception as e: return public.return_message(-1, 0, public.lang("Operation failed:{}",e)) # 获取Json文件内容 def __readFile(self): try: return json.loads(public.readFile(self.GROUP_PATH)) if public.readFile(self.GROUP_PATH) else [] except: return [] # 返回指定组信息 def get_info(self, get): if not hasattr(get, "id"): return public.return_message(-1, 0, public.lang("Missing parameters id")) return public.returnResult(True, data=self.__group_info(get.id, self.__readFile())) # 获取指定组信息 内部使用 def __group_info(self, group_id, filedata): result = None for result in filedata: if group_id == result["id"]: break return result # 容器是否正在运行 def __is_running(self, container_name, container_list): container_status = {dp.rename(temp['Names'][0].replace("/", "")): temp["State"] for temp in container_list} if container_name in container_status and container_status[container_name] == "running": return True else: return False def docker_list(self, get): try: # 获取容器列表和运行状态 sk_container = container.dockerContainer() container_list = sk_container.get_container() filedata = self.__readFile() # 构建容器状态列表 container_status_list = [] # 构建分组容器字典 group_containers = {group_data["group_name"]: group_data["order"] for group_data in filedata} # 遍历每个容器并获取状态 for temp in container_list: container_name = dp.rename(temp['Names'][0].replace("/", "")) # 假设容器信息中包含名称字段 container_status = { "name": container_name, "status": temp["State"], "group": "" } for group_name, group_order in group_containers.items(): if container_name in group_order: container_status["group"] = group_name break container_status_list.append(container_status) return public.returnResult(True, data=container_status_list) except Exception as e: return public.returnResult(True, data=[])