├── vmid.json ├── cookie └── ikuai.json ├── ip_pool.json ├── port_pool.json ├── img ├── 信息页.png ├── 前台订单页.png ├── 快照页.png ├── 操作记录页.png ├── 磁盘页.png ├── 网络页.png ├── 远程页.png ├── 前台控制台页.png ├── 后台商品配置页.png ├── 端口映射页面-0.png └── 端口映射页面-1.png ├── templates ├── error.html ├── disk.html ├── kzt.html ├── rw.html ├── network.html ├── connect.html ├── demo.html ├── nat.html ├── snapshot.html └── info.html ├── README.md └── proxmoxlxc.php /vmid.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /cookie/ikuai.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ip_pool.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /port_pool.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /img/信息页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasonDye/ProxmoxVE-LXC-X-module/HEAD/img/信息页.png -------------------------------------------------------------------------------- /img/前台订单页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasonDye/ProxmoxVE-LXC-X-module/HEAD/img/前台订单页.png -------------------------------------------------------------------------------- /img/快照页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasonDye/ProxmoxVE-LXC-X-module/HEAD/img/快照页.png -------------------------------------------------------------------------------- /img/操作记录页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasonDye/ProxmoxVE-LXC-X-module/HEAD/img/操作记录页.png -------------------------------------------------------------------------------- /img/磁盘页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasonDye/ProxmoxVE-LXC-X-module/HEAD/img/磁盘页.png -------------------------------------------------------------------------------- /img/网络页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasonDye/ProxmoxVE-LXC-X-module/HEAD/img/网络页.png -------------------------------------------------------------------------------- /img/远程页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasonDye/ProxmoxVE-LXC-X-module/HEAD/img/远程页.png -------------------------------------------------------------------------------- /img/前台控制台页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasonDye/ProxmoxVE-LXC-X-module/HEAD/img/前台控制台页.png -------------------------------------------------------------------------------- /img/后台商品配置页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasonDye/ProxmoxVE-LXC-X-module/HEAD/img/后台商品配置页.png -------------------------------------------------------------------------------- /img/端口映射页面-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasonDye/ProxmoxVE-LXC-X-module/HEAD/img/端口映射页面-0.png -------------------------------------------------------------------------------- /img/端口映射页面-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MasonDye/ProxmoxVE-LXC-X-module/HEAD/img/端口映射页面-1.png -------------------------------------------------------------------------------- /templates/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 |
15 |
16 |
{$error['code']}
17 |

{$error['msg']}

18 |

{$error['info']}

19 |
20 |
-------------------------------------------------------------------------------- /templates/disk.html: -------------------------------------------------------------------------------- 1 |
2 | 6 | LXC服务器目前不支持硬盘扩容、新增,您可以选择升级到拥有更大磁盘的套餐。 7 |
8 |
9 |
10 |
11 |
12 |
磁盘详细信息
13 |
14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
磁盘标识大小
{$disk[0]}{$params['configoptions_upgrade']['disk']} G
31 | 32 | 33 |
34 | 35 |
36 | 37 |
38 | 39 | 40 | 41 |
42 | 43 | 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ProxmoxVE-LXC-X-module 2 |
3 | 4 |

ProxmoxVE LXC X


