Compare commits
94 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4b90f8d84 | ||
|
|
472e9c8266 | ||
|
|
cbf686b787 | ||
|
|
e3f2491b56 | ||
|
|
5acc32fb2b | ||
|
|
f614863547 | ||
|
|
49a5d7f317 | ||
|
|
a81013bbc2 | ||
|
|
5432eaad80 | ||
|
|
63f56f8eea | ||
|
|
cc302ed650 | ||
|
|
2d8888138f | ||
|
|
8d3c6e4abd | ||
|
|
f1f16e0826 | ||
|
|
fb9b730355 | ||
|
|
98270007e5 | ||
|
|
3585a6cc1c | ||
|
|
e266fa8c9d | ||
|
|
f4c3f0de0e | ||
|
|
470b1e15d2 | ||
|
|
38a0e9f935 | ||
|
|
e221503cc8 | ||
|
|
7851db7cad | ||
|
|
efe73f8a28 | ||
|
|
f612c84897 | ||
|
|
ea985a2d37 | ||
|
|
60d0a67d40 | ||
|
|
aa54e51c7b | ||
|
|
0f64b5b835 | ||
|
|
b054965528 | ||
|
|
0634a17cdc | ||
|
|
fb08f8ac36 | ||
|
|
86fbffd0b6 | ||
|
|
1e01f1b1a9 | ||
|
|
ecb6a4aa51 | ||
|
|
335ff949be | ||
|
|
3d9bff7e9c | ||
|
|
5d2dfc273e | ||
|
|
7ee297e562 | ||
|
|
22809ce9b3 | ||
|
|
4ae70047ab | ||
|
|
b8266f7f8c | ||
|
|
fe6c1bae56 | ||
|
|
1718d17e5a | ||
|
|
f1e701ac02 | ||
|
|
5d97d34ab1 | ||
|
|
5624ef1bac | ||
|
|
a6e98b75a9 | ||
|
|
4af6008317 | ||
|
|
2d798d1a0e | ||
|
|
655ee29e10 | ||
|
|
5a7c823c40 | ||
|
|
caa173cef4 | ||
|
|
0fd26ef72a | ||
|
|
deedc53eb0 | ||
|
|
d14ee3ce0e | ||
|
|
5f8534e1a9 | ||
|
|
ec1f4fa6e7 | ||
|
|
9d30365d5e | ||
|
|
05e21eb441 | ||
|
|
c7474af62a | ||
|
|
03adc10597 | ||
|
|
e4fe986a6b | ||
|
|
69787b823c | ||
|
|
171eadce0d | ||
|
|
28921ab03d | ||
|
|
ad6aac64f8 | ||
|
|
8e4a3c56d0 | ||
|
|
b3e7e28795 | ||
|
|
40af00ac02 | ||
|
|
9c8a67732d | ||
|
|
f6083d8abd | ||
|
|
e5279e0158 | ||
|
|
e92f35b9f7 | ||
|
|
0a790074e3 | ||
|
|
bddb2d75fb | ||
|
|
b5f5248b78 | ||
|
|
cb3fe9628b | ||
|
|
e73ff1a39b | ||
|
|
b4d9b29805 | ||
|
|
d32d719690 | ||
|
|
39beaf0b07 | ||
|
|
e95913aad9 | ||
|
|
07c4a3cc7e | ||
|
|
0e9d70f189 | ||
|
|
c966c22348 | ||
|
|
c0da37de26 | ||
|
|
5f1292f876 | ||
|
|
df3508ebc9 | ||
|
|
2e9a46b3c3 | ||
|
|
c74308f202 | ||
|
|
cb56d559b2 | ||
|
|
f91048c34e | ||
|
|
ea94ea50a1 |
59
.github/ISSUE_TEMPLATE/🐛-bug-report.md
vendored
@@ -1,37 +1,78 @@
|
||||
---
|
||||
name: "\U0001F41B Bug Report"
|
||||
about: Create a report to help us improve the module!
|
||||
name: "\U0001F41B Bug/Issue Report"
|
||||
about: Report a problem to help us improve the module!
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
**Please describe the module problem clearly:**
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behaviour:
|
||||
**To reproduce for testing, do this:**
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
4. See error (etc etc)
|
||||
|
||||
**Instead, expected behaviour is:**
|
||||
|
||||
**Expected behaviour**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
**Screenshots of the problem (not configs):**
|
||||
|
||||
If applicable, add screenshots to help explain your problem to us.
|
||||
|
||||
Enabling full error displaying should include a stack trace too!
|
||||
|
||||
**Module > Support/Health tab (remove IP and paste here):**
|
||||
- Version of module
|
||||
- Web Server info
|
||||
- PHP version
|
||||
- etc.
|
||||
|
||||
**Config Screenshots: WHMCS Package, Module Plan, PVE, etc:**
|
||||
|
||||
Do not hold back! We need full visibility to help you.
|
||||
|
||||
To help with this, read the README and screenshot **per config step.**
|
||||
|
||||
We spend time making it easy for you to get help - please respect that & help us!
|
||||
|
||||
**WHMCS Information (please complete the following):**
|
||||
|
||||
- WHMCS Version (must be supported):
|
||||
- Using HTTPS: Yes or No
|
||||
- Static, Public IPv4 Address?
|
||||
- Using HTTPS w/ Valid Cert?
|
||||
|
||||
**Proxmox Information (complete the following):**
|
||||
|
||||
- Public IPv4 for Proxmox?
|
||||
- FCrDNS for Proxmox node/s?
|
||||
- VNC configuration followed?
|
||||
|
||||
**WHMCS Debug Log of any failed request + Proxmox Logs:**
|
||||
|
||||
Include the logs, meaning debug log from WHMCS and regular from Proxmox.
|
||||
|
||||
Note: To do this, you need to enable Debug Logging in 2 places. Read the README!
|
||||
|
||||
**Advise how your WHMCS and Proxmox networking is configured**
|
||||
|
||||
- Firewalls?
|
||||
- Dynamic IP or CGNAT?
|
||||
- Did the issue not used to happen?
|
||||
- Describe the connectivity, other behaviours, etc.
|
||||
|
||||
We cannot help if you have an impossible set-up, like Dynamic IP and expecting it to work.
|
||||
|
||||
**Confirm that you have MORE THAN 100 services (all statuses) in WHMCS?**
|
||||
|
||||
Otherwise you will receive a "value does not look like a valid VM ID" error. Check the error!
|
||||
|
||||
**Verify that you have read the README.md file in full - confirm here please.**
|
||||
|
||||
We will close issues which show that insufficient reading, troubleshooting, etc, was undertaken firstly.
|
||||
|
||||
103
CHANGELOG.md
@@ -1,10 +1,107 @@
|
||||
# Changelog
|
||||
All notable changes to Proxmox VE for WHMCS will be documented in this file.
|
||||
|
||||
## [1.3.0] - TBC 2025-??-??
|
||||
## [1.3.x] - TBC 2026-??-??
|
||||
|
||||
https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/milestones
|
||||
|
||||
## [1.2.17] - 2025-10-19 - _"VNC & Hyperscale!"_
|
||||
|
||||
### 💅 Polish
|
||||
- Max Memory: Ensure you can set more than 128GB (#169)
|
||||
- Max CPUs/Cores: Expand column to allow for 100+ (#169)
|
||||
- VNC Prepared: Green background with clearer wording (#167)
|
||||
- Check Status: Allow for client-driven status checks (#168)
|
||||
|
||||
### 🐛 Bug Fix
|
||||
- noVNC: Delete PVEAuthCookie before setting it (#167)
|
||||
- noVNC: PVEAuthCookie is secure & samesite=None (#167)
|
||||
- SQL -> Plans: Expand several fields (future-proof) (#169)
|
||||
|
||||
## [1.2.16] - 2025-10-15 - _"Minor Adjustments"_
|
||||
|
||||
### 💅 Polish
|
||||
- WHMCS Parameter: RequiresServer set to true
|
||||
- Plan Add/Edit: Text descriptions updated
|
||||
- Update Available: Hyperlinked to repo
|
||||
- Admin GUI: Textual layout updates
|
||||
- Servers: PVE Button updated text
|
||||
- README: Final resting milestone
|
||||
|
||||
## [1.2.15] - 2025-08-29 - _"Little Adjustments"_
|
||||
|
||||
### 💅 Polish
|
||||
- NIC #2: Split info (MAC, link status, etc) to multiple lines
|
||||
- SQL Expansion: Prepare for Nodes/ISOs/TPLs/Logs/SSH Keys/etc
|
||||
- Deactivation Keeps Data: No table drops on de-activate (#160)
|
||||
|
||||
### 🐛 Bug Fix
|
||||
- Function Rename: hash_encryption to pvewhmcs_hash_encryption (#159)
|
||||
|
||||
## [1.2.14] - 2025-08-19 - _"Client Area tidy"_
|
||||
|
||||
### 🚀 Feature
|
||||
- Cluster Tasks: Show the cluster history in Admin GUI (#50)
|
||||
|
||||
### 💅 Polish
|
||||
- Admin Area, Server Test: Renamed to "Proxmox VE" for brevity
|
||||
- Admin Area, Pane Titles: Renamed most panes to make it simpler
|
||||
- Client Area: Improved layout and formatting of Guest Info (#155)
|
||||
- Client Area: Improved naming and ordering of Actions menu (#157)
|
||||
- Client Area: Updated 64x64px icons for Running/Suspended/Offline
|
||||
|
||||
### 🐛 Bug Fix
|
||||
- Client Area, Swap %: "NaN%" replaced with "0%" for QEMU (#154)
|
||||
|
||||
## [1.2.13] - 2025-08-13 - _"Little Things"_
|
||||
|
||||
### 💅 Polish
|
||||
- Connection Test: Module shows as "Proxmox VE for WHMCS" (#151)
|
||||
- Apps/Integrations: Now shown with logo & some info (whmcs.json)
|
||||
- WHMCS Admin > Servers: Added a PVE GUI link for each node (#152)
|
||||
|
||||
## [1.2.12] - 2025-08-12 - _"Adjustments"_
|
||||
|
||||
### 🚀 Feature
|
||||
- Cluster / Guest Resources: Add into the Admin GUI (#139)
|
||||
|
||||
### 💅 Polish
|
||||
- Unprivileged CT: At-create-only security option (#105)
|
||||
- Client Area: Running/Suspended/Stopped new icons (#149)
|
||||
|
||||
### 🐛 Bug Fix
|
||||
- Blanket $0.00: Apply fixed nil amount properly (#148)
|
||||
- Import Guest QEMU not KVM: Proper value stored (#150)
|
||||
|
||||
## [1.2.11] - 2025-08-05 - _"Start VMID OK"_
|
||||
|
||||
### 💅 Polish
|
||||
- Virtio Networking: Default set, instead of Intel E1000
|
||||
|
||||
### 🐛 Bug Fix
|
||||
- Start VMID: Change method to `/cluster/nextid` (#145)
|
||||
- Actions & Client Area: Final changes to VMID (#146)
|
||||
|
||||
## [1.2.10] - 2025-07-31 - _"Import Friendly"_
|
||||
|
||||
### 🚀 Feature
|
||||
- Guest Import: Add Service for existing PVE Guest (#75)
|
||||
- PVE VMID: Allow for custom VMID (via Start ID) (#136)
|
||||
- SQL Updates: Beta functionality to auto-patch (#62)
|
||||
- CONTRIBUTORS.md: Recognising key efforts! (#140)
|
||||
|
||||
### 💅 Polish
|
||||
- Fallback Client Area: Use serviceid if no VMID set (#137)
|
||||
- Admin Landing: Auto-select the VM/CT Plans pane/tab (#138)
|
||||
- Minor Wording: Slight adjustments around Module Admin GUI
|
||||
|
||||
### 🐛 Bug Fix
|
||||
- Trunk -> Tag: Wrong parameter name for VLAN ID (#125)
|
||||
- Function Rename: Avoid same name as Virtualizor (#129)
|
||||
- netrate & IPv6: Declare 0 (netrate); add IPv6 DNS (#119)
|
||||
|
||||
(\*): SQL Note: There's column changes in 2x module tables, see [UPDATE-SQL.md](https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/blob/master/UPDATE-SQL.md)
|
||||
|
||||
## [1.2.8] - 2025-04-26 - _"Pause to Refine"_
|
||||
|
||||
### 🚀 Feature
|
||||
@@ -12,12 +109,14 @@ https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/milestones
|
||||
- (LXC Users: ^ means you need to amend Template value)
|
||||
|
||||
### 💅 Polish
|
||||
- LXC Net Rate, QEMU Disk I/O: Apply values (#103)
|
||||
- Addon Module, GUI: Improve attribute phrasing (#103)
|
||||
- Network, Bridge ID: No longer mandatory, re: SDN (#113)
|
||||
- (deps) noVNC: Bump from v1.5.0 to v1.6.0 (#115)
|
||||
- (deps) TigerVNC: "" v1.14.0 to v1.15.0 (#116)
|
||||
|
||||
### 🐛 Bug Fix
|
||||
- LXC Net Rate, QEMU Disk I/O: Apply values (#103)
|
||||
|
||||
(\*): SQL Note: There's a modified column in a module table, see [UPDATE-SQL.md](https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/blob/master/UPDATE-SQL.md)
|
||||
|
||||
## [1.2.7] - 2025-01-02 - _"Terminate Balloons"_
|
||||
|
||||
17
CONTRIBUTORS.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Contributors to Proxmox VE for WHMCS
|
||||
|
||||
This document seeks to say "cheers", "many thanks" & "love your work" to the people and companies who have helped to make this project what it is today.
|
||||
|
||||
## Users who've contributed
|
||||
|
||||
- [@cybercoder](https://github.com/cybercoder)
|
||||
- [@lsthompson](https://github.com/lsthompson)
|
||||
- [@The-Network-Crew](https://github.com/The-Network-Crew)
|
||||
- [@nodespacehosting](https://github.com/nodespacehosting)
|
||||
- [@WaldperlachFabi](https://github.com/WaldperlachFabi)
|
||||
- [@is7Qin](https://github.com/is7Qin)
|
||||
|
||||
## Why not make it even better?
|
||||
|
||||
> [!TIP]
|
||||
> You can always step up and write some improvements to the Module. Why not?
|
||||
518
README.md
@@ -1,14 +1,14 @@
|
||||
# Proxmox VE for WHMCS (Module) Provision & Manage
|
||||
|
||||
**Salvation, a free and open-source solution for beloved PVE!** If you love it, REVIEW & SHARE IT! ❤️
|
||||
<img alt="Logo for the Proxmox VE for WHMCS module" src="_images/logo-pvewhmcs.png">
|
||||
|
||||
**Salvation, a free and open-source solution for beloved PVE!** If you love it, REVIEW & SHARE IT! Cheers. ❤️
|
||||
|
||||
TNC Dev are looking for a co-developer to assist with finishing the project overhaul.
|
||||
If you have proven and public git-logged experience, or similar, please say g'day.
|
||||
|
||||
Please note: We are only looking for high-quality applicants with spare time.
|
||||
As it stands, we won't have much spare dev time for PVEWHMCS in early 2025.
|
||||
|
||||
<img alt="Logo for the Proxmox VE for WHMCS module" src="zLOGO.png">
|
||||
As it stands, we won't have much spare dev time for this Module in 2025.
|
||||
|
||||
- Configure VM/CT plans with custom CPU/RAM/VLAN/On-boot/Bandwidth/etc
|
||||
- Automatically Provision VMs & CTs in **Proxmox VE** from **WHMCS** easily
|
||||
@@ -16,84 +16,117 @@
|
||||
- Create/Suspend/Unsuspend/Terminate via WHMCS Admin Area
|
||||
- Statistics/Graphing is available in the Client Area for services :)
|
||||
- Leverage the power of QEMU & LXC with PVE's convenience
|
||||
- Import existing VM/CT Guest from Proxmox into WHMCS
|
||||
- Choose PVE VMID start & integrate to your schema
|
||||
- Supports 128GB+ RAM & 128+ CPU cores per Guest!
|
||||
|
||||
Repo: https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/
|
||||
https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/
|
||||
|
||||
## ❤️ RTFM: Read the Manual & Review the Module!
|
||||
**Client Area GUI - Landing:**
|
||||
|
||||
**Please read the entire README.md file before getting started with Proxmox VE for WHMCS.** Thanks!
|
||||
<img alt="Client Area GUI showing management of a powered-on VM" src="_images/zVMclientGUI.png">
|
||||
|
||||
We're pretty much done overhauling the Module to suit our needs at The Network Crew Pty Ltd & Merlot Digital.
|
||||
**Admin Area GUI - Landing:**
|
||||
|
||||
<img alt="Admin Area GUI for the Module, showing the Nodes & Guests" src="_images/zClusterGuests.png">
|
||||
|
||||
# ❤️ RTFM: Read the Manual & Review the Module!
|
||||
|
||||
**Please read the entire README.md file before getting started with Proxmox VE for WHMCS (`pvewhmcs`).**
|
||||
|
||||
> **Please review the module!** https://marketplace.whmcs.com/product/6935-proxmox-ve-for-whmcs#reviews
|
||||
>
|
||||
> _If you want it to remain free and fabulous, it could use a moment of your time in reviewing it._ **Thanks!**
|
||||
|
||||
## 🎯 MODULE: System Requirements (PVE/WHMCS)
|
||||
# 🎯 MODULE: System Requirements (PVE/WHMCS)
|
||||
|
||||
### WHMCS must have >100 services!
|
||||
- **(WHMCS)** v8.x.x stable (HTTPS)
|
||||
- **(NET)** WAN Access: WHMCS to PVE
|
||||
- **(VNC)** Special Requirements: PTR, etc.
|
||||
- **(PHP)** v8.x.x (latest stable version)
|
||||
- **(PHP)** max_execution_time = 300
|
||||
- **(Proxmox)** 2 users (API & VNC)
|
||||
- **(Proxmox)** VE v8.x.x (current)
|
||||
|
||||
New Biz: Fresh Installations/Businesses using WHMCS need to take note of the Service ID <100 case.
|
||||
Please note specific VNC & Network requirements below - read 100% of the README.md. :-)
|
||||
|
||||
**SID >100:** The WHMCS Service ID requirement is CRITICAL, as **Proxmox reserves VMIDs <100 (system).**
|
||||
# ✅ MODULE: Installation & Configuration
|
||||
|
||||
_If you don't have enough services (of any status) in WHMCS (DB: tblhosting.id), create enough dummy/test entries to reach Service ID 101+._ **Else you're likely to see an error which explains this:**
|
||||
> [!WARNING]
|
||||
> **DON'T SKIP ANY PART OF THIS README.md & please don't raise pointless Issues - thank you!**
|
||||
|
||||
`HTTP/1.1 400 Parameter verification failed. (invalid format - value does not look like a valid VM ID)`
|
||||
## 📋 1. PREP: Upload & Configure the Module
|
||||
|
||||
To check, browse to your **latest** service in WHMCS, then check the URL - it will reveal the Service ID. If it is less than 100, subtract it from 100 to deduce how many "dummy services" you need to add in a dummy order.
|
||||
**First, read the above System Requirements, and resolve any blockers to using Proxmox VE for WHMCS.**
|
||||
|
||||
Once over 100, it fits the requirement & you're good!
|
||||
### 👥 PVE: User x2 Requirement (API & VNC users)
|
||||
|
||||
### General Requirements
|
||||
|
||||
- (WHMCS) v8.x.x stable (HTTPS)
|
||||
- (WHMCS) **Service ID above 100**
|
||||
- (PHP) v8.x.x (latest stable version)
|
||||
- (PHP) max_execution_time = 300
|
||||
- (Proxmox) VE v8.x (current)
|
||||
- (Proxmox) 2 users (API/VNC)
|
||||
|
||||
## ✅ MODULE: Installation & Configuration
|
||||
|
||||
**DON'T SKIP ANY PART OF THIS README.md - please don't raise pointless Issues - thank you!**
|
||||
|
||||
Firstly, you need to upload, activate and make the WHMCS Module available to Administrators.
|
||||
|
||||
Once you've done all of that, in order to get the module working properly, you need to:
|
||||
|
||||
0. Proxmox VE > Create an additional VNC-only user, per instructions below
|
||||
1. WHMCS Admin > Config > Servers > Add your PVE host/s (user: root; IP: PVE's)
|
||||
2. WHMCS Admin > Addons > Proxmox VE for WHMCS > Module Config > VNC Secret (see below)
|
||||
3. WHMCS Admin > Addons > Proxmox VE for WHMCS > Add KVM/LXC Plan/s
|
||||
4. WHMCS Admin > Addons > Proxmox VE for WHMCS > Add an IP Pool
|
||||
5. WHMCS Admin > Config > Products/Services > New Service (create offering)
|
||||
6. " " > Newly-added Service > Tab 3 > **SAVE** (links Module Plan to WHMCS Service type)
|
||||
|
||||
## 🥽 noVNC: Console Tunnel (Client Area)
|
||||
|
||||
After forking the module, we considered how to improve security of Console Tunneling via WHMCS. We decided to implement a routing method which uses a secondary user in Proxmox VE with very restrictive permissions. This is due to be re-built again to further enhance security.
|
||||
|
||||
### To offer VNC via WHMCS Client Area
|
||||
|
||||
1. Install & configure the module properly
|
||||
2. Follow the PVE User Requirement info below
|
||||
3. Public IPv4 for PVE (or proxy to private)
|
||||
4. PVE and WHMCS on the same Domain Name*
|
||||
5. Have valid PTR/rDNS for the PVE Address
|
||||
|
||||
noVNC has been overhauled. It isn't guaranteed, nor the project at all. :-)
|
||||
|
||||
- Note #1 = You must use different Subdomains on the same Domain Name, for the cookie (anti-CSRF).
|
||||
- Note #2 = If your Domain Name has a 2-part TLD (ie. co.uk) then you will need to fork & amend `novnc_router.php` - ideally we/someone will optimise this to better cater to all formats.
|
||||
|
||||
## 👥 PVE: User Requirements (API & VNC)
|
||||
#### Credentials: root account for each PVE host
|
||||
|
||||
**You must have a root account to use the Module at all.** Configured via WHMCS > Servers.
|
||||
|
||||
Additionally, to improve security, for VNC you must also have a Restricted User. Configured in the _Module_.
|
||||
This is configured in the `pam` realm.
|
||||
|
||||
### Creating the VNC user within PVE
|
||||
#### Credentials: VNC user for Console Access only
|
||||
|
||||
Additionally, to improve security, for VNC you must also have a Restricted User.
|
||||
|
||||
Configured in the _Module_ as detailed below, once you've added/restricted it in PVE.
|
||||
|
||||
### 🏃♂️ Installing the WHMCS Module `pvewhmcs`
|
||||
|
||||
<img alt="WHMCS Server testing OK for a Proxmox VE (pvewhmcs) server/node" src="_images/zServerTestOK.png">
|
||||
|
||||
**First up, get the basics sorted out:**
|
||||
|
||||
0. Upload the Module to your WHMCS installation, ensuring correct permissions/ownership.
|
||||
1. Activate it via WHMCS > Addon Modules > Proxmox VE for WHMCS > Activate.
|
||||
2. In the same spot post-activation, expose the Module to Administrators.
|
||||
3. Make sure your Proxmox host has a valid SSL Certificate installed.
|
||||
4. Ensure you've TCP/8006 connectivity between WHMCS & PVE.
|
||||
|
||||
**Once you've done all of that, in order to get the module working properly, you need to:**
|
||||
|
||||
0. Proxmox VE > Create an additional VNC-only user, per instructions below
|
||||
1. WHMCS Admin > Config > Servers > Add (Advanced) > PVE Host/s (User: `root`; IPv4: `PVE's`; no port suffix!)
|
||||
2. WHMCS Admin > Addons > Proxmox VE for WHMCS > Module Config > VNC Secret (see below)
|
||||
3. WHMCS Admin > Addons > Proxmox VE for WHMCS > Add QEMU/LXC Plan/s
|
||||
4. WHMCS Admin > Addons > Proxmox VE for WHMCS > Add an IPv4 Pool
|
||||
5. WHMCS Admin > Config > Products/Services > New Service (create offering)
|
||||
6. " " > Newly-added Service > Tab 3 > **SAVE** (links Module Plan to WHMCS Service type)
|
||||
7. (Optional) WHMCS Admin > Addons > Proxmox VE for WHMCS > Import Guest
|
||||
|
||||
#### Admin GUI: QEMU Plan :: Creation interface
|
||||
|
||||
<img alt="Plan Creation GUI for adding a new QEMU VM Plan" src="_images/zQEMUplanAdd.png">
|
||||
|
||||
#### Admin GUI: WHMCS Product/Service "Module" SAVE!
|
||||
|
||||
<img alt="Pane/tab where you need to SAVE the module Plan & Pool against the WHMCS Service" src="_images/zProductSave.png">
|
||||
|
||||
#### Admin GUI: WHMCS Servers > Links direct to PVE GUI
|
||||
|
||||
<img alt="WHMCS Admin > Configuration > Servers interface, showing link button to Proxmox GUI, labelled with the PVE hostname" src="_images/zServerListLink.png">
|
||||
|
||||
## 🥽 2. noVNC: Console Tunnel (Client Area)
|
||||
|
||||
After forking the module, we considered how to improve security of Console Tunneling via WHMCS. We decided to implement a routing method which uses a secondary user in Proxmox VE with very restrictive permissions.
|
||||
|
||||
**This is due to be re-built again in 2026 to further enhance security.**
|
||||
|
||||
### How to offer VNC via WHMCS Client Area!
|
||||
|
||||
1. Install & configure the module properly
|
||||
2. Follow the PVE User Requirement info below
|
||||
3. Routed IPv4 for PVE (or TLS-proxy to LAN)
|
||||
4. PVE and WHMCS on the same 1x Domain Name*
|
||||
5. Have valid PTR/rDNS set on the PVE Address
|
||||
|
||||
> **If proxying, that is your sole responsibility to configure & diagnose.**
|
||||
>
|
||||
> Otherwise, PVE must be WAN-accessible and all other configs/reqs satisfied.
|
||||
|
||||
### Creating the VNC User within Proxmox VE
|
||||
|
||||
1. Create User Group "VNC" via PVE > ` Datacenter / Permissions / Group`
|
||||
2. Create new User "vnc" > `Datacenter / Permissions / Users` - Group: "VNC", Realm: pve
|
||||
@@ -101,94 +134,268 @@ Additionally, to improve security, for VNC you must also have a Restricted User.
|
||||
4. Permit VNC Access -> `Datacenter / Permissions / Add Group Permissions` - Group: "VNC", Role: "VNC"
|
||||
5. WHMCS > Modules > Proxmox VE for WHMCS > Module Config > VNC Secret = 'vnc' password (PVE) you set
|
||||
|
||||
> Do NOT set less restrictive permissions. The above is designed for hypervisor security.
|
||||
> [!CAUTION]
|
||||
> Do NOT set less restrictive permissions. The above is designed for interim security.
|
||||
>
|
||||
> However, if you wish for proper security, wait for VNC to be further improved.
|
||||
> **However, if you wish for proper security: wait for VNC to be further improved.**
|
||||
>
|
||||
> **Note**: Custom WHMCS install folders like /clients/ are not yet VNC-supported. #114
|
||||
|
||||
## ⚙️ VM/CT PLANS: Setting everything up
|
||||
<img alt="Client Area GUI showing the reply which links off to the VNC Console/Client" src="_images/zConsoleReady.png">
|
||||
|
||||
These steps explain the unique requirements per-option.
|
||||
### Important info about Console Access
|
||||
|
||||
Custom Fields: Values need to go in Name & Select Options.
|
||||
**noVNC has been overhauled. It isn't guaranteed, nor the project at all. :-)**
|
||||
|
||||
> **Unsure?** Consult the zMANUAL-PVE4.pdf _legacy_ manual file.
|
||||
Once you have it configured, clicking noVNC in Client Area provides direct link - click it:
|
||||
|
||||
### VM Option 1: KVM, using PVE Template VM
|
||||
<img alt="Client Area is ready for you to click into noVNC terminal console" src="_images/zVNCprepared.png">
|
||||
|
||||
Firstly, create the Template in PVE. You need its unique PVE ID.
|
||||
**Here are most of the critical requirements for VNC tunnelling:**
|
||||
|
||||
1. PVE must be at an IPv4 which has PTR the exact same as PVE's hostname.
|
||||
2. You must use different Subdomains on the 1x Domain Name, for the cookie (anti-CSRF).
|
||||
3. If your Domain Name has a 2-part TLD (ie. co.uk) then you will need to fork & amend `novnc_router.php` - ideally we/someone will optimise this down the track.
|
||||
4. You must configure a VNC Secret in the Module Settings, after creating it in PVE.
|
||||
5. You must have a stable and "relatively" static IPv4 fixed/routed WAN address for each PVE host. **CGNAT, Cellular & other "fast DHCP" style configurations cannot be worked with due to a variety of external network issues.** We will not support anything except a perfectly-configured `pvewhmcs`. Thank you!
|
||||
6. Cookies must be properly usable and not manipulated by htaccess or similar rules, to ensure that `PVEAuthCookie` is properly set in-browser, for same-domain cross-subdomain access.
|
||||
|
||||
<img alt="Admin GUI of the Module Config (VNC Secret, Start VMID, Debug Log y/n)" src="_images/zConfiguration.png">
|
||||
|
||||
> [!TIP]
|
||||
> **To troubleshoot noVNC errors like "Connection Closed (1006)":**
|
||||
>
|
||||
> Load noVNC with `logging=debug` added to the query string, ie. `vnc.html?logging=debug`<br>
|
||||
> _Or in Settings change Logging to debug-level, then open JS Console before reloading noVNC._
|
||||
|
||||
## 🌐 3. Networking: IPv4 Pools, IPv6, vmbr/SDN
|
||||
|
||||
### IPv4: Pool required for assignment
|
||||
|
||||
Please make sure you create an IPv4 Pool with sufficient scope/size to be able to deploy addresses within it to your guest VMs and CTs. Else it won't be able to create a Service for you.
|
||||
|
||||
#### Private IPs for PVE Hosts
|
||||
|
||||
Note that VNC may be problematic without work due to the strict requirements introduced in Proxmox v8.0 (strict same-site attribute). Just as SSL/TLS Certificates are no longer trusted for Public IP Addresses, there is increasing work to make the web secure-by-default which makes VNC/etc safer.
|
||||
|
||||
#### Existing Guest Imports from PVE
|
||||
|
||||
Take note that during the Guest Import process, there is no association ensured to an IP Pool, rather we take your inputs and use them verbatim due to existing/current nature of the Guest's configuration.
|
||||
|
||||
### IPv6: SLAAC default (via 2nd vNIC)
|
||||
|
||||
Available options:
|
||||
1. **SLAAC** (2nd vNIC)
|
||||
2. **DHCP** (2nd vNIC)
|
||||
3. **Off** (v4-only)
|
||||
|
||||
You may add different config via PVE/`pvesh` manually of course, if you need to specify a prefix etc.
|
||||
|
||||
### vmbr / SDN: Config type
|
||||
|
||||
This depends on your configuration on the PVE Host/s - bridge (vmbr0 etc) or software-defined (SDN).
|
||||
|
||||
- **If normal (bridged)** - use `vmbr` as the Network, then use `0` as the Interface ID - this makes up `vmbr0`.
|
||||
- **If SDN (Software Defined Network)** - use SDN Name for Network, leave Interface ID blank (= no suffix).
|
||||
|
||||
## ⚙️ 4. VM/CT PLANS: Setting everything up
|
||||
|
||||
These steps explain the unique requirements for QEMU & LXC guests.
|
||||
|
||||
**Custom Fields:** Values need to go in Name & Select Options.<br>
|
||||
This needs configuring for each `WHMCS Admin > Products & Services` entry.
|
||||
|
||||
<img alt="Custom Fields for the Service/Product set the ISO/Template/etc." src="_images/zProductISOetc.png">
|
||||
|
||||
### VM Option 1: QEMU, PVE Template VM Clone
|
||||
|
||||
Firstly, create the Template VM in PVE. You need its unique PVE ID.
|
||||
|
||||
Use that ID in the Custom Field `KVMTemplate`, as in `ID|Name`.
|
||||
|
||||
> Note: `Name` is what's displayed in the WHMCS Client Area.
|
||||
> **Note**: `ID` is the Unique ID that your Template VM has in PVE.<br>
|
||||
> **Note**: `Name` is what will be displayed to your Clients in WHMCS.
|
||||
|
||||
### VM Option 2: KVM, WHMCS Plan + PVE ISO
|
||||
### VM Option 2: QEMU, WHMCS Plan + PVE ISO
|
||||
|
||||
Firstly, create the Plan in WHMCS Module. Then, WHMCS Config > Services.
|
||||
Firstly, create the Plan in WHMCS Module. Then too in WHMCS Config > Services.
|
||||
|
||||
> Under the Service, you need to add a Custom Field `ISO` with the full location.
|
||||
> Under the Service, you need to add a Custom Field `ISO` with the full location.<br>
|
||||
> This ISO must be located on the PVE Host, and not on the WHMCS installation side.
|
||||
|
||||
### CT Option: LXC, using PVE Template File
|
||||
### CT Option 1: LXC, PVE Template File
|
||||
|
||||
Firstly, store the Template in PVE. You need its storage, folder & File Name.
|
||||
|
||||
> Use that prefixed file name in the Custom Field `Template`, as in:<br>
|
||||
> `local:vztmpl/ubuntu-99.99-standard_amd64.tar.gz|Ubuntu 99`
|
||||
|
||||
ie. If using ZFS for Templates, substitute local with volume name.
|
||||
### VM/CT Import/Associate Existing Guest
|
||||
|
||||
Then make a 2nd Custom Field `Password` for the CT's root user.
|
||||
You can associate an existing PVE Guest through the WHMCS Module too, like this:
|
||||
|
||||
## 🌐 IPv4/v6: Networking (IP Pools)
|
||||
<img alt="Importing GUI for linking to existing PVE Guest" src="_images/zVMIDimport.png">
|
||||
|
||||
Please make sure you create an IP Pool with sufficient scope/size to be able to deploy addresses within it to your guest VMs and CTs. Else it won't be able to create a Service for you.
|
||||
> [!CAUTION]
|
||||
> All module-imported services need to be checked and amended to ensure configs such as Billing Cycle, Price, Discount, Assigned IPs, NS1/2, etc, are properly set!
|
||||
|
||||
**Private IPs for PVE Hosts:** Note that VNC may be problematic without work due to the strict requirements introduced in Proxmox v8.0 (strict same-site attribute).
|
||||
### Custom Fields: Important Notes (ZFS/CTs)
|
||||
|
||||
### IPv6: SLAAC default, 2nd vNIC
|
||||
#### ZFS etc: Configure to suit isolated TPLs
|
||||
|
||||
Per The-Network-Crew/Proxmox-VE-for-WHMCS#33 there's SLAAC/DHCP/off available (2x vNICs) (May 2024).
|
||||
- `local` is the name of the file-system that you have the Template on
|
||||
- `vztmpl` is the directoty name per convention, with the ISO within
|
||||
- `ubuntu-99.99-...` etc is the Template file name, exactly as-is
|
||||
|
||||
You can of course add different config via PVE/`pvesh` manually, if you need to specify a prefix.
|
||||
If using ZFS for Templates, substitute `local` with the volume name.
|
||||
|
||||
## 💅 FEATURES: PVE v8.x bling
|
||||
#### Password: Configure the CT's root user
|
||||
|
||||
There are new features deployed into Proxmox VE upstream in the v8 branch which are exciting and should be added to this module.
|
||||
Create a 2nd Custom Field `Password` for the Container's root user on all CT Services.
|
||||
|
||||
### Proxmox v8.0
|
||||
## 🔄 5. PATCH: Updating the Module
|
||||
|
||||
1. Create, manage and assign resource mappings for PCI and USB devices for use in virtual machines (VMs) via API and web UI.
|
||||
2. (DONE) Add virtual machine CPU models based on the x86-64 psABI Micro-Architecture Levels and use the widely supported x86-64-v2-AES as default for new VMs created via the web UI.
|
||||
### Regularly check for updates
|
||||
|
||||
### Proxmox v8.1
|
||||
**WHMCS Admin -> Addon Modules -> Proxmox VE for WHMCS -> Support/Health**
|
||||
|
||||
1. Secure Boot support.
|
||||
2. Software Defined Networking (SDN).
|
||||
3. New flexible notification system (SMTP & Gotify).
|
||||
4. MAC Organizationally Unique Identifier (OUI) BC:24:11: prefix!
|
||||
### Updating to a newer release!
|
||||
|
||||
### Proxmox v8.2
|
||||
1. Download the new version
|
||||
2. Upload it over the top (FTP)
|
||||
3. Login to WHMCS Admin
|
||||
4. Verify all working OK
|
||||
5. **Watch the repo!**
|
||||
|
||||
1. Import Wizard for Guests.
|
||||
2. Unattended PVE Install (answer file).
|
||||
3. Backup Fleecing (local disk as data block buffer).
|
||||
4. Firewall Preview (based on nftables).
|
||||
> **Logging in _should_ trigger the self-upgrade procedure for the SQL database.**
|
||||
>
|
||||
> (**Beta in v1.2.x:** for now, verify yourself that updates were successful)
|
||||
|
||||
### Proxmox v8.3
|
||||
### SQL: Keeping your DB up-to-date
|
||||
|
||||
1. Software-defined Networking/Firewall.
|
||||
2. Better guest importing from OVA/OVF.
|
||||
3. Webhook target for system alerting.
|
||||
4. Better change detection for PBS.
|
||||
> [!IMPORTANT]
|
||||
> Since v1.3.0, logging into WHMCS Admin & opening the module should run any needed SQL Ops.
|
||||
>
|
||||
> v1.2.9 & below, consult the **_docs/UPDATE-SQL.md** file, open your SQL DB & run statements.
|
||||
|
||||
### Proxmox v8.4
|
||||
Then you're done with each update!
|
||||
|
||||
1. Live migrate with mediated devices.
|
||||
2. Support for external backup providers.
|
||||
3. Host dir's, share with guests (virtiofs).
|
||||
_**Note**: db.sql file currently contains new tables for v1.3.x releases as well_
|
||||
|
||||
PVE Roadmap: https://pve.proxmox.com/wiki/Roadmap
|
||||
<img alt="Admin GUI of the Support/Health page (an available update is highlighted)" src="_images/zPatchAvailable.png">
|
||||
|
||||
## 🤬 ABUSE: Zero Tolerance (ZT)
|
||||
## 🆘 6. HELP: Best-effort Support
|
||||
|
||||
> [!WARNING]
|
||||
> We will not support ANY set-ups which do not follow ALL of the set-up processes 100%.
|
||||
>
|
||||
> Read the ENTIRE README, understand it, follow it, and submit detailed Issues.
|
||||
>
|
||||
> Else, do not expect any form of Support. Respect our time. Thank you!
|
||||
|
||||
### Before raising a GitHub Issue, please check:
|
||||
|
||||
1. The Wiki.
|
||||
2. The README.md.
|
||||
3. Open GitHub Issues on the repo.
|
||||
4. HTTP, PHP, WHMCS & debug logs (see below).
|
||||
5. PVE logs; best practices; network; etc.
|
||||
6. Read the errors. Do they explain it?
|
||||
|
||||
### Issues/etc raised must include:
|
||||
|
||||
**Logs:** We work to ensure that Proxmox VE for WHMCS passes through error details to you.
|
||||
|
||||
Hence, we ask that you are as verbose and thorough as possible when reporting Issues. Thanks!
|
||||
|
||||
#### All Logs & Debug Logging too
|
||||
|
||||
- **(Logs: PHP)** `error_log` contents
|
||||
- **(Logs: WHMCS)** Module Debug Logging*
|
||||
- **(Logs: Config)** WHMCS Display/Log Errors = ON
|
||||
- **(Logs: PVE)** Logs from Proxmox Host/s (`pveproxy` etc)
|
||||
|
||||
<img alt="Admin GUI of the WHMCS Module Debug Log interface" src="_images/zModuleDebug.png">
|
||||
|
||||
#### Other Requirements for Support
|
||||
|
||||
- **(Visibility)** Screenshots of the issue
|
||||
- **(Configs)** WHMCS/PHP/Module/Proxmox/etc
|
||||
- **(Reproduction)** `pvesh` etc variants of failing calls
|
||||
- **(Network)** Proof WHMCS Server can talk to PVE OK
|
||||
- **(PEBKAC)** _PROOF THAT YOU'VE FOLLOWED THIS README!_
|
||||
|
||||
**The more info & context you provide up-front, the quicker & easier it will be!**
|
||||
|
||||
\* Debug: Also enable Debug Logging in Proxmox VE for WHMCS > Settings, as needed.
|
||||
|
||||
> [!TIP]
|
||||
> **Please note that this is FOSS and Support is not guaranteed at all.**<br>
|
||||
>
|
||||
> **If you don't read, listen or actively try, no help will be provided.**
|
||||
>
|
||||
> https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/issues/new/choose
|
||||
|
||||
<img alt="Admin GUI showing the Cluster History (PVE Task) log" src="_images/zClusterHistory.png">
|
||||
|
||||
# 💅 FEATURES: Upcoming PVE bling
|
||||
|
||||
There are new features deployed into PVE upstream which are exciting and may be integrated.
|
||||
|
||||
**PVE Roadmap:** https://pve.proxmox.com/wiki/Roadmap
|
||||
|
||||
### Proxmox v9.x
|
||||
|
||||
1. VM snapshots on thick LVM, snapshots as volume chains
|
||||
2. Fabrics for software networking (SDN) Open/OSPF/Ceph/VPN
|
||||
3. Major upgrade to Debian Trixie (testing status in 2025)
|
||||
|
||||
### Proxmox v8.x
|
||||
|
||||
1. Live migrate with mediated devices
|
||||
2. Support for external Backup providers
|
||||
3. Host dir's, share with guests (virtiofs)
|
||||
4. Firewall into Software-defined Networking
|
||||
5. Webhook target for system alerting
|
||||
6. Better change detection for PBS
|
||||
7. (✅) Import Wizard for VMware/etc Guests
|
||||
8. Unattended PVE Install (via answer file)
|
||||
9. Backup Fleecing (local disk as data block buffer)
|
||||
10. Secure Boot support
|
||||
11. (✅) Software Defined Networking (SDN)
|
||||
12. New flexible notification system (SMTP & Gotify)
|
||||
13. MAC Organizationally Unique Identifier (OUI) BC:24:11: prefix!
|
||||
14. Create, manage & assign resource mappings for PCI & USB devices for use in VMs via API and GUI
|
||||
15. (✅) Add CPUs (x86-64 psABI Micro-Architecture Levels) & adopt default x86-64-v2-AES
|
||||
|
||||
### Proxmox 7.x
|
||||
|
||||
1. Cross-cluster guest migrations
|
||||
2. Cluster Resource Scheduling (CRS) launched
|
||||
3. Re-balance CRS on fresh start-up, not just on-recovery
|
||||
4. CRM into HA Manager, as a node maintenance switch
|
||||
|
||||
# 🖥️ INC: Libraries & Dependencies
|
||||
|
||||
| License | Dependency | In-use Ver. | Link to Repository, etc.|
|
||||
|---------|------------|-------------|-------------------------|
|
||||
| **(MIT)** | PHP Client for PVE2 API | **2022/Dec/05** | https://github.com/CpuID/pve2-api-php-client |
|
||||
| **(GPLv2)** | TigerVNC VncViewer.jar | **v1.15.0** | https://sourceforge.net/projects/tigervnc/files/stable/ |
|
||||
| **(MPLv2)** | noVNC HTML5 Viewer | **v1.6.0** | https://github.com/novnc/noVNC/ |
|
||||
| **(GPLv3)** | SPICE HTML5 Viewer | **v0.3** | https://gitlab.freedesktop.org/spice/spice-html5/ |
|
||||
| **(MIT)** | IPv4/SN Validation | **August 2012** | https://github.com/tapmodo/php-ipv4/ |
|
||||
|
||||
# 📄 DIY: Documentation & Resources
|
||||
|
||||
| Developer | Link to Documentation, etc. |
|
||||
|-----------|-----------------------------|
|
||||
| **(PVE API)** | https://pve.proxmox.com/pve-docs/api-viewer/ |
|
||||
| **(TigerVNC)** | https://github.com/TigerVNC/tigervnc/wiki |
|
||||
| **(noVNC)** | https://github.com/novnc/noVNC/wiki |
|
||||
| **(WHMCS)** | https://developers.whmcs.com & https://classdocs.whmcs.com |
|
||||
| **(psABIs)** | https://gitlab.com/x86-psABIs/x86-64-ABI/-/jobs/artifacts/master/raw/x86-64-ABI/abi.pdf?job=build |
|
||||
|
||||
# 🤬 ABUSE: Zero Tolerance (ZT)
|
||||
|
||||
This module has been overhauled and remains functionally-OK but not thoroughly tested nor reviewed.
|
||||
|
||||
@@ -198,94 +405,27 @@ If you cannot accept this, do not download nor use the code. Complaints, nasty r
|
||||
|
||||
**Be grateful & considerate - thank you!**
|
||||
|
||||
## 🆘 HELP: Best-effort Support
|
||||
# 🎉 FOSS: Open-source Contributions
|
||||
|
||||
**Before raising a GitHub Issue, please check:**
|
||||
If you'd like to contribute to the Module, please open a Pull on GitHub >> The-Network-Crew/Proxmox-VE-for-WHMCS >> cheers! _The original module was written in 2 months by @cybercoder for sale online in 2016, though didn't sell any copies so they kindly open-sourced it and removed the licensing requirement._
|
||||
|
||||
1. The Wiki.
|
||||
2. The README.md.
|
||||
3. Open GitHub Issues on the repo.
|
||||
4. HTTP, PHP, WHMCS & debug logs (see below).
|
||||
5. PVE logs; best practices; network; etc.
|
||||
6. Read the errors. Do they explain it?
|
||||
**Thank you to psyborg® for the module's logo design! We love it.**
|
||||
|
||||
> Help: Including logs, details, steps to reproduce, etc, please raise a **GitHub Issue**.
|
||||
>
|
||||
> Logs: We work to ensure that Proxmox VE for WHMCS passes through error details to you.
|
||||
FOSS is only possible thanks to dedicated people around the world! :-)
|
||||
|
||||
### Issues/etc raised must include:
|
||||
**See [CONTRIBUTORS.md](https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/blob/master/CONTRIBUTORS.md) for those who've made PVEWHMCS possible.**
|
||||
|
||||
#### Logging & Debug Logging
|
||||
|
||||
- (Logs: PHP) `error_log` contents
|
||||
- (Logs: WHMCS) Module Debug Logging*
|
||||
- (Logs: Config) WHMCS Display/Log Errors = ON
|
||||
- (Logs: PVE) Logs from Proxmox Host (`pveproxy` etc)
|
||||
|
||||
#### Other Support Requirements
|
||||
|
||||
- (Visibility) Screenshots of the issue
|
||||
- (Configs) WHMCS/PHP/Module/Proxmox/etc
|
||||
- (Reproduction) `pvesh` etc variants of failing calls
|
||||
- (Network) Proof WHMCS Server can talk to PVE OK
|
||||
- (PEBKAC) _PROOF THAT YOU'VE FOLLOWED THIS README!_
|
||||
|
||||
The more info/context you provide up-front, the quicker & easier it will be!
|
||||
|
||||
\* Debug: Also enable Debug Logging in Proxmox VE for WHMCS > Settings, as needed.
|
||||
|
||||
**Please note that this is FOSS and Support is not guaranteed at all.**
|
||||
|
||||
**If you don't read, listen or actively try, no help is given.**
|
||||
|
||||
## 🔄 UPDATING: Patching the Module
|
||||
|
||||
WHMCS Admin > Addon Modules > Proxmox VE for WHMCS > Support/Health shows updates.
|
||||
|
||||
You can download the new version and upload it over the top, then run any needed SQL ops.
|
||||
|
||||
Please consult the **UPDATE-SQL.md** file, open your WHMCS DB & run the statements. Then you're done.
|
||||
|
||||
## 🖥️ INC: Libraries & Dependencies
|
||||
|
||||
- (MIT) PHP Client for PVE2 API (Dec 5th, 2022) https://github.com/CpuID/pve2-api-php-client
|
||||
- (GPLv2) TigerVNC VncViewer.jar (v1.14.0 in repo) https://sourceforge.net/projects/tigervnc/files/stable/
|
||||
- (MPLv2) noVNC HTML5 Viewer (v1.5.0 in repo) https://github.com/novnc/noVNC
|
||||
- (GPLv3) SPICE HTML5 Viewer (v0.3 in repo) https://gitlab.freedesktop.org/spice/spice-html5
|
||||
- (MIT) IPv4/SN Validation (August 2012) https://github.com/tapmodo/php-ipv4/
|
||||
|
||||
## 📄 DIY: Documentation & Resources
|
||||
|
||||
- Proxmox API: https://pve.proxmox.com/pve-docs/api-viewer/
|
||||
- TigerVNC: https://github.com/TigerVNC/tigervnc/wiki
|
||||
- noVNC: https://github.com/novnc/noVNC/wiki
|
||||
- WHMCS: https://developers.whmcs.com/
|
||||
- x86-64-ABI: https://gitlab.com/x86-psABIs/x86-64-ABI/-/jobs/artifacts/master/raw/x86-64-ABI/abi.pdf?job=build
|
||||
|
||||
## 🎉 FOSS: Contributions & Open-source
|
||||
|
||||
If you'd like to contribute to the Module, please open a Pull on GitHub >> The-Network-Crew/Proxmox-VE-for-WHMCS
|
||||
|
||||
The original module was written in 2 months by @cybercoder for sale online in 2016, though didn't sell any copies so they kindly open-sourced it and removed the licensing requirement.
|
||||
|
||||
We would like to thank @cybercoder and @WaldperlachFabi for their original contributions and troubleshooting assistance respectively.
|
||||
|
||||
Thank you to psyborg® for the module's logo design! We love it.
|
||||
|
||||
FOSS is only possible thanks to dedicated individuals!
|
||||
|
||||
## Usage License (GPLv3) & Links to TNC & Co.
|
||||
|
||||
_**This module is licensed under the GNU General Public License (GPL) v3.0.**_
|
||||
|
||||
GPLv3: https://www.gnu.org/licenses/gpl-3.0.txt (by the Free Software Foundation)
|
||||
|
||||
### Corporate Sites: TNC & Merlot Digital
|
||||
# TNC & Co.
|
||||
|
||||
**The Network Crew Pty Ltd** :: https://tnc.works
|
||||
|
||||
**Merlot Digital** :: https://merlot.digital
|
||||
**🍷 Merlot Digital** :: https://merlot.digital
|
||||
|
||||
### Support: Best-effort via GitHub Issues
|
||||
**AS138521** :: Australian family owned
|
||||
|
||||
Browse issues, raise a new one: **GitHub Issues**
|
||||
# GPLv3
|
||||
|
||||
> [!NOTE]
|
||||
> _**This module is licensed under the GNU General Public License (GPL) v3.0.**_
|
||||
>
|
||||
> GPLv3: https://www.gnu.org/licenses/gpl-3.0.txt (by the Free Software Foundation)
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# SQL Statements for Updates (nav to DB first)
|
||||
|
||||
## v1.2.14 & onwards...
|
||||
|
||||
> [!NOTE]
|
||||
> As we transition to auto-updating, you can interpret manual queries in the `pvewhmcs_upgrade` function.
|
||||
>
|
||||
> It is located in the /modules/addons/pvewhmcs/pvewhmcs.php file near-ish the top. Thank you.
|
||||
|
||||
## v1.2.10 to v1.2.12
|
||||
|
||||
```
|
||||
ALTER TABLE mod_pvewhmcs_plans ADD COLUMN `unpriv` int(1) unsigned DEFAULT 0;
|
||||
```
|
||||
|
||||
## v1.2.8 to v1.2.10
|
||||
|
||||
```
|
||||
ALTER TABLE mod_pvewhmcs ADD COLUMN `start_vmid` int(10) DEFAULT 100;
|
||||
ALTER TABLE mod_pvewhmcs_vms ADD COLUMN `vmid` int(10) DEFAULT NULL;
|
||||
UPDATE mod_pvewhmcs_vms SET vmid = id WHERE vmid IS NULL;
|
||||
```
|
||||
|
||||
## v1.2.7 to v1.2.8
|
||||
|
||||
```
|
||||
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
BIN
_images/zClusterGuests.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
_images/zClusterHistory.png
Normal file
|
After Width: | Height: | Size: 469 KiB |
BIN
_images/zConfiguration.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
BIN
_images/zConsoleReady.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
_images/zModuleDebug.png
Normal file
|
After Width: | Height: | Size: 226 KiB |
BIN
_images/zPatchAvailable.png
Normal file
|
After Width: | Height: | Size: 218 KiB |
BIN
_images/zProductISOetc.png
Normal file
|
After Width: | Height: | Size: 162 KiB |
BIN
_images/zProductSave.png
Normal file
|
After Width: | Height: | Size: 179 KiB |
BIN
_images/zQEMUplanAdd.png
Normal file
|
After Width: | Height: | Size: 291 KiB |
BIN
_images/zServerListLink.png
Normal file
|
After Width: | Height: | Size: 381 KiB |
BIN
_images/zServerTestOK.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
_images/zVMIDimport.png
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
_images/zVMclientGUI.png
Normal file
|
After Width: | Height: | Size: 294 KiB |
BIN
_images/zVNCprepared.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
@@ -2,6 +2,7 @@ CREATE TABLE IF NOT EXISTS `mod_pvewhmcs` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`config` varchar(255),
|
||||
`vnc_secret` varchar(255),
|
||||
`start_vmid` int(10) unsigned DEFAULT 100,
|
||||
`debug_mode` tinyint(1) unsigned DEFAULT 0,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
@@ -20,19 +21,64 @@ CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_ip_pools` (
|
||||
`gateway` varchar(100) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_iso` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) NOT NULL,
|
||||
`storage` varchar(20) NOT NULL DEFAULT 'local',
|
||||
`iso_name` varchar(255) NOT NULL,
|
||||
`nodes` int(11) DEFAULT '0',
|
||||
`created` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_logs` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`auth_id` int(11) NOT NULL DEFAULT '0',
|
||||
`user_id` int(11) NOT NULL DEFAULT '0',
|
||||
`service` int(11) NOT NULL DEFAULT '0',
|
||||
`timestamp` datetime NOT NULL,
|
||||
`node_id` int(11) NOT NULL DEFAULT '0',
|
||||
`target_id` int(11) NOT NULL DEFAULT '0',
|
||||
`level` varchar(10) NOT NULL,
|
||||
`type` text NOT NULL,
|
||||
`action` text NOT NULL,
|
||||
`request` text NOT NULL,
|
||||
`response` text NOT NULL,
|
||||
`raw` text NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_nodes` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`pve_id` int(11) NOT NULL,
|
||||
`pve_name` varchar(255) NOT NULL,
|
||||
`whmcs_id` int(11) NOT NULL,
|
||||
`title` varchar(255) NOT NULL,
|
||||
`ip` varchar(100) NOT NULL,
|
||||
`pve_ver` varchar(20) NOT NULL DEFAULT '9.0.0',
|
||||
`status` varchar(20) NOT NULL DEFAULT 'active',
|
||||
`max_guests` int(5) NOT NULL DEFAULT '20',
|
||||
`health` text DEFAULT NULL,
|
||||
`load_avg` varchar(100) DEFAULT NULL,
|
||||
`load_crs` varchar(255) DEFAULT NULL,
|
||||
`notifiers` text DEFAULT NULL,
|
||||
`resources` text DEFAULT NULL,
|
||||
`supports` varchar(255) NOT NULL DEFAULT 'vm,ct',
|
||||
`templates` varchar(1000) NOT NULL DEFAULT '',
|
||||
`created` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_plans` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) CHARACTER SET utf8 NOT NULL,
|
||||
`vmtype` varchar(8) NOT NULL,
|
||||
`ostype` varchar(8) DEFAULT NULL,
|
||||
`cpus` tinyint(2) unsigned DEFAULT NULL,
|
||||
`cpus` smallint(4) unsigned DEFAULT NULL,
|
||||
`cpuemu` varchar(30) CHARACTER SET utf8 DEFAULT NULL,
|
||||
`cores` tinyint(2) unsigned DEFAULT NULL,
|
||||
`cores` smallint(4) unsigned DEFAULT NULL,
|
||||
`cpulimit` smallint(5) unsigned DEFAULT NULL,
|
||||
`cpuunits` smallint(5) unsigned DEFAULT NULL,
|
||||
`memory` smallint(5) unsigned NOT NULL,
|
||||
`swap` smallint(5) unsigned DEFAULT NULL,
|
||||
`disk` smallint(5) unsigned DEFAULT NULL,
|
||||
`memory` int(10) unsigned NOT NULL,
|
||||
`swap` int(10) unsigned DEFAULT NULL,
|
||||
`disk` int(10) unsigned DEFAULT NULL,
|
||||
`diskformat` varchar(10) DEFAULT NULL,
|
||||
`diskcache` varchar(20) DEFAULT NULL,
|
||||
`disktype` varchar(20) DEFAULT NULL,
|
||||
@@ -40,20 +86,42 @@ CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_plans` (
|
||||
`diskio` varchar(20) DEFAULT '0',
|
||||
`netmode` varchar(10) DEFAULT NULL,
|
||||
`bridge` varchar(20) NOT NULL DEFAULT 'vmbr',
|
||||
`vmbr` tinyint(1) unsigned DEFAULT NULL,
|
||||
`vmbr` tinyint(3) unsigned DEFAULT NULL,
|
||||
`netmodel` varchar(10) DEFAULT NULL,
|
||||
`netrate` varchar(5) DEFAULT '0',
|
||||
`netrate` int(10) DEFAULT '0',
|
||||
`firewall` tinyint(1) unsigned NOT NULL DEFAULT 0,
|
||||
`bw` int(6) unsigned DEFAULT 0,
|
||||
`bw` int(10) unsigned DEFAULT 0,
|
||||
`kvm` tinyint(1) unsigned DEFAULT 0,
|
||||
`onboot` tinyint(1) unsigned DEFAULT 0,
|
||||
`vlanid` varchar(10) DEFAULT NULL,
|
||||
`vlanid` int(10) DEFAULT NULL,
|
||||
`ipv6` varchar(10) DEFAULT 'auto',
|
||||
`balloon` varchar(10) DEFAULT '0',
|
||||
`balloon` int(10) DEFAULT '0',
|
||||
`unpriv` tinyint(1) unsigned DEFAULT 0,
|
||||
`ssh-keys` varchar(100) DEFAULT '',
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_ssh_keys` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) NOT NULL DEFAULT '',
|
||||
`ssh_key` text NOT NULL,
|
||||
`created` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_templates` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`tpl_id` int(11) DEFAULT NULL,
|
||||
`title` varchar(255) NOT NULL,
|
||||
`guest` varchar(8) NOT NULL DEFAULT 'vm',
|
||||
`ostype` varchar(8) DEFAULT NULL,
|
||||
`storage` varchar(20) DEFAULT 'local',
|
||||
`template` varchar(255) DEFAULT NULL,
|
||||
`nodes` int(11) DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_vms` (
|
||||
`id` int(10) unsigned NOT NULL,
|
||||
`vmid` int(10) unsigned DEFAULT NULL,
|
||||
`node_id` int(10) unsigned DEFAULT NULL,
|
||||
`user_id` int(10) unsigned NOT NULL,
|
||||
`vtype` varchar(255) NOT NULL,
|
||||
`ipaddress` varchar(255) NOT NULL,
|
||||
@@ -62,4 +130,4 @@ CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_vms` (
|
||||
`created` datetime DEFAULT NULL,
|
||||
`v6prefix` varchar(128) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
);
|
||||
@@ -19,7 +19,6 @@
|
||||
<img src="/modules/servers/pvewhmcs/img/{$vm_status['status']}.png"/><br/>
|
||||
<span style="text-transform: uppercase"><strong><i>{$vm_status['status']}</i></strong></span><br/>
|
||||
Up: {$vm_status['uptime']}
|
||||
|
||||
</div>
|
||||
<div class="col col-md-7">
|
||||
<div class="row">
|
||||
@@ -57,28 +56,13 @@
|
||||
|
||||
<table class="table table-bordered table-striped">
|
||||
<tr>
|
||||
<td><strong>IP</strong> (Addressing)</td><td><strong>{$vm_config['ipv4']}</strong><br/>Subnet Mask: {$vm_config['netmask4']}<br/>Gateway: {$vm_config['gateway4']}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>OS/etc</strong> (System)</td>
|
||||
<td>Kernel: {$vm_config['ostype']}</td>
|
||||
<td><strong>Memory</strong> (RAM)</td>
|
||||
<td><strong>{$vm_config['memory']}MB</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Compute</strong> (CPU)</td>
|
||||
<td>{$vm_config['sockets']} socket/s, {$vm_config['cores']} core/s<br />
|
||||
Emulation: {$vm_config['cpu']}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Memory</strong> (RAM)</td>
|
||||
<td>{$vm_config['memory']}MB</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>NIC</strong> (Interface #1)</td>
|
||||
<td>{($vm_config['net0']|replace:',':'<br/>')}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>NIC</strong> (Interface #2)</td>
|
||||
<td>{$vm_config['net1']}</td>
|
||||
<td><strong>{$vm_config['cpu']} {$vm_config['cores']} core/s on {$vm_config['sockets']} socket/s
|
||||
</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Storage</strong> (SSD/HDD)</td>
|
||||
@@ -91,6 +75,21 @@
|
||||
{($vm_config['virtio0']|replace:',':'<br/>')}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>OS/etc</strong> (System)</td>
|
||||
<td>Kernel: {$vm_config['ostype']}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>IPv4</strong> (Network)</td><td><strong>{$vm_config['ipv4']}</strong><br/>Mask: {$vm_config['netmask4']}<br/>Gateway: {$vm_config['gateway4']}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>NIC</strong> (Interface #1)</td>
|
||||
<td>{($vm_config['net0']|replace:',':'<br/>')}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>NIC</strong> (Interface #2)</td>
|
||||
<td>{($vm_config['net1']|replace:',':'<br/>')}</td>
|
||||
</tr>
|
||||
</table>
|
||||
{if ($smarty.get.a eq 'vmStat')}
|
||||
<h4>VM Statistics</h4>
|
||||
|
||||
BIN
modules/servers/pvewhmcs/img/logo.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 6.1 KiB |
@@ -21,6 +21,11 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Delete the authentication cookie, if it exists
|
||||
if (isset($_COOKIE['PVEAuthCookie'])) {
|
||||
unset($_COOKIE['PVEAuthCookie']);
|
||||
}
|
||||
|
||||
if (isset($_GET['pveticket']) && isset($_GET['host']) && isset($_GET['path']) && isset($_GET['vncticket'])) {
|
||||
// Take passed-in variables and re-assign for usage
|
||||
$pveticket = $_GET['pveticket'];
|
||||
@@ -33,7 +38,14 @@ if (isset($_GET['pveticket']) && isset($_GET['host']) && isset($_GET['path']) &&
|
||||
// Now extract just the domain parts we need (FUTURE: capacity/option for multi-part TLDs)
|
||||
$domainonly = preg_replace("/^(.*?)\.(.*)$/","$2",$whmcsdomain['path']);
|
||||
// Set the cookie as Proxmox will be expecting it, so it is WHMCS to VNC without further login
|
||||
setrawcookie('PVEAuthCookie', $pveticket, 0, '/', $domainonly);
|
||||
setrawcookie('PVEAuthCookie', $pveticket, [
|
||||
'expires' => 0,
|
||||
'path' => '/',
|
||||
'domain' => $domainonly,
|
||||
'secure' => true,
|
||||
'httponly' => false,
|
||||
'samesite' => 'None',
|
||||
]);
|
||||
|
||||
// Create the final noVNC URL with the re-encoded vncticket
|
||||
$hostname = gethostbyaddr($host);
|
||||
@@ -47,4 +59,4 @@ if (isset($_GET['pveticket']) && isset($_GET['host']) && isset($_GET['path']) &&
|
||||
echo 'Error: Missing required info to route your request. Please try again.';
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
?>
|
||||
@@ -6,6 +6,7 @@
|
||||
File: /modules/servers/pvewhmcs/pvewhmcs.php (PVE Work)
|
||||
|
||||
Copyright (C) The Network Crew Pty Ltd (TNC) & Co.
|
||||
For other Contributors to PVEWHMCS, see CONTRIBUTORS.md
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -33,6 +34,33 @@ use Illuminate\Database\Capsule\Manager as Capsule;
|
||||
// Prepare to source Guest type
|
||||
global $guest;
|
||||
|
||||
// Fix the Server Test showing "Pvewhmcs" instead of pretty name
|
||||
// ref: https://developers.whmcs.com/provisioning-modules/meta-data-params/
|
||||
function pvewhmcs_MetaData() {
|
||||
return array(
|
||||
'DisplayName' => 'Proxmox VE',
|
||||
'APIVersion' => '1.1',
|
||||
'RequiresServer' => 'true',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* AdminLink: show a direct link to the Proxmox UI on :8006.
|
||||
* Falls back to server IP if hostname is empty.
|
||||
*/
|
||||
function pvewhmcs_AdminLink(array $params) {
|
||||
$host = $params['serverhostname'] ?: $params['serverip'];
|
||||
if (!$host) {
|
||||
// Nothing to link to – return the module page as a safe fallback
|
||||
return '<a href="addonmodules.php?module=pvewhmcs">Module Config</a>';
|
||||
}
|
||||
|
||||
$url = 'https://' . $host . ':8006';
|
||||
return '<form action="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '" method="get" target="_blank">
|
||||
<input type="submit" value="Log in to PVE" class="btn btn-sm btn-default" />
|
||||
</form>';
|
||||
}
|
||||
|
||||
// WHMCS CONFIG > SERVICES/PRODUCTS > Their Service > Tab #3 (Plan/Pool)
|
||||
function pvewhmcs_ConfigOptions() {
|
||||
// Retrieve PVE for WHMCS Cluster
|
||||
@@ -40,16 +68,16 @@ function pvewhmcs_ConfigOptions() {
|
||||
|
||||
// Retrieve Plans
|
||||
foreach (Capsule::table('mod_pvewhmcs_plans')->get() as $plan) {
|
||||
$plans[$plan->id]=$plan->vmtype.' : '.$plan->title ;
|
||||
$plans[$plan->id] = '(' . $plan->vmtype . ') ' . $plan->title ;
|
||||
}
|
||||
|
||||
// Retrieve IP Pools
|
||||
foreach (Capsule::table('mod_pvewhmcs_ip_pools')->get() as $ippool) {
|
||||
$ippools[$ippool->id]=$ippool->title ;
|
||||
$ippools[$ippool->id] = $ippool->title ;
|
||||
}
|
||||
|
||||
/*
|
||||
$proxmox = new PVE2_API($server->ipaddress, $server->username, "pam", get_server_pass_from_whmcs($server->password));
|
||||
$proxmox = new PVE2_API($server->ipaddress, $server->username, "pam", pvewhmcs_get_whmcs_server_password($server->password));
|
||||
if ($proxmox->login()) {
|
||||
# Get first node name.
|
||||
$nodes = $proxmox->get_node_list();
|
||||
@@ -74,13 +102,13 @@ function pvewhmcs_ConfigOptions() {
|
||||
"FriendlyName" => "PVE Plan",
|
||||
"Type" => "dropdown",
|
||||
'Options' => $plans ,
|
||||
"Description" => "KVM/LXC : Plan Name"
|
||||
"Description" => "(QEMU/LXC) Plan Name"
|
||||
),
|
||||
"IPPool" => array(
|
||||
"FriendlyName" => "IPv4 Pool",
|
||||
"Type" => "dropdown",
|
||||
'Options'=> $ippools,
|
||||
"Description" => "IPv4 : Allocation Pool"
|
||||
"Description" => "(IPv4) Allocation Pool"
|
||||
),
|
||||
);
|
||||
|
||||
@@ -115,6 +143,9 @@ function pvewhmcs_CreateAccount($params) {
|
||||
// Select an IP Address from Pool
|
||||
$ip = Capsule::select('select ipaddress,mask,gateway from mod_pvewhmcs_ip_addresses i INNER JOIN mod_pvewhmcs_ip_pools p on (i.pool_id=p.id and p.id=' . $params['configoption2'] . ') where i.ipaddress not in(select ipaddress from mod_pvewhmcs_vms) limit 1')[0];
|
||||
|
||||
// Get the starting VMID from the config options
|
||||
$vmid = Capsule::table('mod_pvewhmcs')->where('id', '1')->value('start_vmid');
|
||||
|
||||
////////////////////////
|
||||
// CREATE IF QEMU/KVM //
|
||||
////////////////////////
|
||||
@@ -126,7 +157,9 @@ function pvewhmcs_CreateAccount($params) {
|
||||
$nodes = $proxmox->get_node_list();
|
||||
$first_node = $nodes[0];
|
||||
unset($nodes);
|
||||
$vm_settings['newid'] = $params["serviceid"];
|
||||
// Find the next available VMID by checking if the VMID exists either for QEMU or LXC
|
||||
$vmid = pvewhmcs_find_next_available_vmid($proxmox, $first_node, $vmid);
|
||||
$vm_settings['newid'] = $vmid;
|
||||
$vm_settings['name'] = "vps" . $params["serviceid"] . "-cus" . $params['clientsdetails']['userid'];
|
||||
$vm_settings['full'] = true;
|
||||
// KVM TEMPLATE - Conduct the VM CLONE from Template to Machine
|
||||
@@ -182,6 +215,7 @@ function pvewhmcs_CreateAccount($params) {
|
||||
Capsule::table('mod_pvewhmcs_vms')->insert(
|
||||
[
|
||||
'id' => $params['serviceid'],
|
||||
'vmid' => $vmid,
|
||||
'user_id' => $params['clientsdetails']['userid'],
|
||||
'vtype' => 'qemu',
|
||||
'ipaddress' => $ip->ipaddress,
|
||||
@@ -211,7 +245,8 @@ function pvewhmcs_CreateAccount($params) {
|
||||
// PREPARE SETTINGS FOR QEMU/LXC EVENTUALITIES //
|
||||
/////////////////////////////////////////////////
|
||||
} else {
|
||||
$vm_settings['vmid'] = $params["serviceid"];
|
||||
// No longer inheriting WHMCS Service ID, so //
|
||||
// $vm_settings['vmid'] = $params["serviceid"];
|
||||
if ($plan->vmtype == 'lxc') {
|
||||
///////////////////////////
|
||||
// LXC: Preparation Work //
|
||||
@@ -220,6 +255,7 @@ function pvewhmcs_CreateAccount($params) {
|
||||
$vm_settings['swap'] = $plan->swap;
|
||||
$vm_settings['rootfs'] = $plan->storage . ':' . $plan->disk;
|
||||
$vm_settings['bwlimit'] = $plan->diskio;
|
||||
$vm_settings['nameserver'] = '1.1.1.1 1.0.0.1';
|
||||
$vm_settings['net0'] = 'name=eth0,bridge=' . $plan->bridge . $plan->vmbr . ',ip=' . $ip->ipaddress . '/' . mask2cidr($ip->mask) . ',gw=' . $ip->gateway . ',rate=' . $plan->netrate;
|
||||
if (!empty($plan->ipv6) && $plan->ipv6 != '0') {
|
||||
// Standard prep for the 2nd int.
|
||||
@@ -227,10 +263,12 @@ function pvewhmcs_CreateAccount($params) {
|
||||
switch ($plan->ipv6) {
|
||||
case 'auto':
|
||||
// Pass in auto, triggering SLAAC
|
||||
$vm_settings['nameserver'] .= ' 2606:4700:4700::1111 2606:4700:4700::1001';
|
||||
$vm_settings['net1'] .= ',ip6=auto';
|
||||
break;
|
||||
case 'dhcp':
|
||||
// DHCP for IPv6 option
|
||||
$vm_settings['nameserver'] .= ' 2606:4700:4700::1111 2606:4700:4700::1001';
|
||||
$vm_settings['net1'] .= ',ip6=dhcp';
|
||||
break;
|
||||
case 'prefix':
|
||||
@@ -240,14 +278,14 @@ function pvewhmcs_CreateAccount($params) {
|
||||
break;
|
||||
}
|
||||
if (!empty($plan->vlanid)) {
|
||||
$vm_settings['net1'] .= ',trunk=' . $plan->vlanid;
|
||||
$vm_settings['net1'] .= ',tag=' . $plan->vlanid;
|
||||
}
|
||||
}
|
||||
if (!empty($plan->vlanid)) {
|
||||
$vm_settings['net0'] .= ',trunk=' . $plan->vlanid;
|
||||
$vm_settings['net0'] .= ',tag=' . $plan->vlanid;
|
||||
}
|
||||
$vm_settings['nameserver'] = '76.76.2.0 76.76.10.0';
|
||||
$vm_settings['onboot'] = $plan->onboot;
|
||||
$vm_settings['unprivileged'] = $plan->unpriv;
|
||||
$vm_settings['password'] = $params['customfields']['Password'];
|
||||
} else {
|
||||
////////////////////////////
|
||||
@@ -257,15 +295,18 @@ function pvewhmcs_CreateAccount($params) {
|
||||
$vm_settings['sockets'] = $plan->cpus;
|
||||
$vm_settings['cores'] = $plan->cores;
|
||||
$vm_settings['cpu'] = $plan->cpuemu;
|
||||
$vm_settings['nameserver'] = '1.1.1.1 1.0.0.1';
|
||||
$vm_settings['ipconfig0'] = 'ip=' . $ip->ipaddress . '/' . mask2cidr($ip->mask) . ',gw=' . $ip->gateway;
|
||||
if (!empty($plan->ipv6) && $plan->ipv6 != '0') {
|
||||
switch ($plan->ipv6) {
|
||||
case 'auto':
|
||||
// Pass in auto, triggering SLAAC
|
||||
$vm_settings['nameserver'] .= ' 2606:4700:4700::1111 2606:4700:4700::1001';
|
||||
$vm_settings['ipconfig1'] = 'ip6=auto';
|
||||
break;
|
||||
case 'dhcp':
|
||||
// DHCP for IPv6 option
|
||||
$vm_settings['nameserver'] .= ' 2606:4700:4700::1111 2606:4700:4700::1001';
|
||||
$vm_settings['ipconfig1'] = 'ip6=dhcp';
|
||||
break;
|
||||
case 'prefix':
|
||||
@@ -275,7 +316,6 @@ function pvewhmcs_CreateAccount($params) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$vm_settings['nameserver'] = '76.76.2.0 76.76.10.0';
|
||||
$vm_settings['kvm'] = $plan->kvm;
|
||||
$vm_settings['onboot'] = $plan->onboot;
|
||||
|
||||
@@ -301,7 +341,7 @@ function pvewhmcs_CreateAccount($params) {
|
||||
$vm_settings['net0'] .= ',rate=' . $plan->netrate;
|
||||
}
|
||||
if (!empty($plan->vlanid)) {
|
||||
$vm_settings['net0'] .= ',trunk=' . $plan->vlanid;
|
||||
$vm_settings['net0'] .= ',tag=' . $plan->vlanid;
|
||||
}
|
||||
// IPv6: Same configs for second interface
|
||||
if (isset($vm_settings['ipconfig1'])) {
|
||||
@@ -314,7 +354,7 @@ function pvewhmcs_CreateAccount($params) {
|
||||
$vm_settings['net1'] .= ',rate=' . $plan->netrate;
|
||||
}
|
||||
if (!empty($plan->vlanid)) {
|
||||
$vm_settings['net1'] .= ',trunk=' . $plan->vlanid;
|
||||
$vm_settings['net1'] .= ',tag=' . $plan->vlanid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -336,6 +376,10 @@ function pvewhmcs_CreateAccount($params) {
|
||||
$first_node = $nodes[0];
|
||||
unset($nodes);
|
||||
|
||||
// Find the next available VMID by checking if the VMID exists either for QEMU or LXC
|
||||
$vmid = pvewhmcs_find_next_available_vmid($proxmox, $first_node, $vmid);
|
||||
$vm_settings['vmid'] = $vmid;
|
||||
|
||||
if ($plan->vmtype == 'kvm') {
|
||||
$v = 'qemu';
|
||||
} else {
|
||||
@@ -395,6 +439,7 @@ function pvewhmcs_CreateAccount($params) {
|
||||
Capsule::table('mod_pvewhmcs_vms')->insert(
|
||||
[
|
||||
'id' => $params['serviceid'],
|
||||
'vmid' => $vmid,
|
||||
'user_id' => $params['clientsdetails']['userid'],
|
||||
'vtype' => $v,
|
||||
'ipaddress' => $ip->ipaddress,
|
||||
@@ -427,6 +472,52 @@ function pvewhmcs_CreateAccount($params) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the next free VMID cluster-wide by probing /cluster/nextid.
|
||||
* Returns the first VMID >= $start_vmid for which /cluster/nextid?vmid=X returns X.
|
||||
*
|
||||
* @param PVE2_API $proxmox Proxmox API client
|
||||
* @param string $node Ignored (VMIDs are cluster-wide)
|
||||
* @param int $start_vmid Starting VMID from Module config
|
||||
* @return int
|
||||
* @throws Exception on unexpected API errors or if cap exceeded
|
||||
*/
|
||||
function pvewhmcs_find_next_available_vmid($proxmox, $node, $start_vmid) {
|
||||
$max_attempts = 1000; // Safety cap to avoid infinite loops
|
||||
$vmid = (int) $start_vmid; // Starting with configured VMID
|
||||
|
||||
for ($i = 0; $i < $max_attempts; $i++, $vmid++) {
|
||||
try {
|
||||
// Proxmox API: is this VMID vacant?
|
||||
// If vacant, servers echo it back in 'data'.
|
||||
$resp = $proxmox->get('/cluster/nextid', ['vmid' => $vmid]);
|
||||
|
||||
// Different PHP clients return either ['data' => '123'] or just '123'
|
||||
$data = (is_array($resp) && array_key_exists('data', $resp)) ? $resp['data'] : $resp;
|
||||
|
||||
if ((int) $data === $vmid) {
|
||||
return $vmid; // confirmed vacant
|
||||
}
|
||||
|
||||
// If the API returns a *different* number here, we ignore it and keep probing
|
||||
continue;
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
$msg = strtolower($e->getMessage());
|
||||
|
||||
// Occupied case looks like: "400 Parameter verification failed. vmid: VM 106 already exists"
|
||||
if (strpos($msg, 'already exists') !== false || strpos($msg, 'parameter verification failed') !== false) {
|
||||
continue; // try the next VMID
|
||||
}
|
||||
|
||||
// Any other error is unexpected; surface it.
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Unable to find a free VMID starting at {$start_vmid} after {$max_attempts} attempts");
|
||||
}
|
||||
|
||||
// PVE API FUNCTION, ADMIN: Test Connection with Proxmox node
|
||||
function pvewhmcs_TestConnection(array $params) {
|
||||
try {
|
||||
@@ -476,8 +567,8 @@ function pvewhmcs_SuspendAccount(array $params) {
|
||||
$guest=Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
|
||||
$pve_cmdparam = array();
|
||||
// Log and fire request
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/stop';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/stop' , $pve_cmdparam);
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/stop';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/stop' , $pve_cmdparam);
|
||||
}
|
||||
// DEBUG - Log the request parameters before it's fired
|
||||
if (Capsule::table('mod_pvewhmcs')->where('id', '1')->value('debug_mode') == 1) {
|
||||
@@ -513,8 +604,8 @@ function pvewhmcs_UnsuspendAccount(array $params) {
|
||||
$guest=Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
|
||||
$pve_cmdparam = array();
|
||||
// Log and fire request
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/start';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/start');
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/start';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/start');
|
||||
}
|
||||
// DEBUG - Log the request parameters before it's fired
|
||||
if (Capsule::table('mod_pvewhmcs')->where('id', '1')->value('debug_mode') == 1) {
|
||||
@@ -551,13 +642,13 @@ function pvewhmcs_TerminateAccount(array $params) {
|
||||
$guest=Capsule::table('mod_pvewhmcs_vms')->where('id', '=', $params['serviceid'])->get()[0];
|
||||
$pve_cmdparam = array();
|
||||
// Stop the service if it is not already stopped
|
||||
$guest_specific = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'].'/status/current');
|
||||
$guest_specific = $proxmox->get('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/current');
|
||||
if ($guest_specific['status'] != 'stopped') {
|
||||
$proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/stop' , $pve_cmdparam);
|
||||
$proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/stop' , $pve_cmdparam);
|
||||
sleep(30);
|
||||
}
|
||||
|
||||
if ($proxmox->delete('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'],array('skiplock'=>1))) {
|
||||
if ($proxmox->delete('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid,array('skiplock'=>1))) {
|
||||
// Delete entry from module table once service terminated in PVE
|
||||
Capsule::table('mod_pvewhmcs_vms')->where('id', '=', $params['serviceid'])->delete();
|
||||
return "success";
|
||||
@@ -568,7 +659,7 @@ function pvewhmcs_TerminateAccount(array $params) {
|
||||
}
|
||||
|
||||
// GENERAL CLASS: WHMCS Decrypter
|
||||
class hash_encryption {
|
||||
class pvewhmcs_hash_encryption {
|
||||
/**
|
||||
* Hashed value of the user provided encryption key
|
||||
* @var string
|
||||
@@ -601,7 +692,7 @@ class hash_encryption {
|
||||
* @param boold $base64 Enable base64 en- / decoding
|
||||
* @return mixed
|
||||
*/
|
||||
function hash_encryption($key, $base64 = true) {
|
||||
function pvewhmcs_hash_encryption($key, $base64 = true) {
|
||||
|
||||
global $cc_encryption_hash;
|
||||
|
||||
@@ -728,7 +819,7 @@ class hash_encryption {
|
||||
*
|
||||
* @todo Add more random sources.
|
||||
* @access private
|
||||
* @see function hash_encryption
|
||||
* @see function pvewhmcs_hash_encryption
|
||||
* @return string Binary pseudo random string
|
||||
**/
|
||||
function _generate_iv() {
|
||||
@@ -760,14 +851,14 @@ class hash_encryption {
|
||||
}
|
||||
|
||||
// GENERAL FUNCTION: Server PW from WHMCS DB
|
||||
function get_server_pass_from_whmcs($enc_pass){
|
||||
function pvewhmcs_get_whmcs_server_password($enc_pass){
|
||||
global $cc_encryption_hash;
|
||||
// Include WHMCS database configuration file
|
||||
include_once(dirname(dirname(dirname(dirname(__FILE__)))).'/configuration.php');
|
||||
$key1 = md5 (md5 ($cc_encryption_hash));
|
||||
$key2 = md5 ($cc_encryption_hash);
|
||||
$key = $key1.$key2;
|
||||
$hasher = new hash_encryption($key);
|
||||
$hasher = new pvewhmcs_hash_encryption($key);
|
||||
return $hasher->decrypt($enc_pass);
|
||||
}
|
||||
|
||||
@@ -785,13 +876,14 @@ function pvewhmcs_AdminCustomButtonArray() {
|
||||
// MODULE BUTTONS: Client Interface button regos
|
||||
function pvewhmcs_ClientAreaCustomButtonArray() {
|
||||
$buttonarray = array(
|
||||
"<img src='./modules/servers/pvewhmcs/img/novnc.png'/> noVNC (HTML5)" => "noVNC",
|
||||
"<img src='./modules/servers/pvewhmcs/img/tigervnc.png'/> TigerVNC (Java)" => "javaVNC",
|
||||
"<i class='fa fa-2x fa-flag-checkered'></i> Start Machine" => "vmStart",
|
||||
"<i class='fa fa-2x fa-sync'></i> Reboot Now" => "vmReboot",
|
||||
"<i class='fa fa-2x fa-flag-checkered'></i> Start" => "vmStart",
|
||||
"<i class='fa fa-2x fa-sync'></i> Reboot" => "vmReboot",
|
||||
"<i class='fa fa-2x fa-power-off'></i> Power Off" => "vmShutdown",
|
||||
"<i class='fa fa-2x fa-stop'></i> Hard Stop" => "vmStop",
|
||||
"<i class='fa fa-2x fa-chart-bar'></i> Statistics" => "vmStat",
|
||||
"<i class='fa fa-2x fa-search'></i> Check Status" => "vmCheck",
|
||||
"<img src='./modules/servers/pvewhmcs/img/novnc.png'/> noVNC (HTML5)" => "noVNC",
|
||||
"<img src='./modules/servers/pvewhmcs/img/tigervnc.png'/> TigerVNC (Java)" => "javaVNC",
|
||||
);
|
||||
return $buttonarray;
|
||||
}
|
||||
@@ -823,7 +915,7 @@ function pvewhmcs_ClientArea($params) {
|
||||
unset($nodes);
|
||||
|
||||
# Get and set VM variables
|
||||
$vm_config = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/config') ;
|
||||
$vm_config = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/config') ;
|
||||
$cluster_resources = $proxmox->get('/cluster/resources');
|
||||
$vm_status = null;
|
||||
|
||||
@@ -835,19 +927,27 @@ function pvewhmcs_ClientArea($params) {
|
||||
'pvewhmcs',
|
||||
__FUNCTION__,
|
||||
'CLUSTER INFO: ' . $cluster_encoded,
|
||||
'GUEST CONFIG (Service #' . $params['serviceid'] . ' / Client #' . $params['clientsdetails']['userid'] . '): ' . $vmspecs_encoded
|
||||
'GUEST CONFIG (Service #' . $params['serviceid'] . ' / PVE ID #' . $guest->vmid . ' / Client #' . $params['clientsdetails']['userid'] . '): ' . $vmspecs_encoded
|
||||
);
|
||||
}
|
||||
|
||||
# Loop through data, find ID
|
||||
$vm_status = null;
|
||||
foreach ($cluster_resources as $vm) {
|
||||
// Using vmid directly, from Module Table against API Response (ignoring Service ID now)
|
||||
if ($vm['vmid'] == $guest->vmid && $vm['type'] == $guest->vtype) {
|
||||
$vm_status = $vm;
|
||||
break;
|
||||
}
|
||||
|
||||
// If the vmid is not found, check against serviceid (<v1.2.9 case)
|
||||
if ($vm['vmid'] == $params['serviceid'] && $vm['type'] == $guest->vtype) {
|
||||
$vm_status = $vm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
# Set usage data appropriately
|
||||
# Retrieve & set usage data appropriately
|
||||
if ($vm_status !== null) {
|
||||
$vm_status['uptime'] = time2format($vm_status['uptime']);
|
||||
$vm_status['cpu'] = round($vm_status['cpu'] * 100, 2);
|
||||
@@ -857,13 +957,13 @@ function pvewhmcs_ClientArea($params) {
|
||||
|
||||
if ($guest->vtype == 'lxc') {
|
||||
// Check on swap before setting graph value
|
||||
$ct_specific = $proxmox->get('/nodes/'.$first_node.'/lxc/'.$params['serviceid'].'/status/current');
|
||||
$ct_specific = $proxmox->get('/nodes/'.$first_node.'/lxc/'.$guest->vmid.'/status/current');
|
||||
if ($ct_specific['maxswap'] != 0) {
|
||||
$vm_status['swapusepercent'] = intval($ct_specific['swap'] * 100 / $ct_specific['maxswap']);
|
||||
} else {
|
||||
// Fall back to 0% usage to satisfy chart requirement
|
||||
$vm_status['swapusepercent'] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Fall back to 0% usage to satisfy chart requirement
|
||||
$vm_status['swapusepercent'] = 0;
|
||||
}
|
||||
} else {
|
||||
// Handle the VM not found in the cluster resources (Optional)
|
||||
@@ -872,97 +972,97 @@ function pvewhmcs_ClientArea($params) {
|
||||
|
||||
// Max CPU usage Yearly
|
||||
$rrd_params = '?timeframe=year&ds=cpu&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] . '/rrd' . $rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid . '/rrd' . $rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['cpu']['year'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Max CPU usage monthly
|
||||
$rrd_params = '?timeframe=month&ds=cpu&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['cpu']['month'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Max CPU usage weekly
|
||||
$rrd_params = '?timeframe=week&ds=cpu&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['cpu']['week'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Max CPU usage daily
|
||||
$rrd_params = '?timeframe=day&ds=cpu&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['cpu']['day'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Max memory Yearly
|
||||
$rrd_params = '?timeframe=year&ds=maxmem&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['maxmem']['year'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Max memory monthly
|
||||
$rrd_params = '?timeframe=month&ds=maxmem&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['maxmem']['month'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Max memory weekly
|
||||
$rrd_params = '?timeframe=week&ds=maxmem&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['maxmem']['week'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Max memory daily
|
||||
$rrd_params = '?timeframe=day&ds=maxmem&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['maxmem']['day'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Network rate Yearly
|
||||
$rrd_params = '?timeframe=year&ds=netin,netout&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['netinout']['year'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Network rate monthly
|
||||
$rrd_params = '?timeframe=month&ds=netin,netout&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['netinout']['month'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Network rate weekly
|
||||
$rrd_params = '?timeframe=week&ds=netin,netout&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['netinout']['week'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Network rate daily
|
||||
$rrd_params = '?timeframe=day&ds=netin,netout&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['netinout']['day'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Max IO Yearly
|
||||
$rrd_params = '?timeframe=year&ds=diskread,diskwrite&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['diskrw']['year'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Max IO monthly
|
||||
$rrd_params = '?timeframe=month&ds=diskread,diskwrite&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['diskrw']['month'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Max IO weekly
|
||||
$rrd_params = '?timeframe=week&ds=diskread,diskwrite&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['diskrw']['week'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
// Max IO daily
|
||||
$rrd_params = '?timeframe=day&ds=diskread,diskwrite&cf=AVERAGE';
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd = $proxmox->get('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/rrd'.$rrd_params) ;
|
||||
$vm_rrd['image'] = utf8_decode($vm_rrd['image']) ;
|
||||
$vm_statistics['diskrw']['day'] = base64_encode($vm_rrd['image']);
|
||||
|
||||
@@ -976,7 +1076,7 @@ function pvewhmcs_ClientArea($params) {
|
||||
$vm_config['v6prefix'] = $guest->v6prefix ;
|
||||
}
|
||||
else {
|
||||
echo '<center><strong>Unable to contact Hypervisor - aborting!<br>Please contact Tech Support.</strong></center>';
|
||||
echo '<center><strong>Error: Unable to gather data from Hypervisor.<br>Please contact Tech Support!</strong></center>';
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1017,16 +1117,16 @@ function pvewhmcs_noVNC($params) {
|
||||
unset($nodes);
|
||||
// Early prep work
|
||||
$guest = Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
|
||||
$vm_vncproxy = $proxmox->post('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/vncproxy', array( 'websocket' => '1' )) ;
|
||||
$vm_vncproxy = $proxmox->post('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/vncproxy', array( 'websocket' => '1' )) ;
|
||||
// Get both tickets prepared
|
||||
$pveticket = $proxmox->getTicket();
|
||||
$vncticket = $vm_vncproxy['ticket'];
|
||||
// $path should only contain the actual path without any query parameters
|
||||
$path = 'api2/json/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/vncwebsocket?port=' . $vm_vncproxy['port'] . '&vncticket=' . urlencode($vncticket);
|
||||
$path = 'api2/json/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/vncwebsocket?port=' . $vm_vncproxy['port'] . '&vncticket=' . urlencode($vncticket);
|
||||
// Construct the noVNC Router URL with the path already prepared now
|
||||
$url = '/modules/servers/pvewhmcs/novnc_router.php?host=' . $serverip . '&pveticket=' . urlencode($pveticket) . '&path=' . urlencode($path) . '&vncticket=' . urlencode($vncticket);
|
||||
// Build and deliver the noVNC Router hyperlink for access
|
||||
$vncreply = '<center><strong>Console (noVNC) prepared for usage. <a href="'.$url.'" target="_blanK">Click here</a> to open the noVNC window.</strong></center>' ;
|
||||
$vncreply = '<center style="background-color: green;"><strong style="color: white;">Console (noVNC) successfully prepared!<br><a href="'.$url.'" target="_blanK" style="color: Khaki;"><u>Click here to launch noVNC.</u></a></strong></center>' ;
|
||||
return $vncreply;
|
||||
} else {
|
||||
$vncreply = 'Failed to prepare noVNC. Please contact Technical Support.';
|
||||
@@ -1054,16 +1154,16 @@ function pvewhmcs_SPICE($params) {
|
||||
unset($nodes);
|
||||
// Early prep work
|
||||
$guest = Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
|
||||
$vm_vncproxy = $proxmox->post('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/vncproxy', array( 'websocket' => '1' )) ;
|
||||
$vm_vncproxy = $proxmox->post('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/vncproxy', array( 'websocket' => '1' )) ;
|
||||
// Get both tickets prepared
|
||||
$pveticket = $proxmox->getTicket();
|
||||
$vncticket = $vm_vncproxy['ticket'];
|
||||
// $path should only contain the actual path without any query parameters
|
||||
$path = 'api2/json/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/vncwebsocket?port=' . $vm_vncproxy['port'] . '&vncticket=' . urlencode($vncticket);
|
||||
$path = 'api2/json/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/vncwebsocket?port=' . $vm_vncproxy['port'] . '&vncticket=' . urlencode($vncticket);
|
||||
// Construct the SPICE Router URL with the path already prepared now
|
||||
$url = '/modules/servers/pvewhmcs/spice_router.php?host=' . $serverip . '&pveticket=' . urlencode($pveticket) . '&path=' . urlencode($path) . '&vncticket=' . urlencode($vncticket);
|
||||
// Build and deliver the SPICE Router hyperlink for access
|
||||
$vncreply = '<center><strong>Console (SPICE) prepared for usage. <a href="'.$url.'" target="_blanK">Click here</a> to open the noVNC window.</strong></center>' ;
|
||||
$vncreply = '<center style="background-color: green;"><strong>Console (SPICE) successfully prepared.<br><a href="'.$url.'" target="_blanK" style="color: Khaki;"><u>Click here</u></a> to launch SPICE.</strong></center>' ;
|
||||
return $vncreply;
|
||||
} else {
|
||||
$vncreply = 'Failed to prepare SPICE. Please contact Technical Support.';
|
||||
@@ -1090,7 +1190,7 @@ function pvewhmcs_javaVNC($params){
|
||||
// Early prep work
|
||||
$guest = Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
|
||||
$vncparams = array();
|
||||
$vm_vncproxy = $proxmox->post('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/vncproxy', $vncparams) ;
|
||||
$vm_vncproxy = $proxmox->post('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$guest->vmid .'/vncproxy', $vncparams) ;
|
||||
// Java-specific params
|
||||
$javaVNCparams = array() ;
|
||||
$javaVNCparams[0] = $serverip ;
|
||||
@@ -1100,7 +1200,7 @@ function pvewhmcs_javaVNC($params){
|
||||
$javaVNCparams[4] = $vm_vncproxy['ticket'] ;
|
||||
// URL preparation to deliver in hyperlink message
|
||||
$url = './modules/servers/pvewhmcs/tigervnc.php?'.http_build_query($javaVNCparams).'' ;
|
||||
$vncreply = '<center><strong>Console (TigerVNC) prepared for usage. <a href="'.$url.'" target="_blanK">Click here</a> to open the TigerVNC window.</strong></center>' ;
|
||||
$vncreply = '<center style="background-color: green;"><strong>Console (TigerVNC) successfully prepared.<br><a href="'.$url.'" target="_blanK" style="color: Khaki;"><u>Click here</u></a> to launch TigerVNC.</strong></center>' ;
|
||||
// echo '<script>window.open("modules/servers/pvewhmcs/tigervnc.php?'.http_build_query($javaVNCparams).'","VNC","location=0,toolbar=0,menubar=0,scrollbars=1,resizable=1,width=802,height=624")</script>';
|
||||
return $vncreply;
|
||||
} else {
|
||||
@@ -1129,8 +1229,8 @@ function pvewhmcs_vmStart($params) {
|
||||
unset($nodes);
|
||||
$guest = Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
|
||||
$pve_cmdparam = array();
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/start';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/start' , $pve_cmdparam);
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/start';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/start' , $pve_cmdparam);
|
||||
}
|
||||
// DEBUG - Log the request parameters before it's fired
|
||||
if (Capsule::table('mod_pvewhmcs')->where('id', '1')->value('debug_mode') == 1) {
|
||||
@@ -1172,15 +1272,15 @@ function pvewhmcs_vmReboot($params) {
|
||||
$guest = Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
|
||||
$pve_cmdparam = array();
|
||||
// Check status before doing anything
|
||||
$guest_specific = $proxmox->get('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/current');
|
||||
$guest_specific = $proxmox->get('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/current');
|
||||
if ($guest_specific['status'] = 'stopped') {
|
||||
// START if Stopped
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/start';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/start' , $pve_cmdparam);
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/start';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/start' , $pve_cmdparam);
|
||||
} else {
|
||||
// REBOOT if Started
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/reboot';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/reboot' , $pve_cmdparam);
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/reboot';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/reboot' , $pve_cmdparam);
|
||||
}
|
||||
}
|
||||
// DEBUG - Log the request parameters before it's fired
|
||||
@@ -1224,8 +1324,8 @@ function pvewhmcs_vmShutdown($params) {
|
||||
$guest = Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
|
||||
$pve_cmdparam = array();
|
||||
// $pve_cmdparam['timeout'] = '60';
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/shutdown';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/shutdown' , $pve_cmdparam);
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/shutdown';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/shutdown' , $pve_cmdparam);
|
||||
}
|
||||
// DEBUG - Log the request parameters before it's fired
|
||||
if (Capsule::table('mod_pvewhmcs')->where('id', '1')->value('debug_mode') == 1) {
|
||||
@@ -1267,8 +1367,8 @@ function pvewhmcs_vmStop($params) {
|
||||
$guest = Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
|
||||
$pve_cmdparam = array();
|
||||
// $pve_cmdparam['timeout'] = '60';
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/stop';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/stop' , $pve_cmdparam);
|
||||
$logrequest = '/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/stop';
|
||||
$response = $proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $guest->vmid . '/status/stop' , $pve_cmdparam);
|
||||
}
|
||||
// DEBUG - Log the request parameters before it's fired
|
||||
if (Capsule::table('mod_pvewhmcs')->where('id', '1')->value('debug_mode') == 1) {
|
||||
@@ -1289,6 +1389,11 @@ function pvewhmcs_vmStop($params) {
|
||||
}
|
||||
}
|
||||
|
||||
// CLIENT AREA: REFRESH TO CHECK STATUS ON-CLICK
|
||||
function pvewhmcs_vmCheck($params) {
|
||||
return "success";
|
||||
}
|
||||
|
||||
// NETWORKING FUNCTION: Convert subnet mask to CIDR
|
||||
function mask2cidr($mask){
|
||||
$long = ip2long($mask);
|
||||
@@ -1338,4 +1443,4 @@ function time2format($s) {
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
?>
|
||||
?>
|
||||
24
modules/servers/pvewhmcs/whmcs.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"schema": "1.0",
|
||||
"type": "whmcs-servers",
|
||||
"name": "pvewhmcs",
|
||||
"license": "open-source",
|
||||
"category": "provisioning",
|
||||
"description": {
|
||||
"name": "Proxmox VE for WHMCS",
|
||||
"tagline": "Seamless integration of Proxmox VE (PVE) VMs & CTs with WHMCS.",
|
||||
"long": ""
|
||||
},
|
||||
"logo": {
|
||||
"filename": "img/logo.png"
|
||||
},
|
||||
"support": {
|
||||
"docs_url": "https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "The Network Crew Pty Ltd",
|
||||
"homepage": "https:\/\/tnc.works\/"
|
||||
}
|
||||
]
|
||||
}
|
||||