#!/bin/bash

# ====================================================
# 服务器超售系统 (单文件 WebUI 版) - 对接魔方财务
# ====================================================

# --- 默认配置 ---
MEM_OVERSELL_RATIO=2.0
CPU_OVERSELL_RATIO=3.0
STORAGE_PATH="/var/lib/libvirt/images"
DEFAULT_BRIDGE="br0"
WEB_PORT=8888

# --- 修复换行符 ---
if [[ $(tail -c 1 "$0" | xxd -p) == "0d" ]]; then sed -i 's/\r//g' "$0"; exec bash "$0" "$@"; fi

# --- 核心函数：监控资源 (输出 JSON 给 WebUI) ---
get_resource_json() {
    TOTAL_MEM=$(free -m | grep Mem | awk '{print $2}')
    V_TOTAL_MEM=$(echo "$TOTAL_MEM * $MEM_OVERSELL_RATIO" | bc | cut -d. -f1)
    ALLOCATED_MEM=0
    for dom in $(virsh list --all --name); do
        DOM_MEM=$(virsh dominfo "$dom" 2>/dev/null | grep "Max memory" | awk '{print $3}')
        if [ -n "$DOM_MEM" ]; then ALLOCATED_MEM=$((ALLOCATED_MEM + DOM_MEM / 1024)); fi
    done
    REMAINING_V_MEM=$((V_TOTAL_MEM - ALLOCATED_MEM))
    echo "{\"total_physical\":$TOTAL_MEM, \"virtual_total\":$V_TOTAL_MEM, \"allocated\":$ALLOCATED_MEM, \"remaining\":$REMAINING_V_MEM}"
}

# --- 核心函数：虚拟机列表 ---
get_vms_json() {
    echo "["
    FIRST=true
    for dom in $(virsh list --all --name); do
        if [ -z "$dom" ]; then continue; fi
        if [ "$FIRST" = false ]; then echo ","; fi
        STATE=$(virsh domstate "$dom")
        CPU=$(virsh dominfo "$dom" | grep "CPU(s)" | awk '{print $2}')
        MEM=$(virsh dominfo "$dom" | grep "Max memory" | awk '{print $3}')
        echo "{\"name\":\"$dom\", \"state\":\"$STATE\", \"cpu\":\"$CPU\", \"mem\":\"$((MEM/1024))MB\"}"
        FIRST=false
    done
    echo "]"
}

# --- 核心函数：Web Server (Python 实现) ---
start_web() {
    echo "正在启动 WebUI 界面，访问地址: http://$(curl -s ifconfig.me):$WEB_PORT"
    python3 - <<EOF
import http.server, json, subprocess, os

class Handler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(200)
            self.send_header('Content-type', 'text/html; charset=utf-8')
            self.end_headers()
            html = """
            <!DOCTYPE html><html><head><title>超售系统管理</title>
            <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet">
            </head><body class="bg-light"><div class="container mt-5">
            <h2 class="mb-4">服务器超售系统 - 宿主机面板</h2>
            <div class="card mb-4"><div class="card-body" id="res">加载资源信息...</div></div>
            <h3>虚拟机列表</h3>
            <table class="table table-hover bg-white border">
                <thead><tr><th>名称</th><th>状态</th><th>CPU</th><th>内存</th><th>操作</th></tr></thead>
                <tbody id="vms"></tbody>
            </table>
            <script>
                function loadData() {
                    fetch('/api/res').then(r=>r.json()).then(data=>{
                        document.getElementById('res').innerHTML = '物理内存: '+data.total_physical+'MB | 虚拟总内存: '+data.virtual_total+'MB | 已分配: '+data.allocated+'MB | <b>剩余可用: '+data.remaining+'MB</b>';
                    });
                    fetch('/api/vms').then(r=>r.json()).then(data=>{
                        let h = '';
                        data.forEach(vm=>{
                            h += '<tr><td>'+vm.name+'</td><td>'+vm.state+'</td><td>'+vm.cpu+'</td><td>'+vm.mem+'</td>';
                            h += '<td><button class="btn btn-sm btn-danger" onclick="op(\'delete\',\''+vm.name+'\')">删除</button></td></tr>';
                        });
                        document.getElementById('vms').innerHTML = h;
                    });
                }
                function op(act, name) { if(confirm('确定执行 '+act+'?')) fetch('/api/op?act='+act+'&name='+name).then(()=>loadData()); }
                loadData(); setInterval(loadData, 5000);
            </script></div></body></html>
            """
            self.wfile.write(html.encode())
        elif self.path == '/api/res':
            self.send_response(200); self.send_header('Content-type', 'application/json'); self.end_headers()
            res = subprocess.check_output(['bash', '$0', 'monitor_json'])
            self.wfile.write(res)
        elif self.path == '/api/vms':
            self.send_response(200); self.send_header('Content-type', 'application/json'); self.end_headers()
            res = subprocess.check_output(['bash', '$0', 'list_json'])
            self.wfile.write(res)
        elif self.path.startswith('/api/op'):
            from urllib.parse import urlparse, parse_qs
            query = parse_qs(urlparse(self.path).query)
            act = query.get('act')[0]; name = query.get('name')[0]
            subprocess.call(['bash', '$0', act, name])
            self.send_response(200); self.end_headers()

http.server.HTTPServer(('0.0.0.0', $WEB_PORT), Handler).serve_forever()
EOF
}

# --- 入口逻辑 ---
case $1 in
    install)
        # 依赖安装... (略，复用之前逻辑)
        echo "安装依赖..."
        if command -v yum >/dev/null; then yum install -y bc qemu-img libvirt python3; else apt-get install -y bc qemu-utils libvirt-clients python3; fi
        systemctl enable --now libvirtd
        ;;
    web) start_web ;;
    monitor_json) get_resource_json ;;
    list_json) get_vms_json ;;
    create)  # 之前创建逻辑...
        VM_NAME=$2; CPU=$3; MEM=$4; DISK=$5
        DISK_IMG="${STORAGE_PATH}/${VM_NAME}.qcow2"
        qemu-img create -f qcow2 "$DISK_IMG" "${DISK}G"
        virt-install --name "$VM_NAME" --vcpus "$CPU" --ram "$MEM" --disk path="$DISK_IMG",format=qcow2 --network bridge="$DEFAULT_BRIDGE" --graphics vnc,listen=0.0.0.0 --noautoconsole --import --os-variant=generic
        ;;
    start|stop|reboot|delete|status)
        ACTION=$1; VM_NAME=$2
        case $ACTION in
            start) virsh start "$VM_NAME" ;;
            stop) virsh destroy "$VM_NAME" ;;
            delete) virsh destroy "$VM_NAME" 2>/dev/null; virsh undefine "$VM_NAME" --remove-all-storage ;;
            status) virsh domstate "$VM_NAME" 2>/dev/null || echo "not_found" ;;
        esac
        ;;
    *) echo "Usage: $0 {install|web|create|start|stop|delete|status}" ;;
esac