5 | 6 | 魔方财务系统对接proxmoxVE的一款模块,可以对接pve的容器功能 7 | 8 | 此模块是原作者Jovesong1的作品改版,添加了很多有用的功能,修复了一些潜在的Bug。 9 | 10 | 此模块的文档请参考:[Wiki](https://github.com/MasonDye/ProxmoxVE-LXC-X-module/wiki/1.-%E9%A6%96%E9%A1%B5) 11 | 12 | 13 | 14 |
15 | 16 | ## 目前实现了那些功能 ? 17 | 18 | 实现了大部分功能,例如 开通、开关机、停止、VNC、磁盘管理、弹性开通、端口映射(基于爱快)、图表状态监控! 19 | 20 | * 后台商品配置功能: 21 | ![image](https://github.com/MasonDye/ProxmoxVE-LXC-X-module/blob/master/img/%E5%90%8E%E5%8F%B0%E5%95%86%E5%93%81%E9%85%8D%E7%BD%AE%E9%A1%B5.png?raw=true) 22 | * 前台订单页
23 | ![image](https://github.com/MasonDye/ProxmoxVE-LXC-X-module/blob/master/img/%E5%89%8D%E5%8F%B0%E8%AE%A2%E5%8D%95%E9%A1%B5.png?raw=true) 24 | * 前台控制台页:
25 | ![image](https://github.com/MasonDye/ProxmoxVE-LXC-X-module/blob/master/img/%E5%89%8D%E5%8F%B0%E6%8E%A7%E5%88%B6%E5%8F%B0%E9%A1%B5.png?raw=true) 26 | * 信息页:
27 | ![image](https://github.com/MasonDye/ProxmoxVE-LXC-X-module/blob/master/img/%E4%BF%A1%E6%81%AF%E9%A1%B5.png?raw=true) 28 | * 网络页:
29 | ![image](https://github.com/MasonDye/ProxmoxVE-LXC-X-module/blob/master/img/%E7%BD%91%E7%BB%9C%E9%A1%B5.png?raw=true) 30 | * 磁盘页:
31 | ![image](https://github.com/MasonDye/ProxmoxVE-LXC-X-module/blob/master/img/%E7%A3%81%E7%9B%98%E9%A1%B5.png?raw=true) 32 | * 快照页:
33 | ![image](https://github.com/MasonDye/ProxmoxVE-LXC-X-module/blob/master/img/%E5%BF%AB%E7%85%A7%E9%A1%B5.png?raw=true) 34 | * 远程页:
35 | ![image](https://github.com/MasonDye/ProxmoxVE-LXC-X-module/blob/master/img/%E8%BF%9C%E7%A8%8B%E9%A1%B5.png?raw=true) 36 | * 操作记录页:
37 | ![image](https://github.com/MasonDye/ProxmoxVE-LXC-X-module/blob/master/img/%E6%93%8D%E4%BD%9C%E8%AE%B0%E5%BD%95%E9%A1%B5.png?raw=true) 38 | * 端口映射页:
39 | ![image](https://github.com/MasonDye/ProxmoxVE-LXC-X-module/blob/master/img/%E7%AB%AF%E5%8F%A3%E6%98%A0%E5%B0%84%E9%A1%B5%E9%9D%A2-0.png?raw=true) 40 | ![image](https://github.com/MasonDye/ProxmoxVE-LXC-X-module/blob/master/img/%E7%AB%AF%E5%8F%A3%E6%98%A0%E5%B0%84%E9%A1%B5%E9%9D%A2-1.png?raw=true) 41 | 42 | **模块已完成绝大部分功能!** 43 | -------------------------------------------------------------------------------- /templates/kzt.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /templates/rw.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
操作记录
6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {foreach $tasks as $key => $vo} 19 | 20 | 23 | 26 | 57 | 58 | 59 | 60 | 74 | 75 | 76 | {/foreach} 77 | 78 | 79 |
开始时间结束时间任务描述状态
21 | {$vo.starttime} 22 | 24 | {$vo.endtime} 25 | 27 | CT:{$params['domain']} | 28 | {if $vo.type=="vzstart"} 29 | 开机 30 | {elseif $vo.type=="vzstop"} 31 | 关机 32 | {elseif $vo.type=="vzrollback"} 33 | 回滚 34 | {elseif $vo.type=="vzsnapshot"} 35 | 创建快照 36 | {elseif $vo.type=="vzcreate"} 37 | 创建主机 38 | {elseif $vo.type=="vzreboot"} 39 | 重启 40 | {elseif $vo.type=="vzdestroy"} 41 | 销毁主机 42 | {elseif $vo.type=="vzshutdown"} 43 | 强制关机 44 | {elseif $vo.type=="vzdelsnapshot"} 45 | 删除快照 46 | {elseif $vo.type=="vncproxy"} 47 | 打开控制台 48 | {else} 49 | {$vo.type} 50 | {/if} 51 | 52 | 53 | 54 | 55 | 56 | 61 | {if $vo.status=='OK'} 62 | 完成 63 | 64 | {else} 65 | 错误 66 | {/if} 67 | 68 | 69 | 70 | 71 | 72 | 73 |
80 | 81 | 82 |
83 | 84 |
85 | 86 |
87 | 88 | 89 | 90 |
91 | 92 | 93 | -------------------------------------------------------------------------------- /templates/network.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
网络详细信息
6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
IP地址子网掩码网关
19 | {if $params['configoptions']['nat'] == "nat"} 20 | (内) 21 | {/if}{$params['dedicatedip']} 22 | 23 | /{$params['configoptions']['Mask']}{$params['configoptions']['gateway']}
31 | 32 | 33 | 34 | 35 | {if $params['configoptions']['nat'] == "nat"} 36 | 37 | 38 | 39 | 40 | 41 | 42 | {/if} 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
公网地址 : {$params['configoptions']['ikuai_ip']}
从公网访问需要在端口映射页面映射端口
网卡 : {$network['name']}
MAC地址 : {$network['hwaddr']}
DNS服务器 : {$params['configoptions']['dns']}
56 |
57 | 58 |
59 | 60 |
61 | 62 |
63 |
64 |
65 |
宽带信息
66 |
67 |
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 |
出口带宽 : {$params['configoptions_upgrade']['network']} M
入口带宽 : {$params['configoptions_upgrade']['network']} M
可用流量 : 不受限制
82 | 83 |
84 | 85 |
86 | 87 |
88 | 89 | 90 | 91 |
92 | 93 | 94 | -------------------------------------------------------------------------------- /templates/connect.html: -------------------------------------------------------------------------------- 1 | 2 | {$test} 3 |
4 |
5 |
SSH连接
6 |
7 |
8 | 您可以通过SSH客户端工具远程连接到此Linux服务器。以下是您的服务器的默认连接信息
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
连接地址端口用户名密码
{$params['configoptions']['ikuai_ip']}{$port}root{$params['password']}
22 | 快速连接命令:ssh -p {$port} root@{$params['configoptions']['ikuai_ip']} 23 |
24 | 具体连接方法可以参考 SSH客户端软件连接Linux服务器教程 25 | 26 |
27 | 28 | 29 | 30 |
31 | 32 | 33 | 34 | {if $vnc} 35 |
36 |
37 |
救援连接
38 |
39 |
40 | 如您与服务器失联,您仍旧可以通过VNC救援远程连接至服务器
41 | 42 | 43 |
44 | 具体使用可以参考 网页VNC远程操作方法 45 |
46 | 47 |
48 | {/if} 49 | 50 | 51 | 52 | 53 | 54 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /templates/demo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |

服务器正在构建中 请耐心等待

37 |
38 | 39 | -------------------------------------------------------------------------------- /templates/nat.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
映射列表
7 |
8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {foreach $list.data as $key => $vo} 28 | 29 | 30 | 31 | 40 | 41 | 42 | 43 | 44 | 45 | 51 | 52 | 53 | {/foreach} 54 | 55 | 56 | 57 |
状态内网端口外网端口协议公网地址备注操作
{if $vo.enabled=='yes'} 32 | 33 | 34 | {else} 35 | 36 | {/if} 37 | 38 | 39 | {$vo.lan_port}{$vo.wan_port}{$vo.protocol}{$params['configoptions']['ikuai_ip']}:{$vo.wan_port}{$vo.comment} 46 | 47 | 48 | 49 | 50 |
58 | 59 | 60 |
61 | 62 |
63 | 64 |
65 | 66 |
67 |
68 |
69 |
映射信息
70 |
71 |
72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 |
可映射数量 : {$params['configoptions_upgrade']['nat_limit']}
已映射数量 : {$list['total']}
84 | 85 |
86 | 87 |
88 | 89 |
90 | 91 | 92 | 93 |
94 | 95 | 96 | 142 | -------------------------------------------------------------------------------- /templates/snapshot.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 |
8 |
9 |
快照列表
10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | {foreach $snapshot as $key => $vo} 32 | 33 | 36 | 37 | 38 | 51 | 52 | {/foreach} 53 | 54 | 55 |
快照名称创建日期/状态描述操作
34 | {$vo.name} 35 | {$vo.snaptime}{$vo.description} 39 | 50 |
56 | 57 | 58 |
59 | 60 | 61 | 91 |
92 | 93 |
94 | 248 | -------------------------------------------------------------------------------- /templates/info.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 33 | 34 | 35 | 36 | 37 |
38 |
39 |
40 |
41 |
42 |
43 |
处理器使用率
44 |
45 |
46 |
47 |
49 |
50 | 51 |
52 |
53 |
0% 的 0 CPU(s)
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
内存使用率(%)
65 |
66 |
67 |
68 |
70 |
71 | 72 |
73 |
74 |
512.00 MiB
75 |
76 | 77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
硬盘占用率(%)
87 |
88 |
89 |
90 |
92 |
93 | 94 |
95 |
96 |
/ G
97 |
98 | 99 |
100 | 101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
已正常运行
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 | 118 | 119 | 120 | 121 | 122 |
123 |
124 |
PVE控制台
125 |
126 |
127 |

使用ProxmoxVE控制面板操作您的服务器

128 |

129 | VMID:{$params['domain']} 132 | 133 |
134 | 135 | 用户名:{$params['dedicatedip']} 138 | 139 |
140 | 141 | 密码:{$params['password']} 144 | 145 |
146 | 147 | 控制面板:{$params['server_http_prefix']}://{$params['server_ip']}:{$params['port']} 150 |

151 |
152 |
153 | 154 | 155 | -------------------------------------------------------------------------------- /proxmoxlxc.php: -------------------------------------------------------------------------------- 1 | 'ProxmoxVE-LXC对接模块', 'APIVersion'=>'2.0', 'HelpDoc'=>'https://www.almondnet.cn/']; 10 | } 11 | 12 | // 测试链接 13 | function proxmoxlxc_TestLink($params){ 14 | 15 | // 构建URL 16 | 17 | // $url = $params['server_http_prefix']."://".$params['server_ip'].":".$params['port']; 18 | // return $url; 19 | 20 | $info = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['hostname']."/status"),true); 21 | 22 | if($info==null || $info['data']==null){ 23 | $result['status'] = 200; 24 | $result['data']['server_status'] = 0; 25 | $result['data']['msg'] ="无法连接,地址可能错误或者是密钥不正确".json_encode($info); 26 | return $result; 27 | }else{ 28 | $result['status'] = 200; 29 | $result['data']['server_status'] = 1; 30 | $result['data']['msg'] = json_encode($info); 31 | return $result; 32 | } 33 | 34 | // return 35 | 36 | } 37 | 38 | // 后台设置输出内容 39 | function proxmoxlxc_ConfigOptions(){ 40 | return [ 41 | [ 42 | 'type'=>'text', 43 | 'name'=>'系统网卡名称', 44 | 'description'=>'分配给虚拟机的网卡', 45 | 'placeholder'=>'vmbr0', 46 | 'default'=>"vmbr0", 47 | 'key'=>'net_name' 48 | ], 49 | [ 50 | 'type'=>'text', 51 | 'name'=>'处理器限制', 52 | 'description'=>'处理器性能百分比限制(0无限制)', 53 | 'placeholder'=>'0-8192 (0无限制)', 54 | 'default'=>"0", 55 | 'key'=>'cpulimit' 56 | ], 57 | [ 58 | 'type'=>'text', 59 | 'name'=>'处理器权重', 60 | 'description'=>'越大此机器获取的CPU时间越长(0禁用)', 61 | 'placeholder'=>'0-500000 (0禁用)', 62 | 'default'=>"0", 63 | 'key'=>'cpuunits' 64 | ],[ 65 | 'type'=>'text', 66 | 'name'=>'IP地址池', 67 | 'description'=>'IPV4地址范围(逗号隔开)', 68 | 'placeholder'=>'172.16.0.2,172.16.0.20', 69 | 'default'=>"172.16.0.2,172.16.0.20", 70 | 'key'=>'ip_pool' 71 | ],[ 72 | 'type'=>'text', 73 | 'name'=>'掩码', 74 | 'description'=>'掩码地址', 75 | 'placeholder'=>'24', 76 | 'default'=>"24", 77 | 'key'=>'Mask' 78 | ],[ 79 | 'type'=>'text', 80 | 'name'=>'IP网关', 81 | 'description'=>'网关', 82 | 'placeholder'=>'172.16.0.1', 83 | 'default'=>"172.16.0.1", 84 | 'key'=>'gateway' 85 | ],[ 86 | 'type'=>'text', 87 | 'name'=>'DNS服务器', 88 | 'description'=>'域名解析服务器地址', 89 | 'placeholder'=>'8.8.8.8', 90 | 'default'=>"8.8.8.8", 91 | 'key'=>'dns' 92 | ],[ 93 | 'type'=>'text', 94 | 'name'=>'系统盘存放盘', 95 | 'description'=>'存放系统盘的盘名', 96 | 'placeholder'=>'local-lvm', 97 | 'default'=>"local-lvm", 98 | 'key'=>'system_disk' 99 | ], 100 | [ 101 | 'type'=>'dropdown', 102 | 'name'=>'交换内存', 103 | 'description'=>'按照需求和定位酌情分配', 104 | 'options'=>[ 105 | 'noswap'=>'不分配', 106 | '1024'=>'1024', 107 | '1:1'=>'对等分配' 108 | ], 109 | 'default'=>"noswap", 110 | 'key'=>'swap' 111 | ], 112 | [ 113 | 'type'=>'dropdown', 114 | 'name'=>'类型', 115 | 'description'=>'NAT 或 标准', 116 | 'options'=>[ 117 | 'bz'=>'标准', 118 | 'nat'=>'nat', 119 | ], 120 | 'default'=>"bz", 121 | 'key'=>'nat' 122 | ],[ 123 | 'type'=>'text', 124 | 'name'=>'爱快地址', 125 | 'description'=>'请包含请求头加端口', 126 | 'placeholder'=>'http://example.com:80', 127 | 'default'=>"http://example.com:80", 128 | 'key'=>'ikuai_url' 129 | ],[ 130 | 'type'=>'text', 131 | 'name'=>'爱快用户名', 132 | 'description'=>'类型为标准模式勿略', 133 | 'placeholder'=>'admin', 134 | 'default'=>"admin", 135 | 'key'=>'ikuai_username' 136 | ],[ 137 | 'type'=>'text', 138 | 'name'=>'爱快密码', 139 | 'description'=>'类型为标准模式勿略', 140 | 'placeholder'=>'password', 141 | 'default'=>"password", 142 | 'key'=>'ikuai_password' 143 | ],[ 144 | 'type'=>'text', 145 | 'name'=>'映射展示地址', 146 | 'description'=>'类型为标准模式勿略', 147 | 'placeholder'=>'example.com', 148 | 'default'=>"example.com", 149 | 'key'=>'ikuai_ip' 150 | ],[ 151 | 'type'=>'text', 152 | 'name'=>'端口池-开始', 153 | 'description'=>'端口范围(开始)', 154 | 'placeholder'=>'40000', 155 | 'default'=>"40000", 156 | 'key'=>'port_pool_start' 157 | ],[ 158 | 'type'=>'text', 159 | 'name'=>'VMID起始值', 160 | 'description'=>'VMID起始值,唯一值不能相同', 161 | 'placeholder'=>'500', 162 | 'default'=>"500", 163 | 'key'=>'vmid_start' 164 | ],[ 165 | 'type'=>'text', 166 | 'name'=>'产品唯一值', 167 | 'description'=>'产品唯一值,不能相同,推荐UUID', 168 | 'placeholder'=>'D6D58A71-BA11-9192-E822-B2F46EBF1C65', 169 | 'default'=>"D6D58A71-BA11-9192-E822-B2F46EBF1C65", 170 | 'key'=>'product_unique_value' 171 | ],[ 172 | 'type'=>'text', 173 | 'name'=>'端口池-结束', 174 | 'description'=>'端口范围(结束)', 175 | 'placeholder'=>'50000', 176 | 'default'=>"50000", 177 | 'key'=>'port_pool_end' 178 | ],[ 179 | 'type'=>'dropdown', 180 | 'name'=>'嵌套虚拟化', 181 | 'description'=>'Docker等虚拟化是否允许', 182 | 'options'=>[ 183 | 'open'=>'开启', 184 | 'close'=>'关闭', 185 | ], 186 | 'default'=>"open", 187 | 'key'=>'nesting' 188 | ], 189 | 190 | 191 | ]; 192 | 193 | } 194 | 195 | 196 | // 前台页面 197 | function proxmoxlxc_ClientArea($params){ 198 | 199 | $info = [ 200 | 'info'=>['name'=>'信息'], 201 | 'net'=>['name'=>'网络'], 202 | 'disk'=>['name'=>'硬盘'], 203 | // 'firewalld'=>['name'=>'防火墙'], 204 | 'snapshot'=>['name'=>'快照'], 205 | 'connect'=>['name'=>'远程连接'], 206 | // 'demo'=>['name'=>'测试'], 207 | ]; 208 | if($params['configoptions']['nat']=='nat'){ 209 | $info['nat']=['name'=>'端口映射']; 210 | } 211 | 212 | $info['rw']=['name'=>'操作记录']; 213 | 214 | return $info; 215 | } 216 | 217 | 218 | // 前台输出页面 219 | function proxmoxlxc_ClientAreaOutput($params, $key){ 220 | 221 | if($key == "demo"){ 222 | 223 | // 信息页面 224 | return [ 225 | 'template'=>'templates/demo.html', 226 | 'vars'=>[ 227 | 'params'=>$params 228 | ] 229 | ]; 230 | 231 | } 232 | 233 | if($key == "info"){ 234 | 235 | // 信息页面 236 | return [ 237 | 'template'=>'templates/info.html', 238 | 'vars'=>[ 239 | 'params'=>$params 240 | ] 241 | ]; 242 | 243 | }else if($key == "net"){ 244 | // 网络页面 245 | return [ 246 | 'template'=>'templates/network.html', 247 | 'vars'=>[ 248 | 'params'=>$params, 249 | 'test'=>json_encode($params), 250 | 'network'=>proxmoxlxc_GET_lxc_config($params)['data']['net0'] 251 | ] 252 | ]; 253 | 254 | }else if($key == "disk"){ 255 | // 磁盘页面 256 | return [ 257 | 'template'=>'templates/disk.html', 258 | 'vars'=>[ 259 | 'params'=>$params, 260 | 'temp'=>json_encode(proxmoxlxc_GET_lxc_config($params)['data']), 261 | 'disk'=>proxmoxlxc_GET_lxc_config($params)['data']['rootfs'] 262 | ] 263 | ]; 264 | 265 | }else if($key == "snapshot"){ 266 | // 快照页面 267 | return [ 268 | 'template'=>'templates/snapshot.html', 269 | 'vars'=>[ 270 | 'params'=>$params, 271 | 'temp'=>json_encode(proxmoxlxc_GET_lxc_snapshot_list($params)), 272 | 'snapshot'=>proxmoxlxc_GET_lxc_snapshot_list($params) 273 | 274 | ] 275 | ]; 276 | 277 | }else if($key == "rw"){ 278 | // 任务页面 279 | return [ 280 | 'template'=>'templates/rw.html', 281 | 'vars'=>[ 282 | 'params'=>$params, 283 | 'temp'=>json_encode(proxmoxlxc_tasks_get_list($params)), 284 | 'tasks'=>proxmoxlxc_tasks_get_list($params) 285 | 286 | ] 287 | ]; 288 | 289 | }else if($key == "nat"){ 290 | // 映射页面 291 | // proxmoxlxc_nat_request($params,"",""); 292 | // 获取映射列表 293 | 294 | $nat_list = proxmoxlxc_nat_get_list($params); 295 | 296 | // $port_pool = explode(',', $params['configoptions']['port_pool_opt']); 297 | // $min_port = (int)$port_pool[0]; 298 | // $max_port = (int)$port_pool[1]; 299 | 300 | $min_port = (int)$params['configoptions']['port_pool_start']; 301 | $max_port = (int)$params['configoptions']['port_pool_end']; 302 | 303 | if($nat_list['ErrMsg']=='Success'){ 304 | // return "登陆成功了 本币"; 305 | // return $info; 306 | // echo json_encode($nat_list); 307 | 308 | return [ 309 | 'template'=>'templates/nat.html', 310 | 'vars'=>[ 311 | 'params'=>$params, 312 | 'list'=>$nat_list['Data'], 313 | 'test'=>json_encode($params), 314 | 'max_port'=>$max_port, 315 | 'min_port'=>$min_port 316 | // 'temp'=>json_encode(proxmoxlxc_tasks_get_list($params)), 317 | // 'tasks'=>proxmoxlxc_tasks_get_list($params) 318 | 319 | ] 320 | ]; 321 | 322 | 323 | }else{ 324 | // return json_encode($info); 325 | return [ 326 | 'template'=>'templates/error.html', 327 | 'vars'=>[ 328 | 'error'=>[ 329 | 'code'=>'502', 330 | 'msg'=>'无法连接映射服务器', 331 | 'info'=>$nat_list['ErrMsg'] 332 | ] 333 | ] 334 | ]; 335 | } 336 | 337 | 338 | 339 | }else if($key == "connect"){ 340 | // 任务页面 341 | // $ticket = proxmoxlxc_get_ticket($params); 342 | $port ="null"; 343 | 344 | if($params['configoptions']['nat']=='nat'){ 345 | $nat_list = proxmoxlxc_nat_get_list($params); 346 | 347 | if($nat_list['ErrMsg']=='Success'){ 348 | 349 | foreach ($nat_list['Data']['data'] as $value){ 350 | if($value['lan_port']=='22'){ 351 | $port = $value['wan_port']; 352 | } 353 | } 354 | 355 | } 356 | 357 | }else{ 358 | $port = '22'; 359 | } 360 | 361 | return [ 362 | 'template'=>'templates/connect.html', 363 | 'vars'=>[ 364 | 'params'=>$params, 365 | 'port'=>$port, 366 | 'vnc'=>proxmoxlxc_vnc_if($params) 367 | 368 | ] 369 | ]; 370 | 371 | } 372 | 373 | } 374 | 375 | // 允许执行的func 376 | function proxmoxlxc_AllowFunction(){ 377 | return [ 378 | 'client'=>["Getcurrent","delete_snapshot","RollBACK_snapshot","create_snapshot","nat_add","nat_del","Vnc"], 379 | ]; 380 | } 381 | 382 | /*图表*/ 383 | 384 | 385 | // 定义图表 386 | function proxmoxlxc_Chart(){ 387 | return [ 388 | 'cpu'=>[ // 图表type 389 | 'title'=>'CPU使用率', // 标题 390 | 'select'=>[ 391 | [ 392 | 'name'=>'1小时', 393 | 'value'=>'hour' 394 | ], 395 | [ 396 | 'name'=>'一天', 397 | 'value'=>'day' 398 | 399 | ], 400 | [ 401 | 'name'=>'七天', 402 | 'value'=>'week' 403 | ],[ 404 | 'name'=>'一月', 405 | 'value'=>'month' 406 | ], 407 | ] 408 | 409 | 410 | ], 411 | 'mem'=>[ // 图表type 412 | 'title'=>'内存使用率', // 标题 413 | 'select'=>[ 414 | [ 415 | 'name'=>'1小时', 416 | 'value'=>'hour' 417 | ], 418 | [ 419 | 'name'=>'一天', 420 | 'value'=>'day' 421 | 422 | ], 423 | [ 424 | 'name'=>'七天', 425 | 'value'=>'week' 426 | ],[ 427 | 'name'=>'一月', 428 | 'value'=>'month' 429 | ], 430 | ] 431 | 432 | ], 433 | 'disk'=>[ // 图表type 434 | 'title'=>'硬盘IO', // 标题 435 | 'select'=>[ 436 | [ 437 | 'name'=>'1小时', 438 | 'value'=>'hour' 439 | ], 440 | [ 441 | 'name'=>'一天', 442 | 'value'=>'day' 443 | 444 | ], 445 | [ 446 | 'name'=>'七天', 447 | 'value'=>'week' 448 | ],[ 449 | 'name'=>'一月', 450 | 'value'=>'month' 451 | ], 452 | ] 453 | 454 | ], 455 | 'network'=>[ // 图表type 456 | 'title'=>'网络流量', // 标题 457 | 'select'=>[ 458 | [ 459 | 'name'=>'1小时', 460 | 'value'=>'hour' 461 | ], 462 | [ 463 | 'name'=>'一天', 464 | 'value'=>'day' 465 | 466 | ], 467 | [ 468 | 'name'=>'七天', 469 | 'value'=>'week' 470 | ],[ 471 | 'name'=>'一月', 472 | 'value'=>'month' 473 | ], 474 | ] 475 | 476 | ], 477 | ]; 478 | 479 | } 480 | 481 | function proxmoxlxc_ChartData($params){ 482 | 483 | // 计算一下机器运行时间 484 | 485 | // 读取机器信息 486 | $uptime = proxmoxlxc_GET_lxc_info($params)['data']['uptime']; 487 | $timeframe = $params['chart']['select']; 488 | // if($uptime>=86400){ 489 | // // 一天了 490 | // $timeframe = "day"; 491 | // }else{ 492 | // // 一小时 493 | // $timeframe = "hour"; 494 | // } 495 | // return ['status'=>'error', 'msg'=>json_encode($uptime)]; 496 | 497 | $info = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."/rrddata?timeframe=".$timeframe),true); 498 | 499 | 500 | 501 | if($params['chart']['type'] == 'cpu'){ 502 | 503 | // 组成数组 504 | 505 | foreach ($info['data'] as $value){ 506 | 507 | $cpu = substr($value['cpu'] * 100,0,2); 508 | // $cpu = substr($value['cpu'],0,4); 509 | $result['data']['list'][0][] = [ 510 | 'time' =>date('Y-m-d H:i:s', $value['time']), 511 | 'value' =>$cpu 512 | ]; 513 | 514 | } 515 | 516 | $result["status"] = "success"; // 失败返回error 517 | 518 | $result["data"]["unit"] = "%"; //单位 519 | 520 | $result["data"]["chart_type"] = "line"; //支持 line线形,area区域填充 521 | 522 | $result["data"]["label"] = ["CPU使用率(%)"]; //对应每条线的label 523 | 524 | 525 | }elseif($params['chart']['type'] == 'mem'){ 526 | 527 | // 组成数组 528 | 529 | foreach ($info['data'] as $value){ 530 | 531 | if($value['maxmem']==""){ 532 | break; 533 | } 534 | // $cpu = round(substr($value['cpu'],0,4) * 100,2); 535 | // $cpu = substr($value['cpu'],0,4); 536 | $max_mem = ($value['maxmem'] / 1024) / 1024 ; 537 | $run_mem = ($value['mem'] / 1024) / 1024 ; 538 | 539 | $mem = round($run_mem / $max_mem * 100,2); 540 | // (data.data.mem / 1024) / 1024 (run_mem/mem_max*100) 541 | 542 | // 内存百分比的 543 | $result['data']['list'][0][] = [ 544 | 'time' =>date('Y-m-d H:i:s', $value['time']), 545 | 'value' =>$mem 546 | ]; 547 | 548 | 549 | } 550 | 551 | $result["status"] = "success"; // 失败返回error 552 | 553 | $result["data"]["unit"] = "%"; //单位 554 | 555 | $result["data"]["chart_type"] = "line"; //支持 line线形,area区域填充 556 | 557 | $result["data"]["label"] = ["内存使用率(%)"]; //对应每条线的label 558 | 559 | }elseif($params['chart']['type'] == 'disk'){ 560 | 561 | // 组成数组 562 | $dw = "K"; 563 | foreach ($info['data'] as $value){ 564 | 565 | $diskwrite = round($value['diskwrite'] / 1000,3); 566 | $diskread = round($value['diskread'] / 1000,3); 567 | 568 | 569 | // 计算IO 570 | $result['data']['list'][0][] = [ 571 | 'time' =>date('Y-m-d H:i:s', $value['time']), 572 | 'value' =>$diskwrite 573 | ]; 574 | $result['data']['list'][1][] = [ 575 | 'time' =>date('Y-m-d H:i:s', $value['time']), 576 | 'value' =>$diskread 577 | ]; 578 | 579 | 580 | } 581 | 582 | $result["status"] = "success"; // 失败返回error 583 | 584 | $result["data"]["unit"] = "K"; //单位 585 | 586 | $result["data"]["chart_type"] = "line"; //支持 line线形,area区域填充 587 | 588 | $result["data"]["label"] = ["写入速度(kb/s)","读取速度(kb/s)"]; //对应每条线的label 589 | 590 | }elseif($params['chart']['type'] == 'network'){ 591 | 592 | // 组成数组 593 | foreach ($info['data'] as $value){ 594 | 595 | $netin = round($value['netin'] / 1000,3); 596 | $netout = round($value['netout'] / 1000,3); 597 | 598 | 599 | // 计算IO 600 | $result['data']['list'][0][] = [ 601 | 'time' =>date('Y-m-d H:i:s', $value['time']), 602 | 'value' =>$netin 603 | ]; 604 | $result['data']['list'][1][] = [ 605 | 'time' =>date('Y-m-d H:i:s', $value['time']), 606 | 'value' =>$netout 607 | ]; 608 | 609 | 610 | } 611 | 612 | $result["status"] = "success"; // 失败返回error 613 | 614 | $result["data"]["unit"] = "K"; //单位 615 | 616 | $result["data"]["chart_type"] = "line"; //支持 line线形,area区域填充 617 | 618 | $result["data"]["label"] = ["入网流量(KB/s)","出网流量(KB/s)"]; //对应每条线的label 619 | 620 | } 621 | 622 | return $result; 623 | 624 | } 625 | 626 | // vnc 627 | function proxmoxlxc_Vnc($params){ 628 | 629 | // 判断是否存在VNC控制台的后端程序 630 | 631 | if(!proxmoxlxc_vnc_if($params)){ 632 | 633 | return ['status'=>'error','msg'=>'VNC功能未启用']; 634 | 635 | } 636 | 637 | 638 | $ticket = proxmoxlxc_get_ticket($params); 639 | if($ticket){ 640 | //noVNC 登入 641 | //return ['status'=>'success','msg'=>'VNC连接创建成功','url'=>$params['server_http_prefix']."://".$params['server_ip'].":".$params['port']."/novnc/mgnovnc.html?novnc=1&console=lxc&node=".$params['server_host']."&vmid=".$params['domain']."&token=".$ticket]; 642 | //XtermJS 登入 643 | return ['status'=>'success','msg'=>'VNC连接创建成功','url'=>$params['server_http_prefix']."://".$params['server_ip'].":".$params['port']."/novnc/mgnovnc.html?xtermjs=1&console=lxc&node=".$params['server_host']."&vmid=".$params['domain']."&token=".$ticket]; 644 | //return ['status'=>'success','msg'=>'VNC连接创建成功','url'=>$params['server_http_prefix']."://".$params['server_ip'].":".$params['port']."?console=shell&xtermjs=1"."&vmid=".$params['domain']."&node=".$params['server_host']."&token=".$ticket]; 645 | } 646 | 647 | 648 | // 不存在返回控制面板 649 | 650 | 651 | 652 | 653 | 654 | // return ['status'=>'success','msg'=>'打开面板成功','url'=>$params['server_http_prefix']."://".$params['server_ip'].":".$params['port']]; 655 | } 656 | 657 | 658 | 659 | // 开通方法 660 | function proxmoxlxc_CreateAccount($params){ 661 | 662 | 663 | 664 | 665 | 666 | 667 | $ip_while_num_max = 100; // IP生成循环次数,如果超过一定阈值直接弹出IP不足 668 | $ip_while_num = 0 ; 669 | $vmid = proxmoxlxc_nextid($params); 670 | /*构建IP地址 只能暂时分配/24的地址*/ 671 | 672 | // 分割IP段 673 | 674 | // 先把段分割成起始跟结束 675 | $temp_ip_ = explode(",",$params['configoptions']['ip_pool']); 676 | 677 | $temp_ip_start = explode(".",$temp_ip_[0]); 678 | 679 | $temp_ip_end = explode(".",$temp_ip_[1]); 680 | 681 | // 开始分配IP地址 682 | while_ip: 683 | 684 | if($ip_while_num>=$ip_while_num_max ){ 685 | return ['status'=>'error','msg'=>"无可用IP地址"]; 686 | } 687 | 688 | $ip = $temp_ip_start[0].".".$temp_ip_start[1].".".$temp_ip_start[2].".".rand($temp_ip_start[3],$temp_ip_end[3]); 689 | 690 | 691 | // 验证IP是否占用 692 | $file = fopen(__DIR__."/ip_pool.json","r"); 693 | 694 | $ip_json =json_decode(fread($file,filesize(__DIR__."/ip_pool.json")),true); 695 | 696 | fclose($file); 697 | 698 | 699 | foreach ($ip_json as $value){ 700 | if($value['ip'] == $ip){ 701 | // 存在相同的IP 冲突,重新获取IP 702 | $ip_while_num = $ip_while_num + 1; 703 | goto while_ip; 704 | 705 | } 706 | } 707 | 708 | // 临时写在这里 709 | // return ['status'=>'error','msg'=>proxmoxlxc_user_add($params,$ip,$params['password'],$vmid)]; 710 | 711 | if(!proxmoxlxc_user_add($params,$ip,$params['password'],$vmid)){ 712 | 713 | return ['status'=>'error','msg'=>"创建用户分配权限失败"]; 714 | 715 | } 716 | 717 | // 构建JSON结构 718 | 719 | $json_network['server_vmid'] = $vmid;//对应主机VMID 720 | $json_network['bridge']=$params['configoptions']['net_name']; 721 | $json_network['ip'] = $ip; 722 | $json_network['mask'] = $params['configoptions']['Mask']; 723 | $json_network['gateway'] = $params['configoptions']['gateway']; 724 | $json_network['rate']=$params['configoptions_upgrade']['network']; 725 | 726 | $ip_json[$ip] = $json_network; 727 | 728 | // 写入库 729 | $file = fopen(__DIR__."/ip_pool.json","w"); 730 | 731 | fwrite($file,json_encode($ip_json)); 732 | 733 | fclose($file); 734 | 735 | // return ['status'=>'error','msg'=>json_encode($ip_json)]; 736 | 737 | /*构建传递参数*/ 738 | 739 | $network['name']='eth0'; 740 | $network['bridge']=$params['configoptions']['net_name']; 741 | $network['gw']=$params['configoptions']['gateway']; 742 | $network['ip']=$ip."/".$params['configoptions']['Mask']; 743 | $network['rate']=$params['configoptions_upgrade']['network']; 744 | foreach ($network as $key=>$value){ 745 | if($network_body==""){ 746 | $network_body = $key."%3D".$value; 747 | }else{ 748 | $network_body = $network_body."%2C".$key."%3D".$value; 749 | } 750 | } 751 | $data['start']=1; 752 | $data['ostemplate'] = $params['configoptions_upgrade']['os']; // 模板 753 | $data['vmid'] = $vmid; // vmid 754 | $data['hostname']=$params['domain']; 755 | $data['unprivileged']=1; 756 | if($params['configoptions']['nesting'] == 'open'){ //嵌套虚拟化允许 757 | // $data['features']='nesting'."%3D"."1"."%2C".'keyctl'."%3D"."1"; 758 | $data['features']='nesting'."%3D"."1"; 759 | // $data['features']='nesting'."%3D"."1"."%2C".'keyctl'."%3D"."1"."%2C".'fuse'."%3D"."1"; 760 | } 761 | $data['password']=$params['password']; 762 | $data['rootfs']=$params['configoptions']['system_disk'].":".$params['configoptions_upgrade']['disk']; 763 | $data['cores']=$params['configoptions_upgrade']['cpu']; 764 | $data['memory']=$params['configoptions_upgrade']['memory']; 765 | $data['net0']=$network_body; 766 | $data['cmode']='console'; 767 | $data['onboot'] = true; 768 | $data['nameserver'] = $params['configoptions']['dns']; 769 | $data['description'] = "

ArcCloud


来自: 智简魔方ProxmoxVE-LXC模块
开通用户:".$params['user_info']['username']."|".$params['user_info']['id']."
产品编号:".$params['hostid']."
产品密码:".$params['password'];//描述 770 | // $data['bwlimit']=$params['configoptions_upgrade']['network']; 771 | if($params['configoptions']['swap'] == '1:1'){ 772 | // 对等分配swap 773 | $data['swap'] = $params['configoptions_upgrade']['memory']; 774 | }elseif($params['configoptions']['swap'] == '1024'){ 775 | // 分配1G 776 | $data['swap'] = '1024'; 777 | } 778 | 779 | /*请求后端创建服务器*/ 780 | $info = json_decode(proxmoxlxc_request($params,"/api2/extjs/nodes/".$params['server_host']."/lxc",$data,"POST"),true); 781 | /*结果处理*/ 782 | 783 | 784 | if($info['success']){ 785 | // 判断是否为nat机器 如果是就执行下默认映射操作 786 | if($params['configoptions']['nat']=="nat"){ 787 | $post['comment'] = $params['domain']."的远程端口"; 788 | $post['type']='tcp+udp'; 789 | $post['lan_port'] = "22"; 790 | $post['lan_addr'] = $ip; 791 | 792 | 793 | 794 | $port_info = proxmoxlxc_nat_add($params,$post); 795 | 796 | if($port_info['ErrMsg']!="Success"){ 797 | active_logs("创建端口映射时出现错误:".json_encode($port_info),$params['uid'],2); 798 | return ['status'=>'error','msg'=>json_encode($port_info)]; 799 | } 800 | $update['port'] =$port_info['wan_port']; 801 | } 802 | 803 | 804 | 805 | /*更新数据列表*/ 806 | 807 | 808 | 809 | $update['dedicatedip'] =$ip; 810 | $update['domain']=$data['vmid']; 811 | Db::name('host')->where('id', $params['hostid'])->update($update); 812 | 813 | 814 | 815 | 816 | /*写入本地文件*/ 817 | 818 | return ['status'=>'success']; 819 | }else{ 820 | // 错误处理 10086 821 | return ['status'=>'error','msg'=>json_encode($info).json_encode($params).json_encode($data['ostemplate'])]; 822 | } 823 | 824 | 825 | 826 | 827 | } 828 | 829 | /*管理*/ 830 | 831 | // 删除机器 832 | function proxmoxlxc_TerminateAccount ($params){ 833 | 834 | 835 | if(!proxmoxlxc_user_del($params)){ 836 | // return ['status'=>'error','msg'=>'用户删除失败']; 837 | active_logs($params['dedicatedip']."@pve用户删除失败",$params['uid'],2); 838 | } 839 | 840 | 841 | $info = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."?purge=1&destroy-unreferenced-disks=1&force=1","","DELETE"),true); 842 | if($info['data']==null || $info == null){ 843 | 844 | 845 | 846 | 847 | 848 | return ['status'=>'error','msg'=>"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."purge=1&destroy-unreferenced-disks=1&force=1"]; 849 | }else{ 850 | /*把操作保存到ip池中 释放IP*/ 851 | 852 | $file = fopen(__DIR__."/ip_pool.json","r"); 853 | 854 | $ip_json =json_decode(fread($file,filesize(__DIR__."/ip_pool.json")),true); 855 | 856 | fclose($file); 857 | 858 | 859 | 860 | // 删除IP 861 | unset($ip_json[$params['dedicatedip']]); 862 | 863 | // 写入库 864 | $file = fopen(__DIR__."/ip_pool.json","w"); 865 | 866 | fwrite($file,json_encode($ip_json)); 867 | 868 | fclose($file); 869 | 870 | // 判断是否为映射机 871 | 872 | // 判断是否为nat机器 如果是就执行下默认映射操作 873 | if($params['configoptions']['nat']=="nat"){ 874 | 875 | // 操作删除映射 876 | $nat_list = proxmoxlxc_nat_get_list($params); 877 | 878 | if($nat_list['ErrMsg']=='Success'){ 879 | // 获取成功 880 | 881 | foreach($nat_list['Data']['data'] as $key=>$value){ 882 | // 执行删除 883 | $port['id'] = $value['id']; 884 | $port['wan_port'] = $value['wan_port']; 885 | $return_info = proxmoxlxc_nat_del($params,$port); 886 | 887 | // active_logs("执行删除映射结果:".json_encode($return_info),$params['uid'],2); 888 | 889 | } 890 | 891 | 892 | }else{ 893 | // 获取失败,写入日志 894 | active_logs("执行删除映射失败:".json_encode($nat_list),$params['uid'],2); 895 | } 896 | 897 | 898 | } 899 | 900 | 901 | // 便利映射数量 902 | 903 | // 删除映射 904 | 905 | 906 | return ['status'=>'success']; 907 | } 908 | 909 | 910 | } 911 | 912 | /*电源管理*/ 913 | 914 | // 开机 915 | function proxmoxlxc_On($params){ 916 | $info = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."/status/start",$data,"POST"),true); 917 | if($info['data']==null || $info == null){ 918 | return ['status'=>'error','msg'=>'操作失败']; 919 | }else{ 920 | return ['status'=>'success']; 921 | } 922 | 923 | 924 | 925 | } 926 | // 关机 927 | function proxmoxlxc_Off($params){ 928 | $info = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."/status/shutdown",$data,"POST"),true); 929 | if($info['data']==null || $info == null){ 930 | return ['status'=>'error','msg'=>'操作失败']; 931 | }else{ 932 | return ['status'=>'success']; 933 | } 934 | 935 | 936 | } 937 | 938 | // 重启 939 | function proxmoxlxc_Reboot($params){ 940 | $info = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."/status/reboot",$data,"POST"),true); 941 | if($info['data']==null || $info == null){ 942 | return ['status'=>'error','msg'=>'操作失败']; 943 | }else{ 944 | return ['status'=>'success']; 945 | } 946 | } 947 | 948 | // 强制关机 949 | function proxmoxlxc_HardOff ($params){ 950 | $info = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."/status/stop",$data,"POST"),true); 951 | if($info['data']==null || $info == null){ 952 | return ['status'=>'error','msg'=>'操作失败']; 953 | }else{ 954 | return ['status'=>'success']; 955 | } 956 | } 957 | 958 | 959 | // 暂停 960 | function proxmoxlxc_SuspendAccount ($params){ 961 | proxmoxlxc_HardOff($params); 962 | } 963 | // 解除暂停 964 | function proxmoxlxc_UnsuspendAccount($params){ 965 | 966 | } 967 | 968 | 969 | /*功能函数*/ 970 | 971 | function proxmoxlxc_Getcurrent($params){ 972 | $post = input('post.'); 973 | 974 | 975 | // 验证PVE状态 976 | if(!proxmoxlxc_Pvestatus($params)){ 977 | return ['status'=>'error','msg'=>'受控端异常']; 978 | } 979 | 980 | 981 | return proxmoxlxc_GET_lxc_info($params); 982 | } 983 | 984 | 985 | // 获取VMID 986 | function proxmoxlxc_nextid($params) { 987 | $vmid_file_path = __DIR__ . "/vmid.json"; 988 | $product_unique_value = $params['configoptions']['product_unique_value']; 989 | $start_vmid = (int)$params['configoptions']['vmid_start']; 990 | 991 | // 初始化 $vmid_data 992 | $vmid_data = []; 993 | 994 | // 文件存在并且可读 995 | if (file_exists($vmid_file_path)) { 996 | $vmid_file = fopen($vmid_file_path, "r+"); 997 | if (flock($vmid_file, LOCK_EX)) { 998 | $file_content = fread($vmid_file, filesize($vmid_file_path)); 999 | if ($file_content !== false && trim($file_content) !== '') { 1000 | $vmid_data = json_decode($file_content, true); 1001 | 1002 | // 检查是否JSON解析失败 1003 | if (json_last_error() !== JSON_ERROR_NONE) { 1004 | $vmid_data = []; // 解析失败,初始化为空数组 1005 | } 1006 | } 1007 | 1008 | if (isset($vmid_data[$product_unique_value])) { 1009 | // 获取当前 VMID 并返回 1010 | $current_vmid = (int)$vmid_data[$product_unique_value]['data']; 1011 | 1012 | // 更新 VMID 并写回文件 1013 | $vmid_data[$product_unique_value]['data'] = $current_vmid + 1; 1014 | ftruncate($vmid_file, 0); 1015 | rewind($vmid_file); 1016 | fwrite($vmid_file, json_encode($vmid_data, JSON_PRETTY_PRINT)); 1017 | fflush($vmid_file); 1018 | flock($vmid_file, LOCK_UN); 1019 | fclose($vmid_file); 1020 | 1021 | return $current_vmid; 1022 | } 1023 | 1024 | flock($vmid_file, LOCK_UN); 1025 | } 1026 | fclose($vmid_file); 1027 | } 1028 | 1029 | // 文件不存在或没有产品唯一值,初始化并写入 1030 | $vmid_data[$product_unique_value] = ['data' => $start_vmid]; 1031 | 1032 | // 合并数据 1033 | if (file_exists($vmid_file_path)) { 1034 | $existing_data = json_decode(file_get_contents($vmid_file_path), true); 1035 | if (json_last_error() === JSON_ERROR_NONE && is_array($existing_data)) { 1036 | $vmid_data = array_merge($existing_data, $vmid_data); 1037 | } 1038 | } 1039 | 1040 | $vmid_file = fopen($vmid_file_path, "w"); 1041 | if (flock($vmid_file, LOCK_EX)) { 1042 | fwrite($vmid_file, json_encode($vmid_data, JSON_PRETTY_PRINT)); 1043 | fflush($vmid_file); 1044 | flock($vmid_file, LOCK_UN); 1045 | } 1046 | fclose($vmid_file); 1047 | 1048 | return $start_vmid; 1049 | } 1050 | 1051 | 1052 | 1053 | // 删除VMID 1054 | // 这个功能先咕咕,没思路 1055 | function proxmoxlxc_delete_id($params) { 1056 | 1057 | } 1058 | 1059 | 1060 | // 没有唯一id,被取代 1061 | // 获取VMID 1062 | // function proxmoxlxc_nextid($params) { 1063 | // $vmid_file_path = __DIR__ . "/vmid.json"; 1064 | 1065 | // // 检查文件是否存在 1066 | // if (file_exists($vmid_file_path)) { 1067 | // $vmid_file_size = filesize($vmid_file_path); 1068 | 1069 | // if ($vmid_file_size > 0) { 1070 | // // 文件存在且不为空,读取 JSON 数据 1071 | // $vmid_file = fopen($vmid_file_path, "r"); 1072 | // $vmid_data = json_decode(fread($vmid_file, $vmid_file_size), true); 1073 | // fclose($vmid_file); 1074 | 1075 | // // 获取当前 VMID 并返回 1076 | // $current_vmid = (int)$vmid_data['data']; 1077 | 1078 | // // 将新的 VMID 加 1 并写回文件 1079 | // $new_vmid_data = ['data' => $current_vmid + 1]; 1080 | // $vmid_file = fopen($vmid_file_path, "w"); 1081 | // fwrite($vmid_file, json_encode($new_vmid_data, JSON_PRETTY_PRINT)); 1082 | // fclose($vmid_file); 1083 | 1084 | // return $current_vmid; 1085 | // } 1086 | // } 1087 | 1088 | // // 文件不存在或为空,写入初始 VMID 并返回 1089 | // $start_vmid = (int)$params['configoptions']['vmid_start']; 1090 | // $new_vmid_data = ['data' => $start_vmid]; 1091 | // $vmid_file = fopen($vmid_file_path, "w"); 1092 | // fwrite($vmid_file, json_encode($new_vmid_data, JSON_PRETTY_PRINT)); 1093 | // fclose($vmid_file); 1094 | 1095 | // return $start_vmid; 1096 | // } 1097 | 1098 | 1099 | 1100 | //老的版本 1101 | // 获取VMID 1102 | // function proxmoxlxc_nextid($params){ 1103 | 1104 | // if(!proxmoxlxc_Pvestatus($params)){ 1105 | // // return ['status'=>'error','msg'=>'受控端异常']; 1106 | // return 0; 1107 | // }else{ 1108 | // $request = json_decode(proxmoxlxc_request($params,"/api2/json/cluster/nextid"),true); 1109 | // return $request['data']; 1110 | // } 1111 | // } 1112 | 1113 | 1114 | 1115 | // 检测pve状态 1116 | function proxmoxlxc_Pvestatus($params){ 1117 | 1118 | return 1; 1119 | 1120 | } 1121 | 1122 | function proxmoxlxc_status($params){ 1123 | 1124 | 1125 | $request = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."/status/current"),true); 1126 | $result['status'] = 'success'; 1127 | if($request['data']['status']=='running'){ 1128 | // 运行中 1129 | $result['data']['status'] = 'on'; 1130 | $result['data']['des'] = '运行中'; 1131 | }elseif($request['data']['status']=='stopped'){ 1132 | $result['data']['status'] = 'off'; 1133 | $result['data']['des'] = '关机'; 1134 | }else{ 1135 | $result['data']['status'] = 'unknown'; 1136 | $result['data']['des'] = '未知'; 1137 | } 1138 | 1139 | return $result; 1140 | 1141 | } 1142 | 1143 | // 获取LXC信息 1144 | function proxmoxlxc_GET_lxc_info($params){ 1145 | $request = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."/status/current"),true); 1146 | return $request; 1147 | 1148 | } 1149 | 1150 | // 获取LXC配置信息 1151 | function proxmoxlxc_GET_lxc_config($params){ 1152 | $request = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."/config"),true); 1153 | 1154 | if($request['data']==null||$request==null){ 1155 | return false; 1156 | } 1157 | 1158 | // 把网卡配置格式化一下 1159 | $temp_net_info = explode(",",$request['data']['net0']); 1160 | foreach ($temp_net_info as $value){ 1161 | 1162 | $temp = explode("=",$value); 1163 | 1164 | $temp_ini[$temp[0]]=$temp[1]; 1165 | 1166 | 1167 | } 1168 | $request['data']['net0'] = $temp_ini; 1169 | 1170 | // 格式化硬盘 1171 | $temp_disk_info = explode(",",$request['data']['rootfs']); 1172 | 1173 | $request['data']['rootfs'] = explode(",",$request['data']['rootfs']);; 1174 | 1175 | 1176 | return $request; 1177 | 1178 | } 1179 | 1180 | /*快照相关*/ 1181 | 1182 | // 获取快照列表 1183 | function proxmoxlxc_GET_lxc_snapshot_list($params){ 1184 | $request = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."/snapshot/"),true); 1185 | $temp = []; 1186 | foreach ($request['data'] as $value){ 1187 | 1188 | if($value['name']=="current"){ 1189 | continue; 1190 | } 1191 | $value['snaptime'] = date('Y-m-d H:i:s',$value['snaptime']); 1192 | 1193 | $value['description'] = mb_convert_encoding($value['description'], 'GBK','UTF-8'); 1194 | // $a = 1; 1195 | array_push($temp,$value); 1196 | 1197 | // $temp['name'] = $value['name']; 1198 | } 1199 | 1200 | return $temp; 1201 | 1202 | } 1203 | 1204 | // 删除快照 1205 | function proxmoxlxc_delete_snapshot($params){ 1206 | 1207 | $post = input('post.'); 1208 | 1209 | $request = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."/snapshot/".$post['name'],"","DELETE"),true); 1210 | 1211 | if($request['data']==null||$request==null){ 1212 | return false; 1213 | } 1214 | 1215 | return ['status'=>'200','msg'=>'快照删除成功']; 1216 | 1217 | } 1218 | 1219 | // 回滚 1220 | function proxmoxlxc_RollBACK_snapshot($params){ 1221 | 1222 | $post = input('post.'); 1223 | 1224 | $request = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."/snapshot/".$post['name']."/rollback","","POST"),true); 1225 | 1226 | if($request['data']==null||$request==null){ 1227 | return false; 1228 | } 1229 | 1230 | return ['status'=>'200','msg'=>'回滚成功']; 1231 | 1232 | } 1233 | 1234 | // 创建快照 1235 | function proxmoxlxc_create_snapshot($params){ 1236 | 1237 | $post = input('post.'); 1238 | 1239 | // 检查传入的 快照名称是否符合后端pve服务器的要求 1240 | if (!isset($post['name']) || !preg_match('/^[a-zA-Z][a-zA-Z0-9_]{1,}$/', $post['name'])) { 1241 | return ['ErrMsg' => 'IllegalFormat']; 1242 | } 1243 | 1244 | // 检查快照描述是否超出了100字 1245 | if (!isset($post['description']) || strlen($post['description']) > 100) { 1246 | return ['ErrMsg' => 'IllegalFormat']; 1247 | } 1248 | 1249 | $data['snapname'] = $post['name']; 1250 | $data['description'] = $post['description']; 1251 | 1252 | $request = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/lxc/".$params['domain']."/snapshot/",$data,"POST"),true); 1253 | 1254 | // 调试代码 1255 | //active_logs(json_encode($request).json_encode($data).$params['server_host'].$params['domain']); 1256 | 1257 | if($request['data']==null||$request==null){ 1258 | return false; 1259 | } 1260 | 1261 | return ['status'=>'200','msg'=>'创建成功']; 1262 | 1263 | } 1264 | 1265 | /*任务相关*/ 1266 | 1267 | // 获取任务列表 1268 | function proxmoxlxc_tasks_get_list($params){ 1269 | 1270 | 1271 | $request = json_decode(proxmoxlxc_request($params,"/api2/json/nodes/".$params['server_host']."/tasks?vmid=".$params['domain']."&start=0&limit=10"),true); 1272 | 1273 | if($request['data']==null||$request==null){ 1274 | return false; 1275 | } 1276 | 1277 | 1278 | $temp = []; 1279 | foreach ($request['data'] as $value){ 1280 | 1281 | $value['starttime'] = date('Y-m-d H:i:s',$value['starttime']); 1282 | $value['endtime'] = date('Y-m-d H:i:s',$value['endtime']); 1283 | 1284 | // $a = 1; 1285 | array_push($temp,$value); 1286 | 1287 | // $temp['name'] = $value['name']; 1288 | } 1289 | 1290 | return $temp; 1291 | 1292 | 1293 | 1294 | // return $request['data']; 1295 | 1296 | 1297 | } 1298 | 1299 | 1300 | /* 1301 | 端口映射相关操作 1302 | */ 1303 | 1304 | 1305 | 1306 | // 获取列表 1307 | function proxmoxlxc_nat_get_list($params){ 1308 | $url = $params['configoptions']['ikuai_url']."/Action/call"; 1309 | 1310 | 1311 | 1312 | $data['func_name'] = "dnat"; 1313 | $data['action'] = "show"; 1314 | $data['param'] = [ 1315 | "TYPE"=>"total,data", 1316 | "limit"=>"0,20", 1317 | "FINDS"=>"lan_addr,lan_port,wan_port,comment", 1318 | "KEYWORDS"=> $params['dedicatedip'] 1319 | 1320 | ]; 1321 | 1322 | $info = json_decode(proxmoxlxc_nat_request($params,$url,$data),true); 1323 | 1324 | // echo json_encode($data); 1325 | 1326 | return $info; 1327 | 1328 | // return proxmoxlxc_nat_request($params,$url,$dataa); 1329 | } 1330 | 1331 | 1332 | 1333 | // 添加映射 1334 | function proxmoxlxc_nat_add($params, $post = "") { 1335 | // 判断是从哪里请求的 1336 | if ($post == "") { 1337 | // 从前台请求的 需要手动拉一下内网ip 1338 | $post = input('post.'); 1339 | $post['lan_addr'] = $params['dedicatedip']; 1340 | } 1341 | 1342 | // 映射数量限制 1343 | $nat_list = proxmoxlxc_nat_get_list($params); 1344 | $nat_limit_error = ['ErrMsg' => 'ReachLimit']; 1345 | 1346 | if ($nat_list['Data']['total'] == $params['configoptions_upgrade']['nat_limit']) { 1347 | return $nat_limit_error; 1348 | } 1349 | 1350 | // 获取端口范围 1351 | // $port_pool = explode(',', $params['configoptions']['port_pool_opt']); 1352 | // $min_port = (int)$port_pool[0]; 1353 | // $max_port = (int)$port_pool[1]; 1354 | $min_port = (int)$params['configoptions']['port_pool_start']; 1355 | $max_port = (int)$params['configoptions']['port_pool_end']; 1356 | 1357 | // 检查 post['wan_port'] 是否在合法范围内 1358 | if (!empty($post['wan_port']) && ($post['wan_port'] < $min_port || $post['wan_port'] > $max_port)) { 1359 | return ['ErrMsg' => 'IllegalPort']; 1360 | } 1361 | 1362 | // 端口分配代码开始 1363 | $port_while_num_max = 100; // 端口生成循环次数,如果超出阈值直接弹出端口不足 1364 | $port_while_num = 0; 1365 | 1366 | $port_pool_file_path = __DIR__ . "/port_pool.json"; 1367 | 1368 | while (true) { 1369 | if ($port_while_num >= $port_while_num_max) { 1370 | return ['ErrMsg' => 'PortUnavailable']; 1371 | } 1372 | 1373 | // 如果未传递外网端口,就按照端口池随机生成 1374 | if (empty($post['wan_port'])) { 1375 | $port = rand($min_port, $max_port); 1376 | } else { 1377 | $port = $post['wan_port']; 1378 | } 1379 | 1380 | // 读取端口池文件 1381 | if (file_exists($port_pool_file_path)) { 1382 | $port_pool_file = fopen($port_pool_file_path, "r"); 1383 | $port_pool_file_json = json_decode(fread($port_pool_file, filesize($port_pool_file_path)), true); 1384 | fclose($port_pool_file); 1385 | } else { 1386 | $port_pool_file_json = []; 1387 | } 1388 | 1389 | $port_taken = false; 1390 | 1391 | foreach ($port_pool_file_json as $key => $value) { 1392 | if ($key == $port) { 1393 | $port_taken = true; 1394 | break; 1395 | } 1396 | } 1397 | 1398 | if (!$port_taken) { 1399 | // 端口没有被占用,执行后续操作 1400 | //if (empty($post['wan_port'])) { 1401 | // 更新端口池文件 1402 | //$port_pool_file_json[$port] = ['server_vmid' => $params['domain']]; 1403 | $port_pool_file_json[$port] = [ 1404 | 'server_vmid' => $params['domain'], 1405 | 'server_ip' => $params['dedicatedip'] 1406 | ]; 1407 | 1408 | $port_pool_file = fopen($port_pool_file_path, "w"); 1409 | fwrite($port_pool_file, json_encode($port_pool_file_json, JSON_PRETTY_PRINT)); 1410 | fclose($port_pool_file); 1411 | //} 1412 | 1413 | $url = $params['configoptions']['ikuai_url'] . "/Action/call"; 1414 | $data['func_name'] = "dnat"; 1415 | $data['action'] = "add"; 1416 | $data['param'] = [ 1417 | "enabled" => "yes", 1418 | "comment" => $post['comment'], 1419 | "interface" => "all", 1420 | "lan_addr" => $post['lan_addr'], 1421 | "protocol" => $post['type'], 1422 | "wan_port" => $port, 1423 | "lan_port" => $post['lan_port'], 1424 | "src_addr" => "" 1425 | ]; 1426 | 1427 | $info = json_decode(proxmoxlxc_nat_request($params, $url, $data), true); 1428 | $info['wan_port'] = $port; 1429 | 1430 | // 写入后台日志 1431 | //active_logs("执行创建映射函数返回结果: " . json_encode($info) . proxmoxlxc_nextid($params) . " | 端口池:" . json_encode($port_pool), $params['uid'], 2); 1432 | active_logs("执行创建映射函数返回结果: " . json_encode($info) . " | 端口池:" . json_encode($port_pool), $params['uid'], 2); 1433 | return $info; 1434 | } elseif (!empty($post['wan_port'])) { 1435 | // 如果 post['wan_port'] 有值且被占用 1436 | return ['ErrMsg' => 'PortCantBeUse']; 1437 | } 1438 | 1439 | // 增加尝试次数 1440 | $port_while_num++; 1441 | } 1442 | } 1443 | 1444 | 1445 | // 之前的,作为备份,不支持外部端口自定义 1446 | // 添加映射 1447 | // function proxmoxlxc_nat_add($params,$post=""){ 1448 | 1449 | // // 判断是从哪里请求的 1450 | // if($post==""){ 1451 | // // 从前台请求的 需要手动拉一下内网ip 1452 | // $post = input('post.'); 1453 | // $post['lan_addr'] = $params['dedicatedip']; 1454 | // } 1455 | 1456 | // // 映射数量限制 1457 | // $nat_list = proxmoxlxc_nat_get_list($params); 1458 | 1459 | // $nat_limit_error = ['ErrMsg' => 'ReachLimit']; 1460 | 1461 | // if ($nat_list['Data']['total'] == $params['configoptions_upgrade']['nat_limit']) { 1462 | // return $nat_limit_error; 1463 | // } 1464 | 1465 | // // 获取端口范围 1466 | // $port_pool = explode(',', $params['configoptions']['port_pool']); 1467 | // $min_port = (int)$port_pool[0]; 1468 | // $max_port = (int)$port_pool[1]; 1469 | 1470 | // // 如果未传递外网端口,就按照端口池随机生成 1471 | // if($post['wan_port']==""){ 1472 | // //$post['wan_port'] = rand(20000,60000); 1473 | // $post['wan_port'] = rand($min_port,$max_port); 1474 | // } 1475 | 1476 | // $url = $params['configoptions']['ikuai_url']."/Action/call"; 1477 | 1478 | 1479 | 1480 | // $data['func_name'] = "dnat"; 1481 | // $data['action'] = "add"; 1482 | // $data['param'] = [ 1483 | // "enabled"=>"yes", 1484 | // "comment"=>$post['comment'], 1485 | // "interface"=>"all", 1486 | // "lan_addr"=> $post['lan_addr'], 1487 | // "protocol"=>$post['type'], 1488 | // "wan_port"=>$post['wan_port'], 1489 | // "lan_port"=>$post['lan_port'], 1490 | // "src_addr"=>"" 1491 | 1492 | // ]; 1493 | 1494 | // $info = json_decode(proxmoxlxc_nat_request($params,$url,$data),true); 1495 | // $info['wan_port'] = $post['wan_port']; 1496 | // // echo json_encode($data); 1497 | 1498 | // // 写入后台日志 1499 | // active_logs("执行创建映射函数返回结果:".json_encode($info),$params['uid'],2); 1500 | // return $info; 1501 | 1502 | // } 1503 | 1504 | 1505 | 1506 | // 删除映射 1507 | function proxmoxlxc_nat_del($params, $post = "") { 1508 | // 判断是从哪里请求的 1509 | if ($post == "") { 1510 | // 从前台请求的 1511 | $post = input('post.'); 1512 | } 1513 | 1514 | // 构建 API 请求 URL 和数据 1515 | $url = $params['configoptions']['ikuai_url'] . "/Action/call"; 1516 | $data['func_name'] = "dnat"; 1517 | $data['action'] = "del"; 1518 | $data['param'] = [ 1519 | "id" => $post['id'], 1520 | ]; 1521 | 1522 | // 发送请求并获取响应 1523 | $info = json_decode(proxmoxlxc_nat_request($params, $url, $data), true); 1524 | 1525 | // 如果删除成功,处理 port_pool.json 文件 1526 | if ($info['ErrMsg'] == 'Success') { 1527 | $port_pool_file_path = __DIR__ . "/port_pool.json"; 1528 | 1529 | if (file_exists($port_pool_file_path)) { 1530 | // 读取端口池文件 1531 | $port_pool_file_content = file_get_contents($port_pool_file_path); 1532 | $port_pool_file_json = json_decode($port_pool_file_content, true); 1533 | 1534 | // 根据请求中的端口号删除相应记录 1535 | $wan_port = $post['wan_port'] ?? null; 1536 | if ($wan_port && array_key_exists($wan_port, $port_pool_file_json)) { 1537 | unset($port_pool_file_json[$wan_port]); 1538 | 1539 | // 保存更新后的端口池文件 1540 | $port_pool_file = fopen($port_pool_file_path, "w"); 1541 | if (flock($port_pool_file, LOCK_EX)) { // 加锁,避免并发问题 1542 | fwrite($port_pool_file, json_encode($port_pool_file_json, JSON_PRETTY_PRINT)); 1543 | fflush($port_pool_file); // 刷新缓冲区 1544 | flock($port_pool_file, LOCK_UN); // 解锁 1545 | } 1546 | fclose($port_pool_file); 1547 | } else { 1548 | // 添加调试日志:未找到要删除的端口 1549 | active_logs("端口 {$wan_port} 不在端口池中或未指定.", $params['uid'], 2); 1550 | } 1551 | } else { 1552 | // 添加调试日志:文件不存在 1553 | active_logs("端口池文件不存在: " . $port_pool_file_path, $params['uid'], 2); 1554 | } 1555 | } else { 1556 | // 添加调试日志:API 删除失败 1557 | active_logs("删除映射 API 返回失败: " . json_encode($info), $params['uid'], 2); 1558 | } 1559 | 1560 | // 写入后台日志 1561 | active_logs("执行删除映射函数返回结果:" . json_encode($info), $params['uid'], 2); 1562 | return $info; 1563 | } 1564 | 1565 | 1566 | 1567 | 1568 | 1569 | 1570 | // 过时的,不能删除port_pool.json文件中的映射记录 1571 | // 删除映射 1572 | // function proxmoxlxc_nat_del($params,$post=""){ 1573 | 1574 | 1575 | // // 判断是从哪里请求的 1576 | // if($post==""){ 1577 | // // 从前台请求的 1578 | // $post = input('post.'); 1579 | // } 1580 | 1581 | 1582 | 1583 | // $url = $params['configoptions']['ikuai_url']."/Action/call"; 1584 | 1585 | 1586 | 1587 | // $data['func_name'] = "dnat"; 1588 | // $data['action'] = "del"; 1589 | // $data['param'] = [ 1590 | // "id"=>$post['id'], 1591 | 1592 | 1593 | // ]; 1594 | 1595 | // $info = json_decode(proxmoxlxc_nat_request($params,$url,$data),true); 1596 | 1597 | // // echo json_encode($data); 1598 | 1599 | // // 写入后台日志 1600 | // active_logs("执行删除映射函数返回结果:".json_encode($info),$params['uid'],2); 1601 | // return $info; 1602 | 1603 | // } 1604 | 1605 | // 请求方法 1606 | function proxmoxlxc_nat_request($params,$url,$data){ 1607 | 1608 | /*登陆获取cookie*/ 1609 | // 定义cookie存放路径 1610 | $cookie_file = dirname(__FILE__).'/cookie/ikuai_'.$params['server_ip'].'.cookie'; 1611 | $login_url = $params['configoptions']['ikuai_url']."/Action/login"; 1612 | // $post_string = "{\"username\":\"admin\",\"passwd\":\"4e62f5790eea7611dd3c3e0ebc6d9c18\",\"pass\":\"c2FsdF8xMXhpYW93ZWlDMTIz\",\"remember_password\":\"true\"}"; 1613 | 1614 | $post_data['username'] = $params['configoptions']['ikuai_username']; 1615 | 1616 | $post_data['passwd']= md5($params['configoptions']['ikuai_password']); 1617 | 1618 | $post_data['pass'] = md5("salt_11".$params['configoptions']['ikuai_password']); 1619 | 1620 | $post_data['remember_password'] = true; 1621 | 1622 | 1623 | 1624 | 1625 | $ch = curl_init($login_url); //初始化 1626 | curl_setopt($ch, CURLOPT_HEADER, 0); //不返回header部分 1627 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //返回字符串,??直接输出 1628 | curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file); //存储cookies 1629 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data)); 1630 | curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); // 屏蔽SSL 1631 | curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE); // 屏蔽SSL 1632 | curl_exec($ch); 1633 | curl_close($ch); 1634 | // echo json_encode($post_data); 1635 | 1636 | 1637 | // 使用cookie请求 1638 | 1639 | $cookie_file = dirname(__FILE__).'/cookie/ikuai_'.$params['server_ip'].'.cookie'; 1640 | 1641 | // $url =$params['configoptions']['ikuai_url']."/Action/call"; 1642 | // $post_string = "{\"func_name\":\"dnat\",\"action\":\"show\",\"param\":{\"TYPE\":\"total,data\",\"limit\":\"0,20\",\"ORDER_BY\":\"\",\"ORDER\":\"\",\"FINDS\":\"lan_addr,lan_port,wan_port,comment\",\"KEYWORDS\":\"172.16.0.2\",\"FILTER1\":\"\",\"FILTER2\":\"\",\"FILTER3\":\"\",\"FILTER4\":\"\",\"FILTER5\":\"\"}}"; 1643 | 1644 | 1645 | // echo "get:".json_encode($dataa); 1646 | 1647 | $ch = curl_init($url); 1648 | curl_setopt($ch, CURLOPT_HEADER, 0); 1649 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 1650 | curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file); //使?上?获取的cookies 1651 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); 1652 | curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); // 屏蔽SSL 1653 | curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE); // 屏蔽SSL 1654 | $response = curl_exec($ch); 1655 | curl_close($ch); 1656 | return $response; 1657 | 1658 | 1659 | 1660 | } 1661 | 1662 | 1663 | /*用户管理相关方法*/ 1664 | 1665 | // 创建用户 1666 | function proxmoxlxc_user_add($params,$username,$password,$vmid){ 1667 | // return FALSE; 1668 | 1669 | // 构建请求参数 1670 | $data['userid'] = $username."@pve"; 1671 | $data['password'] = $password; 1672 | $data['comment'] = "用户:".$params['user_info']['username']."|".$params['user_info']['id']."的VNC账号,服务器编号:".$vmid; 1673 | 1674 | $request = json_decode(proxmoxlxc_request($params,"/api2/extjs/access/users",$data,"POST"),true); 1675 | 1676 | if($request==null){ 1677 | return FALSE; 1678 | } 1679 | 1680 | if($request['success']){ 1681 | // 注册成功 开始分配权限 1682 | 1683 | // 构建参数 1684 | $qx['path'] = "%2Fvms%2F".$vmid; 1685 | $qx['users']= $data['userid']; 1686 | $qx['roles'] = "PVEVMUser"; 1687 | 1688 | // 请求 1689 | $request1 = json_decode(proxmoxlxc_request($params,"/api2/extjs/access/acl",$qx,"PUT"),true); 1690 | 1691 | return $request1; 1692 | 1693 | } 1694 | 1695 | // return "游结果咩:".json_encode($request); 1696 | } 1697 | 1698 | // 删除用户 1699 | function proxmoxlxc_user_del($params){ 1700 | 1701 | $request = json_decode(proxmoxlxc_request($params,"/api2/extjs/access/users/".$params['dedicatedip']."@pve","","DELETE"),true); 1702 | 1703 | if($request==null){ 1704 | return FALSE; 1705 | } 1706 | 1707 | if($request['success']){ 1708 | // 删除成功 开始分配权限 1709 | return true; 1710 | 1711 | 1712 | } 1713 | 1714 | 1715 | } 1716 | 1717 | // 禁用用户 1718 | function proxmoxlxc_user_ban(){ 1719 | proxmoxlxc_HardOff($params); 1720 | 1721 | } 1722 | 1723 | // 解除禁用用户 1724 | function proxmoxlxc_user_unban(){ 1725 | 1726 | } 1727 | 1728 | // 获取用户访问VNC授权 1729 | function proxmoxlxc_get_ticket($params){ 1730 | 1731 | $curl = curl_init(); 1732 | 1733 | $url = $params['server_http_prefix']."://".$params['server_ip'].":".$params['port']."/api2/extjs/access/ticket"; 1734 | curl_setopt($curl,CURLOPT_URL,$url); 1735 | curl_setopt($curl,CURLOPT_POSTFIELDS,"username=".$params['dedicatedip']."&password=".$params['password']."&realm=pve&new-format=1"); 1736 | curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,FALSE); // 屏蔽SSL 1737 | curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,FALSE); // 屏蔽SSL 1738 | curl_setopt($curl, CURLOPT_RETURNTRANSFER,1); 1739 | 1740 | $response = curl_exec($curl); 1741 | $err = curl_error($curl); 1742 | 1743 | curl_close($curl); 1744 | 1745 | if ($err) { 1746 | // 判断服务器请求正常 1747 | return FALSE; 1748 | } else { 1749 | 1750 | $response = json_decode($response,true); 1751 | if($response['success']){ 1752 | return $response['data']['ticket']; 1753 | }else{ 1754 | return FALSE; 1755 | } 1756 | 1757 | } 1758 | 1759 | 1760 | } 1761 | 1762 | // VNC判断是否存在后端文件 1763 | function proxmoxlxc_vnc_if($params){ 1764 | $curl = curl_init(); 1765 | $url = $params['server_http_prefix']."://".$params['server_ip'].":".$params['port']."/novnc/mgnovnc.html"; 1766 | //$url = $params['server_http_prefix']."://".$params['server_ip'].":".$params['port']."/?console=shell&novnc=1"; 1767 | curl_setopt($curl,CURLOPT_URL,$url); 1768 | curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,FALSE); // 屏蔽SSL 1769 | curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,FALSE); // 屏蔽SSL 1770 | curl_setopt($curl, CURLOPT_RETURNTRANSFER,1); 1771 | $response = strval(curl_exec($curl)); 1772 | $err = curl_error($curl); 1773 | 1774 | curl_close($curl); 1775 | 1776 | 1777 | if ($err) { 1778 | return FALSE; 1779 | } else { 1780 | // echo $response; 1781 | if(stripos($response,"Loading")){ 1782 | return true; 1783 | }else{ 1784 | return FALSE; 1785 | } 1786 | // echo "是字符串"; 1787 | 1788 | } 1789 | 1790 | 1791 | } 1792 | 1793 | function proxmoxlxc_request($params,$url,$data="",$method='GET'){ 1794 | 1795 | $url = $params['server_http_prefix']."://".$params['server_ip'].":".$params['port'].$url; 1796 | if($data!=""){ 1797 | 1798 | if($data['no']){ 1799 | // 不格式化 1800 | 1801 | /*注意一下!!!如果后续其他功能BOOM了 绝对是这个造成的!!!! */ 1802 | unset($data['no']); 1803 | 1804 | $body = json_encode($data); 1805 | }else{ 1806 | // 格式化一下要传递的格式 1807 | foreach ($data as $key=>$val) { 1808 | if($body == ""){ 1809 | // 首次 1810 | $body = $key."=".$val."&"; 1811 | }else{ 1812 | $body = $body.$key."=".$val."&"; 1813 | } 1814 | } 1815 | 1816 | } 1817 | 1818 | 1819 | } 1820 | // return $url; 1821 | $ch = curl_init(); //初始化CURL句柄 1822 | curl_setopt($ch, CURLOPT_URL, $url); //设置请求的URL 1823 | curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); //设为TRUE把curl_exec()结果转化为字串,而不是直接输出 1824 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); //设置请求方式 1825 | curl_setopt($ch,CURLOPT_HTTPHEADER,array("X-HTTP-Method-Override: $method","Authorization:PVEAPIToken=".$params['accesshash']));//设置HTTP头信息 携带TOKEN 1826 | curl_setopt($ch, CURLOPT_POSTFIELDS, $body);//设置提交的字符串 1827 | curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); // 屏蔽SSL 1828 | curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE); // 屏蔽SSL 1829 | // curl_setopt($ch, CURLOPT_TIMEOUT,$this->Curl_TimeOut); 1830 | $document = curl_exec($ch);//执行预定义的CURL 1831 | $err = curl_error($ch); 1832 | curl_close($ch); 1833 | $r = mb_convert_encoding($document, 'UTF-8','GBK'); 1834 | 1835 | // 错误处理 1836 | 1837 | if ($err) { 1838 | return "errorCurl:".$err; 1839 | } else { 1840 | return $r; 1841 | } 1842 | 1843 | 1844 | 1845 | } 1846 | 1847 | ?> --------------------------------------------------------------------------------