71 Commits

Author SHA1 Message Date
Luke S Thompson
efe73f8a28 Updated Logs/Tasks image 2025-08-19 13:11:02 +10:00
Luke S Thompson
f612c84897 VMID into PVE Tasks/Logs table 2025-08-19 13:10:14 +10:00
Luke S Thompson
ea985a2d37 Final module pretty name update 2025-08-19 12:54:10 +10:00
Luke S Thompson
60d0a67d40 Update menu imagery (new-only) 2025-08-19 10:39:22 +10:00
Luke S Thompson
aa54e51c7b Re-arrange Log columns; replace SS 2025-08-19 10:06:10 +10:00
Luke S Thompson
0f64b5b835 Add the Cluster History log (SS) 2025-08-19 09:58:03 +10:00
Luke S Thompson
b054965528 Re-order Admin GUI tabs/panes; new SS 2025-08-19 09:55:08 +10:00
Luke S Thompson
0634a17cdc v1.2.14 (fix #50, fix #154, fix #155, fix #157) 2025-08-19 08:42:37 +10:00
Luke S Thompson
fb08f8ac36 New screenshot 2025-08-18 18:34:46 +10:00
Luke S Thompson
86fbffd0b6 Consoles to bottom of menu 2025-08-18 18:31:42 +10:00
Luke S Thompson
1e01f1b1a9 Improve labels for power actions 2025-08-18 18:30:16 +10:00
Luke S Thompson
ecb6a4aa51 Improve Client Area (fix #154, fix #155) 2025-08-18 18:02:23 +10:00
Luke S Thompson
335ff949be Move docs into new folder 2025-08-18 17:19:12 +10:00
Luke S Thompson
3d9bff7e9c Rename one & add another 2025-08-18 17:16:19 +10:00
Luke S Thompson
5d2dfc273e Add Server Test screenshot 2025-08-18 17:09:04 +10:00
Luke S Thompson
7ee297e562 Move images into new folder 2025-08-18 17:01:55 +10:00
Luke S Thompson
22809ce9b3 Add new screenshot 2025-08-18 16:49:05 +10:00
Luke S Thompson
4ae70047ab add Product Save screenshot 2025-08-18 16:47:53 +10:00
Luke S Thompson
b8266f7f8c Shorten name of "WHMCS Server" type 2025-08-18 14:58:45 +10:00
Luke S Thompson
fe6c1bae56 Delete pvewhmcs-v1-2-13.zip 2025-08-13 15:52:44 +10:00
Luke S Thompson
1718d17e5a POST to GET request (#152) 2025-08-13 15:51:07 +10:00
Luke S Thompson
f1e701ac02 Remove trailing / (#152) 2025-08-13 15:48:01 +10:00
Luke S Thompson
5d97d34ab1 v1.2.13 (#151 and #152) 2025-08-13 15:38:11 +10:00
Luke S Thompson
5624ef1bac Change to standardised button (#152) 2025-08-13 15:29:32 +10:00
Luke S Thompson
a6e98b75a9 PVE AdminLink (GUI) fix #152 2025-08-13 15:23:24 +10:00
Luke S Thompson
4af6008317 whmcs.json file/logo; conn. test name (fix #151) 2025-08-13 13:37:21 +10:00
Luke S Thompson
2d798d1a0e v1.2.12 (fix #105, #139, #148, #149, #150) 2025-08-12 14:02:12 +10:00
Luke S Thompson
655ee29e10 Explicit $0.00 x2 on Service Add (#135) 2025-08-11 13:24:35 +10:00
Luke S Thompson
5a7c823c40 Fix C'LOG re: Virtio/E1000 2025-08-05 15:26:41 +10:00
Luke S Thompson
caa173cef4 Final serviceid to vmid (fix #146) 2025-08-05 15:25:54 +10:00
Luke S Thompson
0fd26ef72a /cluster/nextid for #136 & #145 2025-08-05 08:30:27 +10:00
Luke S Thompson
deedc53eb0 Minor tweaks 2025-08-02 15:03:15 +10:00
Luke S Thompson
d14ee3ce0e Final images for now (5 total)
WHMCS Marketplace only includes 3x by default
2025-08-02 12:21:41 +10:00
Luke S Thompson
5f8534e1a9 Module Config pane: minor text updates 2025-08-02 12:14:05 +10:00
Luke S Thompson
ec1f4fa6e7 New H3 for Custom Fields 2025-08-02 12:05:01 +10:00
Luke S Thompson
9d30365d5e Link to classdocs 2025-08-02 11:54:06 +10:00
Luke S Thompson
05e21eb441 Update flow into <ol> 2025-08-02 11:47:12 +10:00
Luke S Thompson
c7474af62a Fix tables 2025-08-02 11:41:31 +10:00
Luke S Thompson
03adc10597 Improved formatting 2025-08-02 11:36:26 +10:00
Luke S Thompson
e4fe986a6b Heading tidy-up etc 2025-08-02 11:21:18 +10:00
Luke S Thompson
69787b823c 'nodes' column (whmcs_id) #127 README 2025-08-02 11:15:34 +10:00
Luke S Thompson
171eadce0d Add 2nd & 3rd screenshots 2025-08-02 09:44:10 +10:00
Luke S Thompson
28921ab03d NIC default Virtio, was E1000 2025-08-02 09:36:38 +10:00
Luke S Thompson
ad6aac64f8 SQL prep for #105 2025-08-02 09:30:11 +10:00
Luke S Thompson
8e4a3c56d0 v1.3.x SQL tweak; README polish 2025-08-02 09:20:48 +10:00
Luke S Thompson
b3e7e28795 v1.2.9.1 rename to v1.2.10
re: PHP's version_compare
2025-08-01 21:51:45 +10:00
Luke S Thompson
40af00ac02 Merge branch 'master' of https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS 2025-08-01 16:54:47 +10:00
Luke S Thompson
9c8a67732d Draft SQL re: #49, #50, #74, #142 2025-08-01 16:54:41 +10:00
Luke S Thompson
f6083d8abd Link to contributors file 2025-08-01 14:43:07 +10:00
Luke S Thompson
e5279e0158 C'LOG & GPL tweaks 2025-08-01 14:39:09 +10:00
Luke S Thompson
e92f35b9f7 Merge branch 'master' of https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS 2025-08-01 14:19:08 +10:00
Luke S Thompson
0a790074e3 revert: version comparison (#62) v1.2.9.1 2025-08-01 14:19:02 +10:00
Luke S Thompson
bddb2d75fb Remove SID >100 ref 2025-07-31 18:06:31 +10:00
Luke S Thompson
b5f5248b78 Advisory for auto SQL ops (beta) 2025-07-31 17:18:49 +10:00
Luke S Thompson
cb3fe9628b Import Guest & Use VMID (#135) v1.2.9
* Starting to get automatic VMID detection implemented (#132) by @tnewton1

* More work on #75 prep (true VMID)

* Guest Import form/logic (draft) re: #75

* Another case to set vmid (re: #75)

* More serviceid -> vmid changes (re: #75)

* Minor typos & tweaks (#75 #136)

* Tidy C'LOG; bump ver (v1.2.9)

* Link to contributors; tidy README

* Fine-tuning from review

* Remove SID >100 per #136 for #75!

* v1.2.9: Guest Import (VMID)

* vmid = id, if empty (manual update)

* Use advised version check

* Fine-tune comments

* Final C'LOG for v1.2.9
2025-07-31 17:05:55 +10:00
Luke S Thompson
e73ff1a39b v1.2.9 SQL op (re: import existing guest #75) 2025-07-30 17:03:50 +10:00
Luke S Thompson
b4d9b29805 Add #129 fix to C'LOG 2025-07-03 17:57:30 +10:00
Luke S Thompson
d32d719690 Update function name (fix #129)
get_server_pass_from_whmcs --> pvewhmcs_get_whmcs_server_password
2025-07-03 17:56:44 +10:00
Luke S Thompson
39beaf0b07 Correct param name (VLAN ID) 2025-06-05 16:37:30 +10:00
Luke S Thompson
e95913aad9 trunks -> tag (re: #125) 2025-06-05 16:35:32 +10:00
Luke S Thompson
07c4a3cc7e v1.2.9 into C'LOG 2025-06-05 16:01:54 +10:00
Luke S Thompson
0e9d70f189 trunk -> trunks (re: #125) 2025-06-05 16:00:32 +10:00
Luke S Thompson
c966c22348 Expand on 🐛-bug-report.md 2025-05-31 17:53:12 +10:00
Luke S Thompson
c0da37de26 Declare IPv6 DNS if v6 is configured (fix #119) 2025-05-01 23:08:29 +10:00
Luke S Thompson
5f1292f876 netrate - default to 0 (re: #103 & #119) 2025-05-01 22:58:25 +10:00
Luke S Thompson
df3508ebc9 Re-classify #103 2025-04-30 18:38:14 +10:00
Luke S Thompson
2e9a46b3c3 Clarify re: install/config (re: #91) 2025-04-29 12:04:30 +10:00
Luke S Thompson
c74308f202 KVM -> QEMU (lang only); IP -> IPv4 2025-04-26 17:49:54 +10:00
Luke S Thompson
cb56d559b2 /n for sentence 2025-04-26 17:38:03 +10:00
Luke S Thompson
f91048c34e More improvements to README 2025-04-26 17:36:56 +10:00
Luke S Thompson
ea94ea50a1 Overhaul layout & info 2025-04-26 17:08:38 +10:00
31 changed files with 1371 additions and 464 deletions

View File

@@ -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.

View File

@@ -1,10 +1,77 @@
# 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-??-??
### 💅 Polish
- SQL Expansion: Prepare for Nodes/ISOs/TPLs/Logs/SSH Keys/etc
https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/milestones
## [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 +79,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
View 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?

500
README.md
View File

@@ -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,116 @@
- 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
- Specify PVE VMID start & integrate to your schema
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 +133,251 @@ 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.
Here are some of the critical requirements for VNC tunnelling:
### VM Option 1: KVM, using PVE Template VM
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!
Firstly, create the Template in PVE. You need its unique PVE ID.
<img alt="Admin GUI of the Module Config (VNC Secret, Start VMID, Debug Log y/n)" src="_images/zConfiguration.png">
## 🌐 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.
> Hence, we will not support any set-ups which do not follow all of the set-up processes 100%.
#### 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.
> **Note**: 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
### 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 +387,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)

View File

@@ -1,5 +1,19 @@
# SQL Statements for Updates (nav to DB first)
## 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
```

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

BIN
_images/zClusterGuests.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

BIN
_images/zClusterHistory.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 KiB

BIN
_images/zConfiguration.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

BIN
_images/zConsoleReady.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

BIN
_images/zModuleDebug.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

BIN
_images/zPatchAvailable.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

BIN
_images/zProductISOetc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

BIN
_images/zProductSave.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

BIN
_images/zQEMUplanAdd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

BIN
_images/zServerListLink.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

BIN
_images/zServerTestOK.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

BIN
_images/zVMIDimport.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

BIN
_images/zVMclientGUI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

View File

@@ -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,6 +21,51 @@ 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,
@@ -50,10 +96,32 @@ CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_plans` (
`vlanid` varchar(10) DEFAULT NULL,
`ipv6` varchar(10) DEFAULT 'auto',
`balloon` varchar(10) DEFAULT '0',
`unpriv` int(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`)
);
);

File diff suppressed because it is too large Load Diff

View File

@@ -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:&nbsp;{$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:&nbsp;{$vm_config['netmask4']}<br/>Gateway:&nbsp;{$vm_config['gateway4']}</td>
</tr>
<tr>
<td><strong>OS/etc</strong> (System)</td>
<td>Kernel:&nbsp;{$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']}&nbsp;socket/s,&nbsp;{$vm_config['cores']}&nbsp;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']}&nbsp;{$vm_config['cores']}&nbsp;core/s&nbsp;on&nbsp;{$vm_config['sockets']}&nbsp;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:&nbsp;{$vm_config['ostype']}</td>
</tr>
<tr>
<td><strong>IP</strong> (Addressing)</td><td><strong>{$vm_config['ipv4']}</strong><br/>Mask:&nbsp;{$vm_config['netmask4']}<br/>Gateway:&nbsp;{$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']}</td>
</tr>
</table>
{if ($smarty.get.a eq 'vmStat')}
<h4>VM Statistics</h4>

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -47,4 +47,4 @@ if (isset($_GET['pveticket']) && isset($_GET['host']) && isset($_GET['path']) &&
echo 'Error: Missing required info to route your request. Please try again.';
exit;
}
?>
?>

View File

@@ -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,34 @@ 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',
);
}
/**
* 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';
$text = htmlspecialchars($host, ENT_QUOTES, 'UTF-8');
return '<form action="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '" method="get" target="_blank">
<input type="submit" value="' . $text . '" 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
@@ -49,7 +78,7 @@ function pvewhmcs_ConfigOptions() {
}
/*
$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 +103,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 +144,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 +158,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 +216,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 +246,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 +256,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 +264,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 +279,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 +296,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 +317,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 +342,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 +355,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 +377,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 +440,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 +473,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 +568,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 +605,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 +643,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";
@@ -760,7 +852,7 @@ 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');
@@ -785,13 +877,13 @@ 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",
"<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,12 +1117,12 @@ 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
@@ -1054,12 +1154,12 @@ 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
@@ -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 ;
@@ -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) {
@@ -1338,4 +1438,4 @@ function time2format($s) {
}
return $str;
}
?>
?>

View 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\/"
}
]
}

View File

@@ -1 +1 @@
1.2.8
1.2.14