26 Commits

Author SHA1 Message Date
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
10 changed files with 779 additions and 381 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,30 @@
# 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.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 +32,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?

403
README.md
View File

@@ -1,14 +1,14 @@
# Proxmox VE for WHMCS (Module) Provision & Manage
<img alt="Logo for the Proxmox VE for WHMCS module" src="zLOGO.png">
**Salvation, a free and open-source solution for beloved PVE!** If you love it, REVIEW & SHARE IT! ❤️
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 PVEWHMCS 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,10 +16,12 @@
- 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/
## ❤️ RTFM: Read the Manual & Review the Module!
# ❤️ RTFM: Read the Manual & Review the Module!
**Please read the entire README.md file before getting started with Proxmox VE for WHMCS.** Thanks!
@@ -29,52 +31,66 @@ We're pretty much done overhauling the Module to suit our needs at The Network C
>
> _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.
# ✅ MODULE: Installation & Configuration
**SID >100:** The WHMCS Service ID requirement is CRITICAL, as **Proxmox reserves VMIDs <100 (system).**
> [!WARNING]
> **DON'T SKIP ANY PART OF THIS README.md - please don't raise pointless Issues - thank you!**
_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:**
## 📋 1. PREP: Upload & Configure the Module
`HTTP/1.1 400 Parameter verification failed. (invalid format - value does not look like a valid VM ID)`
Check the System Requirements above, and resolve any blockers to using Proxmox VE for WHMCS.
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.
### 👥 PVE: User x2 Requirement (API & VNC users)
Once over 100, it fits the requirement & you're good!
#### Credentials: root account for each PVE host
### General Requirements
**You must have a root account to use the Module at all.** Configured via WHMCS > Servers.
- (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)
This is configured in the pam realm. We plan to allow selection in v1.3.x.
## ✅ MODULE: Installation & Configuration
#### Credentials: VNC user for Console Access only
**DON'T SKIP ANY PART OF THIS README.md - please don't raise pointless Issues - thank you!**
Additionally, to improve security, for VNC you must also have a Restricted User.
Firstly, you need to upload, activate and make the WHMCS Module available to Administrators.
Configured in the _Module_ as detailed below, once you've added/restricted it in PVE.
### 🏃‍♂️ INSTALL: Getting ready to use the Module!
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 your PVE host/s (user: root; IP: PVE's)
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 KVM/LXC Plan/s
4. WHMCS Admin > Addons > Proxmox VE for WHMCS > Add an IP Pool
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)
## 🥽 noVNC: Console Tunnel (Client Area)
## 🥽 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 to further enhance security.
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.
### To offer VNC via WHMCS Client Area
This is due to be re-built again 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
@@ -82,18 +98,11 @@ After forking the module, we considered how to improve security of Console Tunne
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. :-)
If proxying, that is your responsibility to diagnose.
- 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.
Else, PVE must be WAN-accessible and all other configs/reqs satisfied.
## 👥 PVE: User Requirements (API & VNC)
**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_.
### Creating the VNC user within PVE
### 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,46 +110,23 @@ 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.**
## ⚙️ VM/CT PLANS: Setting everything up
### Important info about Console Access
These steps explain the unique requirements per-option.
noVNC has been overhauled. It isn't guaranteed, nor the project at all. :-)
Custom Fields: Values need to go in Name & Select Options.
- 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.
> **Unsure?** Consult the zMANUAL-PVE4.pdf _legacy_ manual file.
## 🌐 3. Networking: IPv4 Pools, IPv6, vmbr/SDN
### VM Option 1: KVM, using PVE Template VM
### IPv4: Pool required for assignment
Firstly, create the Template 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.
### VM Option 2: KVM, WHMCS Plan + PVE ISO
Firstly, create the Plan in WHMCS Module. Then, WHMCS Config > Services.
> Under the Service, you need to add a Custom Field `ISO` with the full location.
### CT Option: LXC, using 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.
Then make a 2nd Custom Field `Password` for the CT's root user.
## 🌐 IPv4/v6: Networking (IP Pools)
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.
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).
@@ -150,28 +136,135 @@ Per The-Network-Crew/Proxmox-VE-for-WHMCS#33 there's SLAAC/DHCP/off available (2
You can of course add different config via PVE/`pvesh` manually, if you need to specify a prefix.
## 💅 FEATURES: PVE v8.x bling
### vmbr / SDN: Config type
There are new features deployed into Proxmox VE upstream in the v8 branch which are exciting and should be added to this module.
This depends on your configuration on the PVE Host/s - bridge (vmbr0 etc) or software-defined (SDN).
### Proxmox v8.0
**If normal (bridged)** - use `vmbr` as the Network, then use `0` as the Interface ID - this makes up `vmbr0`.
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.
**If SDN (Software Defined Network)** - use SDN Name for Network, leave Interface ID blank (= no suffix).
### Proxmox v8.1
## ⚙️ 4. VM/CT PLANS: Setting everything up
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!
These steps explain the unique requirements for QEMU & LXC guests.
### Proxmox v8.2
**Custom Fields:** Values need to go in Name & Select Options.<br>
This needs configuring for each `WHMCS Admin > Products & Services` entry.
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).
### 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: `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: QEMU, WHMCS Plan + PVE ISO
Firstly, create the Plan in WHMCS Module. Then, WHMCS Config > Services.
> 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 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`
### VM/CT Import/Associate Existing Guest
You can associate an existing PVE Guest through the WHMCS Module too, like this:
<img alt="Importing GUI for linking to existing PVE Guest" src="zVMIDimport.png">
#### ZFS etc: Comfigure to suit isolated TPL
- `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
ie. If using ZFS for Templates, substitute local with volume name.
#### Password: Configure the CT's root user
Make a 2nd Custom Field `Password` for the CT's root user.
## 🔄 5. PATCH: Updating the Module
**Check:** `WHMCS Admin > Addon Modules > Proxmox VE for WHMCS > Support/Health`
You should download any new version & upload it over the top, then login to WHMCS Admin.
### SQL: Keeping your DB up-to-date
> [!IMPORTANT]
> Since v1.3.0, logging into WHMCS Admin & opening the module should run any needed SQL Ops.
>
> v1.2.9 & below, consult the **UPDATE-SQL.md** file, open your SQL DB & run statements.
Then you're done with each update! :-)
## 🆘 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.
#### 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)
#### 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 is given.**
https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/issues/new/choose
# 💅 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.0 beta
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.4
1. Live migrate with mediated devices.
2. Support for external backup providers.
3. Host dir's, share with guests (virtiofs).
### Proxmox v8.3
@@ -180,15 +273,50 @@ There are new features deployed into Proxmox VE upstream in the v8 branch which
3. Webhook target for system alerting.
4. Better change detection for PBS.
### Proxmox v8.4
### Proxmox v8.2
1. Live migrate with mediated devices.
2. Support for external backup providers.
3. Host dir's, share with guests (virtiofs).
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).
PVE Roadmap: https://pve.proxmox.com/wiki/Roadmap
### Proxmox v8.1
## 🤬 ABUSE: Zero Tolerance (ZT)
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!
### Proxmox v8.0
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.
### Proxmox 7.x
1. Cross-cluster guest migrations
2. Cluster Resource Scheduling (CRS) launched
3. Re-balance CRS on fresh start-up, not just recovery
4. CRM into HA Manager, as a node maintenance switch
5. Proxmox Offline Mirror (POM) launched
# 🖥️ 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.15.0 in repo) https://sourceforge.net/projects/tigervnc/files/stable/
- **(MPLv2)** noVNC HTML5 Viewer (v1.6.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
# 🤬 ABUSE: Zero Tolerance (ZT)
This module has been overhauled and remains functionally-OK but not thoroughly tested nor reviewed.
@@ -198,94 +326,29 @@ If you cannot accept this, do not download nor use the code. Complaints, nasty r
**Be grateful & considerate - thank you!**
## 🆘 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?
> 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.
### Issues/etc raised must include:
#### 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
# 🎉 FOSS: Open-source Contributions
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.
_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.**
Thank you to psyborg® for the module's logo design! We love it.
FOSS is only possible thanks to dedicated people around the world!
FOSS is only possible thanks to dedicated individuals!
**See [CONTRIBUTORS.md](https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/blob/master/CONTRIBUTORS.md) for those who've made PVEWHMCS possible.**
## 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,13 @@
# SQL Statements for Updates (nav to DB first)
## 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

@@ -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,45 @@ 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,
`title` varchar(255) NOT NULL,
`ip` varchar(100) NOT NULL,
`capacity` int(5) NOT NULL DEFAULT '20',
`health` 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 +90,31 @@ CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_plans` (
`vlanid` varchar(10) DEFAULT NULL,
`ipv6` varchar(10) DEFAULT 'auto',
`balloon` varchar(10) 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 +123,4 @@ CREATE TABLE IF NOT EXISTS `mod_pvewhmcs_vms` (
`created` datetime DEFAULT NULL,
`v6prefix` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`)
);
);

View File

@@ -6,19 +6,20 @@
File: /modules/addons/pvewhmcs/pvewhmcs.php (GUI 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// Pull in the WHMCS database handler Capsule for SQL
@@ -35,7 +36,7 @@ function pvewhmcs_config() {
$configarray = array(
"name" => "Proxmox VE for WHMCS",
"description" => "Proxmox VE (Virtual Environment) & WHMCS, integrated & open-source! Provisioning & Management of VMs/CTs.".is_pvewhmcs_outdated(),
"version" => "1.2.8",
"version" => "1.2.10",
"author" => "The Network Crew Pty Ltd",
'language' => 'English'
);
@@ -44,7 +45,7 @@ function pvewhmcs_config() {
// VERSION: also stored in repo/version (for update-available checker)
function pvewhmcs_version(){
return "1.2.8";
return "1.2.10";
}
// WHMCS MODULE: ACTIVATION of the ADDON MODULE
@@ -83,22 +84,50 @@ function pvewhmcs_deactivate() {
return array('status'=>'success','description'=>'Proxmox VE for WHMCS successfully deactivated and all related tables deleted.');
}
// WHMCS MODULE: Upgrade
function pvewhmcs_upgrade($vars) {
// This function gets passed the old ver once post-update, hence lt check
$currentlyInstalledVersion = $vars['version'];
// SQL Operations for v1.2.9/10 version
if (version_compare($currentlyInstalledVersion, '1.2.10', 'lt')) {
$schema = Capsule::schema();
// Add the column "start_vmid" to the mod_pvewhmcs table
if (!$schema->hasColumn('mod_pvewhmcs', 'start_vmid')) {
$schema->table('mod_pvewhmcs', function ($table) {
$table->integer('start_vmid')->default(100)->after('vnc_secret');
});
}
// Add the column "vmid" to the mod_pvewhmcs_vms table
if (!$schema->hasColumn('mod_pvewhmcs_vms', 'vmid')) {
$schema->table('mod_pvewhmcs_vms', function ($table) {
$table->integer('vmid')->default(0)->after('id');
});
// Populate ID into VMID for all previous guests
Capsule::table('mod_pvewhmcs_vms')
->where('vmid', 0)
->update(['vmid' => Capsule::raw('id')]);
}
}
}
// UPDATE CHECKER: live vs repo
function is_pvewhmcs_outdated(){
if(get_pvewhmcs_latest_version() > pvewhmcs_version()){
return "<br><span style='float:right;'><b>Proxmox VE for WHMCS is outdated: <a style='color:red' href='https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/releases'>Download the new version!</a></span>";
}
if(get_pvewhmcs_latest_version() > pvewhmcs_version()){
return "<br><span style='float:right;'><b>Proxmox VE for WHMCS is outdated: <a style='color:red' href='https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/releases'>Download the new version!</a></span>";
}
}
// UPDATE CHECKER: return latest ver
function get_pvewhmcs_latest_version(){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://raw.githubusercontent.com/The-Network-Crew/Proxmox-VE-for-WHMCS/master/version");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close ($ch);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://raw.githubusercontent.com/The-Network-Crew/Proxmox-VE-for-WHMCS/master/version");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close ($ch);
return str_replace("\n", "", $result);
return str_replace("\n", "", $result);
}
// ADMIN MODULE GUI: output (HTML etc)
@@ -124,6 +153,12 @@ function pvewhmcs_output($vars) {
unset($_SESSION['pvewhmcs']) ;
}
// Set the active tab based on the GET parameter, default to 'vmplans'
if (!isset($_GET['tab'])) {
$_GET['tab'] = 'vmplans';
}
// Start the HTML output for the Admin GUI
echo '
<div id="clienttabs">
<ul class="nav nav-tabs admin-tabs">
@@ -138,7 +173,7 @@ function pvewhmcs_output($vars) {
<div class="tab-content admin-tabs">
' ;
// Handle form submissions for saving or updating plans
if (isset($_POST['addnewkvmplan']))
{
save_kvm_plan() ;
@@ -158,6 +193,7 @@ function pvewhmcs_output($vars) {
save_lxc_plan() ;
}
// VM/CT PLANS tab in ADMIN GUI
echo '
<div id="plans" class="tab-pane '.($_GET['tab']=="vmplans" ? "active" : "").'">
<div class="btn-group" role="group" aria-label="...">
@@ -165,13 +201,22 @@ function pvewhmcs_output($vars) {
<i class="fa fa-list"></i>&nbsp; List: Guest Plans
</a>
<a class="btn btn-default" href="'. pvewhmcs_BASEURL .'&amp;tab=vmplans&amp;action=add_kvm_plan">
<i class="fa fa-plus-square"></i>&nbsp; Add: KVM Plan
<i class="fa fa-plus-square"></i>&nbsp; Add: QEMU Plan
</a>
<a class="btn btn-default" href="'. pvewhmcs_BASEURL .'&amp;tab=vmplans&amp;action=add_lxc_plan">
<i class="fa fa-plus-square"></i>&nbsp; Add: LXC Plan
</a>
<a class="btn btn-default" href="'. pvewhmcs_BASEURL .'&amp;tab=vmplans&amp;action=import_guest">
<i class="fa fa-upload"></i>&nbsp; Import: Guest
</a>
</div>
';
// Handle actions based on the 'action' GET parameter
if ($_GET['action']=='import_guest') {
import_guest() ;
}
if ($_GET['action']=='add_kvm_plan') {
kvm_plan_add() ;
}
@@ -192,77 +237,34 @@ function pvewhmcs_output($vars) {
lxc_plan_add() ;
}
// List of VM/CT Plans
if ($_GET['action']=='planlist') {
echo '
<table class="datatable" border="0" cellpadding="3" cellspacing="1" width="100%">
<tbody>
<tr>
<th>
ID
</th>
<th>
Name
</th>
<th>
Guest
</th>
<th>
OS Type
</th>
<th>
CPUs
</th>
<th>
Cores
</th>
<th>
RAM
</th>
<th>
Balloon
</th>
<th>
Swap
</th>
<th>
Disk
</th>
<th>
Disk Type
</th>
<th>
Disk I/O
</th>
<th>
PVE Store
</th>
<th>
Net Mode
</th>
<th>
Bridge
</th>
<th>
NIC
</th>
<th>
VLAN ID
</th>
<th>
Net Rate
</th>
<th>
Net BW
</th>
<th>
IPv6
</th>
<th>
Actions
</th>
</tr>
';
<th>ID</th>
<th>Name</th>
<th>Guest</th>
<th>OS Type</th>
<th>CPUs</th>
<th>Cores</th>
<th>RAM</th>
<th>Balloon</th>
<th>Swap</th>
<th>Disk</th>
<th>Disk Type</th>
<th>Disk I/O</th>
<th>PVE Store</th>
<th>Net Mode</th>
<th>Bridge</th>
<th>NIC</th>
<th>VLAN ID</th>
<th>Net Rate</th>
<th>Net BW</th>
<th>IPv6</th>
<th>Actions</th>
</tr>';
foreach (Capsule::table('mod_pvewhmcs_plans')->get() as $vm) {
echo '<tr>';
echo '<td>'.$vm->id . PHP_EOL .'</td>';
@@ -291,17 +293,13 @@ function pvewhmcs_output($vars) {
</td>' ;
echo '</tr>' ;
}
echo '
';
echo '
</tbody>
</table>
';
echo '</tbody></table>';
}
echo '
</div>
';
// IPv4 POOLS tab in ADMIN GUI
echo '
<div id="ippools" class="tab-pane '.($_GET['tab']=="ippools" ? "active" : "").'" >
<div class="btn-group">
@@ -337,6 +335,7 @@ function pvewhmcs_output($vars) {
echo'
</div>
';
// NODES / CLUSTER tab in ADMIN GUI
echo '<div id="nodes" class="tab-pane '.($_GET['tab']=="nodes" ? "active" : "").'" >' ;
echo ('<strong><h2>PVE: /cluster/resources</h2></strong>');
@@ -347,23 +346,24 @@ function pvewhmcs_output($vars) {
echo ('Coming in v1.3.x<br><br>');
echo ('<strong><a href=\'https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/milestones\' target=\'_blank\'>View the milestones/versions on GitHub</a></strong>');
echo '</div>';
// ACTIONS / LOGS tab in ADMIN GUI
echo '<div id="actions" class="tab-pane '.($_GET['tab']=="actions" ? "active" : "").'" >' ;
echo ('<strong><h2>WHMCS: Module Logging</h2></strong>');
echo ('<u><a href=\'/admin/index.php?rp=/admin/logs/module-log\'>Click here</a></u><br>(Module Config > Debug Mode = ON)');
echo ('<strong><h2>Module: Action History</h2></strong>');
echo ('Coming in v1.3.x');
echo ('<strong><h2>Module: Failed Actions</h2></strong>');
echo ('Coming in v1.3.x');
echo ('<strong><h2>WHMCS: Module Logging</h2></strong>');
echo ('<u><a href=\'/admin/index.php?rp=/admin/logs/module-log\'>Click here</a></u> (Module Config > Debug Mode = ON)<br><br>');
echo ('<strong><a href=\'https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/milestones\' target=\'_blank\'>View the milestones/versions on GitHub</a></strong>');
echo ('Coming in v1.3.x<br><strong><a href=\'https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/milestones\' target=\'_blank\'>View the milestones/versions on GitHub</a></strong>');
echo '</div>';
// SUPPORT / HEALTH tab in ADMIN GUI
echo '<div id="health" class="tab-pane '.($_GET['tab']=="health" ? "active" : "").'" >' ;
echo ('<div id="health" class="tab-pane '.($_GET['tab']=="health" ? "active" : "").'" >') ;
echo ('<b>❤️ Proxmox for WHMCS is open-source and free to use & improve on!</b><br><a href="https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/" target="_blank">https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/</a><br><br>');
echo ('<b style="color:darkgreen;">Your 5-star review on WHMCS Marketplace will help the module grow!</b><br>*****: <a href="https://marketplace.whmcs.com/product/6935-proxmox-ve-for-whmcs" target="_blank">https://marketplace.whmcs.com/product/6935-proxmox-ve-for-whmcs</a><br><br>');
echo ('<strong><h2>System Environment</h2></strong><b>Proxmox VE for WHMCS</b> v' . pvewhmcs_version() . ' (GitHub reports latest as <b>v' . get_pvewhmcs_latest_version() . '</b>)' . '<br><b>PHP</b> v' . phpversion() . ' running on <b>' . $_SERVER['SERVER_SOFTWARE'] . '</b> Web Server (' . $_SERVER['SERVER_NAME'] . ')<br><br>');
echo ('<strong><h2>Updates & Codebase</h2></strong><b>Proxmox for WHMCS is open-source and free to use & improve on! ❤️</b><br>Repo: <a href="https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/" target="_blank">https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/</a><br><br>');
echo ('<strong><h2>Product & Reviewing</h2></strong><b style="color:darkgreen;">Your 5-star review on WHMCS Marketplace will help the module grow!</b><br>*****: <a href="https://marketplace.whmcs.com/product/6935-proxmox-ve-for-whmcs" target="_blank">https://marketplace.whmcs.com/product/6935-proxmox-ve-for-whmcs</a><br><br>');
echo ('<strong><h2>Issues: Common Causes</h2></strong>1. <b>WHMCS needs to have >100 Services, else it is an illegal Proxmox VMID.</b><br>2. Save your Package (Plan/Pool)! (configproducts.php?action=edit&id=...#tab=3)<br>3. Where possible, we pass-through the exact error to WHMCS Admin. Check it for info!<br><br>');
echo ('<strong><h2>Module Technical Support</h2></strong>Please raise an <a href="https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/issues/new" target="_blank"><u>Issue</u></a> on GitHub - include logs, steps to reproduce, etc.<br>Help is not guaranteed (FOSS). We will need your assistance. <b>Thank you.</b><br><br>');
echo ('<strong><h2>Issues: Common Causes</h2></strong>1. Save your Package (Plan/Pool)! (configproducts.php?action=edit&id=...#tab=3)<br>2. Where possible, we pass-through the exact error to WHMCS Admin. Check it for info!<br><br>');
echo ('<strong><h2>Module Technical Support</h2></strong>Our README contains a wealth of information:<br><a href="https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/" target="_blank">https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/</a><br>Please only raise an <a href="https://github.com/The-Network-Crew/Proxmox-VE-for-WHMCS/issues/new" target="_blank"><u>Issue</u></a> on GitHub - inc. logs - if you\'ve properly tried.<br>Help is not guaranteed (FOSS). We will need your assistance. <b>Thank you!</b><br><br>');
echo '</div>';
// Config Tab
@@ -379,6 +379,12 @@ function pvewhmcs_output($vars) {
</td>
</tr>
<tr>
<td class="fieldlabel">VMID Start</td>
<td class="fieldarea">
<input type="text" size="35" name="start_vmid" id="start_vmid" value="'.$config->start_vmid.'"> Starting PVE VMID. Default is 100. Module will increment this until vacant VMID found.
</td>
</tr>
<tr>
<td class="fieldlabel">Debug Mode</td>
<td class="fieldarea">
<label class="checkbox-inline">
@@ -396,13 +402,142 @@ function pvewhmcs_output($vars) {
echo '</div>';
echo '</div>'; // end of tab-content
echo '</div>';
// End of tabbed content
// Handle saving the configuration if the form was submitted
if (isset($_POST['save_config'])) {
save_config() ;
}
}
// Import Guest sub-page handler (standalone, outside pvewhmcs_output)
// This function associates an existing PVE Guest in WHMCS as a new Client Service.
function import_guest() {
$resultMsg = '';
if (!empty($_POST['import_existing_guest'])) {
$vmid = intval($_POST['import_vmid']);
$userid = intval($_POST['import_clientid']);
$productid = intval($_POST['import_productid']);
$ipaddress = trim($_POST['import_ipv4']);
$subnetmask = trim($_POST['import_subnet']);
$gateway = trim($_POST['import_gateway']);
$hostname = trim($_POST['import_hostname']);
$vtype = ($_POST['import_vtype'] === 'lxc') ? 'lxc' : 'kvm';
// Validate Client ID
$client = Capsule::table('tblclients')->where('id', $userid)->where('status', 'Active')->first();
if (!$client) {
$resultMsg = '<div class="errorbox">No active WHMCS Client found with ID '.$userid.'</div>';
} else {
// Validate Product
$product = Capsule::table('tblproducts')->where('id', $productid)->where('retired', 0)->first();
if (!$product) {
$resultMsg = '<div class="errorbox">No active WHMCS Product found with ID '.$productid.'</div>';
} else {
// Create WHMCS Service (Order)
try {
// First, get the first Server ID that matches the product's server group
$serverRel = Capsule::table('tblservergroupsrel')->where('groupid', $product->servergroup)->first();
$serverID = $serverRel ? $serverRel->serverid : 0;
// Do the insertion to the tblhosting table
$serviceID = Capsule::table('tblhosting')->insertGetId([
'userid' => $userid,
'packageid' => $productid,
'regdate' => date('Y-m-d'),
'domain' => $hostname,
'paymentmethod' => 'banktransfer',
'firstpaymentamount' => $product->paytype == 'free' ? 0 : $product->monthly,
'amount' => $product->paytype == 'free' ? 0 : $product->monthly,
'billingcycle' => 'Monthly',
'nextduedate' => date('Y-m-d'),
'nextinvoicedate' => date('Y-m-d'),
'orderid' => 0,
'domainstatus' => 'Active',
'username' => 'root',
'password' => '',
'subscriptionid' => '',
'promoid' => 0,
'server' => $serverID,
'dedicatedip' => $ipaddress,
'assignedips' => $ipaddress,
'ns1' => '',
'ns2' => '',
'diskusage' => 0,
'disklimit' => 0,
'bwusage' => 0,
'bwlimit' => 0,
'lastupdate' => date('Y-m-d H:i:s'),
'suspendreason' => '',
'overideautosuspend' => 0,
'overidesuspenduntil' => '',
'notes' => 'PVEWHMCS: Imported from Proxmox Guest VMID '.$vmid,
]);
} catch (Exception $e) {
$resultMsg = '<div class="errorbox">Could not create WHMCS service: '.htmlspecialchars($e->getMessage()).'</div>';
$serviceID = false;
}
if ($serviceID) {
// Insert into module VMs table
try {
Capsule::table('mod_pvewhmcs_vms')->insert([
'id' => $serviceID,
'vmid' => $vmid,
'user_id' => $userid,
'vtype' => $vtype,
'ipaddress' => $ipaddress,
'subnetmask' => $subnetmask,
'gateway' => $gateway,
'created' => date('Y-m-d H:i:s'),
]);
$resultMsg = '<div class="successbox">Successfully imported PVE VMID '.$vmid.' (' . $vtype . ') as Service ' . $serviceID . ' (' . $product->name . ') for ' . $client->firstname . ' ' . $client->lastname . '. ' . $client->company . '</div>';
} catch (Exception $e) {
$resultMsg = '<div class="errorbox">Database error: '.htmlspecialchars($e->getMessage()).'</div>';
}
}
}
}
}
// Always show the form for easy further imports
if (!empty($resultMsg)) echo $resultMsg;
echo '<form method="post">';
echo '<table class="form" border="0" cellpadding="3" cellspacing="1" width="100%">';
echo '<tr><td class="fieldlabel">PVE VMID</td><td class="fieldarea"><input type="text" name="import_vmid" required></td></tr>';
echo '<tr><td class="fieldlabel">Hostname</td><td class="fieldarea"><input type="text" name="import_hostname" required></td></tr>';
// Active clients dropdown
$clients = Capsule::table('tblclients')->where('status', 'Active')->orderBy('companyname')->orderBy('firstname')->orderBy('lastname')->get();
echo '<tr><td class="fieldlabel">Target Client</td><td class="fieldarea"><select name="import_clientid" required>';
foreach ($clients as $client) {
$label = $client->id.' - '.($client->companyname ? $client->companyname.' - ' : '').$client->firstname.' '.$client->lastname;
echo '<option value="'.$client->id.'">'.htmlspecialchars($label).'</option>';
}
echo '</select></td></tr>';
// Product/Service dropdown (only Active products of Server type)
$products = Capsule::table('tblproducts')->where('type', 'server')->where('retired', 0)->orderBy('name')->get();
echo '<tr><td class="fieldlabel">Service</td><td class="fieldarea"><select name="import_productid" required>';
foreach ($products as $product) {
echo '<option value="'.$product->id.'">'.htmlspecialchars($product->name).'</option>';
}
echo '</select></td></tr>';
// Guest Type dropdown
echo '<tr><td class="fieldlabel">VM/CT</td><td class="fieldarea"><select name="import_vtype" required>';
echo '<option value="kvm">(VM) QEMU</option>';
echo '<option value="lxc">(CT) LXC</option>';
echo '</select></td></tr>';
// IPv4, Subnet, Gateway
echo '<tr><td class="fieldlabel">IPv4</td><td class="fieldarea"><input type="text" name="import_ipv4" required></td></tr>';
echo '<tr><td class="fieldlabel">Subnet</td><td class="fieldarea"><input type="text" name="import_subnet" required></td></tr>';
echo '<tr><td class="fieldlabel">Gateway</td><td class="fieldarea"><input type="text" name="import_gateway" required></td></tr>';
echo '</table>';
echo '<div class="btn-container"><input type="submit" class="btn btn-primary" value="Import Guest" name="import_existing_guest" id="import_existing_guest"></div>';
echo '</form>';
}
// MODULE CONFIG: Commit changes to the database
function save_config() {
try {
@@ -413,6 +548,7 @@ function save_config() {
$connectionManager->table('mod_pvewhmcs')->update(
[
'vnc_secret' => $_POST['vnc_secret'],
'start_vmid' => $_POST['start_vmid'],
'debug_mode' => $_POST['debug_mode'],
]
);
@@ -573,7 +709,7 @@ function kvm_plan_add() {
RAM space in Megabyte e.g 1024 = 1GB (default is 2GB)
</td>
</tr>
<tr>
<tr>
<td class="fieldlabel">RAM - Balloon</td>
<td class="fieldarea">
<input type="text" size="8" name="balloon" id="balloon" value="0" required>
@@ -623,7 +759,7 @@ function kvm_plan_add() {
Virtio is the fastest option, then SCSI, then SATA, etc.
</td>
</tr>
<tr>
<tr>
<td class="fieldlabel">Disk - I/O Cap</td>
<td class="fieldarea">
<input type="text" size="8" name="diskio" id="diskio" value="0" required>
@@ -651,18 +787,18 @@ function kvm_plan_add() {
<tr>
<td class="fieldlabel">Network - Rate</td>
<td class="fieldarea">
<input type="text" size="8" name="netrate" id="netrate">
Network Rate Limit in Megabit/Second, Blank means unlimited.
<input type="text" size="8" name="netrate" id="netrate" value="0">
Network Rate Limit in Megabit/Second. Zero for unlimited.
</td>
</tr>
<tr>
<td class="fieldlabel">Network - BW Limit</td>
<td class="fieldarea">
<input type="text" size="8" name="bw" id="bw">
Monthly Bandwidth Limit in Gigabytes, Blank means unlimited.
Monthly Bandwidth Limit in Gigabytes. Blank for unlimited.
</td>
</tr>
<tr>
<tr>
<td class="fieldlabel">Network - IPv6 Conf.</td>
<td class="fieldarea">
<select class="form-control select-inline" name="ipv6">
@@ -889,7 +1025,7 @@ function kvm_plan_edit($id) {
RAM space in Megabytes e.g 1024 = 1GB
</td>
</tr>
<tr>
<tr>
<td class="fieldlabel">RAM - Balloon</td>
<td class="fieldarea">
<input type="text" size="8" name="balloon" id="balloon" required value="'.$plan->balloon.'">
@@ -939,7 +1075,7 @@ function kvm_plan_edit($id) {
Virtio is the fastest option, then SCSI, then SATA, etc.
</td>
</tr>
<tr>
<tr>
<td class="fieldlabel">Disk - I/O Cap</td>
<td class="fieldarea">
<input type="text" size="8" name="diskio" id="diskio" required value="'.$plan->diskio.'">
@@ -968,17 +1104,17 @@ function kvm_plan_edit($id) {
<td class="fieldlabel">Network - Rate</td>
<td class="fieldarea">
<input type="text" size="8" name="netrate" id="netrate" value="'.$plan->netrate.'">
Network Rate Limit in Megabit, Blank means unlimited.
Network Rate Limit in Megabit. Zero for unlimited.
</td>
</tr>
<tr>
<td class="fieldlabel">Network - BW Limit</td>
<td class="fieldarea">
<input type="text" size="8" name="bw" id="bw" value="'.$plan->bw.'">
Monthly Bandwidth Limit in Gigabyte, Blank means unlimited.
Monthly Bandwidth Limit in Gigabyte. Blank for unlimited.
</td>
</tr>
<tr>
<tr>
<td class="fieldlabel">Network - IPv6 Conf.</td>
<td class="fieldarea">
<select class="form-control select-inline" name="ipv6">
@@ -1096,7 +1232,7 @@ function lxc_plan_add() {
HDD/SSD storage space in Gigabytes e.g 1024 = 1TB
</td>
</tr>
<tr>
<tr>
<td class="fieldlabel">Disk - I/O Cap</td>
<td class="fieldarea">
<input type="text" size="8" name="diskio" id="diskio" value="0" required>
@@ -1134,18 +1270,18 @@ function lxc_plan_add() {
<tr>
<td class="fieldlabel">Network - Rate</td>
<td class="fieldarea">
<input type="text" size="8" name="netrate" id="netrate">
Network Rate Limit in Megabit/Second, blank means unlimited.
<input type="text" size="8" name="netrate" id="netrate" value="0">
Network Rate Limit in Megabit/Second. Zero for unlimited.
</td>
</tr>
<tr>
<td class="fieldlabel">Data - Monthly</td>
<td class="fieldarea">
<input type="text" size="8" name="bw" id="bw">
Monthly Bandwidth Limit in Gigabytes, blank means unlimited.
Monthly Bandwidth Limit in Gigabytes. Blank for unlimited.
</td>
</tr>
<tr>
<tr>
<td class="fieldlabel">Network - IPv6 Conf.</td>
<td class="fieldarea">
<select class="form-control select-inline" name="ipv6">
@@ -1231,7 +1367,7 @@ function lxc_plan_edit($id) {
HDD/SSD storage space in Gigabytes e.g 1024 = 1TB
</td>
</tr>
<tr>
<tr>
<td class="fieldlabel">Disk - I/O Cap</td>
<td class="fieldarea">
<input type="text" size="8" name="diskio" id="diskio" value="'.$plan->diskio.'" required>
@@ -1270,17 +1406,17 @@ function lxc_plan_edit($id) {
<td class="fieldlabel">Network - Rate</td>
<td class="fieldarea">
<input type="text" size="8" name="netrate" id="netrate" value="'.$plan->netrate.'">
Network Rate Limit in Megabit/Second, blank means unlimited.
Network Rate Limit in Megabit/Second. Zero for unlimited.
</td>
</tr>
<tr>
<td class="fieldlabel">Network - BW Limit</td>
<td class="fieldarea">
<input type="text" size="8" name="bw" id="bw" value="'.$plan->bw.'">
Monthly Bandwidth Limit in Gigabytes, blank means unlimited.
Monthly Bandwidth Limit in Gigabytes. Blank for unlimited.
</td>
</tr>
<tr>
<tr>
<td class="fieldlabel">Network - IPv6 Conf.</td>
<td class="fieldarea">
<select class="form-control select-inline" name="ipv6">
@@ -1350,8 +1486,8 @@ function save_kvm_plan() {
);
}
);
$_SESSION['pvewhmcs']['infomsg']['title']='KVM Plan added.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Saved the KVM Plan successfuly.' ;
$_SESSION['pvewhmcs']['infomsg']['title']='QEMU Plan added.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Saved the QEMU Plan successfully.' ;
header("Location: ".pvewhmcs_BASEURL."&tab=vmplans&action=planlist");
} catch (\Exception $e) {
echo "Uh oh! Inserting didn't work, but I was able to rollback. {$e->getMessage()}";
@@ -1392,8 +1528,8 @@ function update_kvm_plan() {
'onboot' => $_POST['onboot'],
]
);
$_SESSION['pvewhmcs']['infomsg']['title']='KVM Plan updated.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Updated the KVM Plan successfuly.' ;
$_SESSION['pvewhmcs']['infomsg']['title']='QEMU Plan updated.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Updated the QEMU Plan successfully. (Updating plans will not alter existing VMs)' ;
header("Location: ".pvewhmcs_BASEURL."&tab=vmplans&action=planlist");
}
@@ -1402,7 +1538,7 @@ function remove_plan($id) {
Capsule::table('mod_pvewhmcs_plans')->where('id', '=', $id)->delete();
header("Location: ".pvewhmcs_BASEURL."&tab=vmplans&action=planlist");
$_SESSION['pvewhmcs']['infomsg']['title']='Plan Deleted.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Selected Item deleted successfuly.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Selected Item deleted successfully.' ;
}
// MODULE FORM ACTION: Save LXC Plan
@@ -1437,7 +1573,7 @@ function save_lxc_plan() {
}
);
$_SESSION['pvewhmcs']['infomsg']['title']='New LXC Plan added.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Saved the LXC Plan successfuly.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Saved the LXC Plan successfully.' ;
header("Location: ".pvewhmcs_BASEURL."&tab=vmplans&action=planlist");
} catch (\Exception $e) {
echo "Uh oh! Inserting didn't work, but I was able to rollback. {$e->getMessage()}";
@@ -1471,13 +1607,13 @@ function update_lxc_plan() {
]
);
$_SESSION['pvewhmcs']['infomsg']['title']='LXC Plan updated.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Updated the LXC Plan successfully. (Updating plans will not effect on current VMs.)' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Updated the LXC Plan successfully. (Updating plans will not alter existing CTs)' ;
header("Location: ".pvewhmcs_BASEURL."&tab=vmplans&action=planlist");
}
// IP POOLS: List all Pools
function list_ip_pools() {
echo '<a class="btn btn-default" href="'. pvewhmcs_BASEURL .'&amp;tab=ippools&amp;action=new_ip_pool"><i class="fa fa-plus-square"></i>&nbsp; New IP Pool</a>';
echo '<a class="btn btn-default" href="'. pvewhmcs_BASEURL .'&amp;tab=ippools&amp;action=new_ip_pool"><i class="fa fa-plus-square"></i>&nbsp; New IPv4 Pool</a>';
echo '<table class="datatable"><tr><th>ID</th><th>Pool</th><th>Gateway</th><th>Action</th></tr>';
foreach (Capsule::table('mod_pvewhmcs_ip_pools')->get() as $pool) {
echo '<tr>';
@@ -1486,7 +1622,7 @@ function list_ip_pools() {
echo '<td>'.$pool->gateway . PHP_EOL .'</td>';
echo '<td>
<a href="'.pvewhmcs_BASEURL.'&amp;tab=ippools&amp;action=list_ips&amp;id='.$pool->id.'"><img height="16" width="16" border="0" alt="Info" src="images/edit.gif"></a>
<a href="'.pvewhmcs_BASEURL.'&amp;tab=ippools&amp;action=removeippool&amp;id='.$pool->id.'" onclick="return confirm(\'Pool and all IP Addresses assigned to it will be deleted, are you sure to continue?\')"><img height="16" width="16" border="0" alt="Remove" src="images/delete.gif"></a>
<a href="'.pvewhmcs_BASEURL.'&amp;tab=ippools&amp;action=removeippool&amp;id='.$pool->id.'" onclick="return confirm(\'Pool and all IPv4 Addresses assigned to it will be deleted, continue?\')"><img height="16" width="16" border="0" alt="Remove" src="images/delete.gif"></a>
</td>' ;
echo '</tr>' ;
}
@@ -1503,7 +1639,7 @@ function add_ip_pool() {
<td class="fieldarea">
<input type="text" size="35" name="title" id="title" required>
</td>
<td class="fieldlabel">Gateway</td>
<td class="fieldlabel">IPv4 Gateway</td>
<td class="fieldarea">
<input type="text" size="25" name="gateway" id="gateway" required>
Gateway address of the pool
@@ -1530,8 +1666,8 @@ function save_ip_pool() {
);
}
);
$_SESSION['pvewhmcs']['infomsg']['title']='New IP Pool added.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='New IP Pool saved successfully.' ;
$_SESSION['pvewhmcs']['infomsg']['title']='New IPv4 Pool added.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='New IPv4 Pool saved successfully.' ;
header("Location: ".pvewhmcs_BASEURL."&tab=ippools&action=list_ip_pools");
} catch (\Exception $e) {
echo "Uh oh! Inserting didn't work, but I was able to rollback. {$e->getMessage()}";
@@ -1544,8 +1680,8 @@ function removeIpPool($id) {
Capsule::table('mod_pvewhmcs_ip_pools')->where('id', '=', $id)->delete();
header("Location: ".pvewhmcs_BASEURL."&tab=ippools&action=list_ip_pools");
$_SESSION['pvewhmcs']['infomsg']['title']='IP Pool Deleted.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Deleted the IP Pool successfully.' ;
$_SESSION['pvewhmcs']['infomsg']['title']='IPv4 Pool Deleted.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Deleted the IPv4 Pool successfully.' ;
}
// IP POOL FORM ACTION: Add IP to Pool
@@ -1554,7 +1690,7 @@ function add_ip_2_pool() {
echo '<form method="post">
<table class="form" border="0" cellpadding="3" cellspacing="1" width="100%">
<tr>
<td class="fieldlabel">IP Pool</td>
<td class="fieldlabel">IPv4 Pool</td>
<td class="fieldarea">
<select class="form-control select-inline" name="pool_id">';
foreach (Capsule::table('mod_pvewhmcs_ip_pools')->get() as $pool) {
@@ -1565,14 +1701,14 @@ function add_ip_2_pool() {
</td>
</tr>
<tr>
<td class="fieldlabel">IP Block</td>
<td class="fieldlabel">Address/Prefix</td>
<td class="fieldarea">
<input type="text" name="ipblock"/>
IP Block with CIDR e.g. 172.16.255.230/27, for single IP address just don\'t use CIDR
IPv4 prefix with CIDR e.g. 172.16.255.230/27, or for single /32 address don\'t use CIDR
</td>
</tr>
</table>
<input type="submit" name="assignIP2pool" value="Save"/>
<input type="submit" name="assignIP2pool" value="Add"/>
</form>';
if (isset($_POST['assignIP2pool'])) {
// check if single IP address
@@ -1603,8 +1739,8 @@ function add_ip_2_pool() {
}
}
header("Location: ".pvewhmcs_BASEURL."&tab=ippools&action=list_ips&id=".$_POST['pool_id']);
$_SESSION['pvewhmcs']['infomsg']['title']='IP Address/Blocks added to Pool.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='You can remove IP Addresses from the pool.' ;
$_SESSION['pvewhmcs']['infomsg']['title']='IPv4 Address/Blocks added to Pool.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='You can remove IPv4 Addresses from the pool.' ;
}
}
@@ -1612,13 +1748,13 @@ function add_ip_2_pool() {
function list_ips() {
//echo '<script>$(function() {$( "#dialog" ).dialog();});</script>' ;
//echo '<div id="dialog">' ;
echo '<table class="datatable"><tr><th>IP Address</th><th>Subnet Mask</th><th>Action</th></tr>' ;
echo '<table class="datatable"><tr><th>IPv4 Address</th><th>Subnet Mask</th><th>Action</th></tr>' ;
foreach (Capsule::table('mod_pvewhmcs_ip_addresses')->where('pool_id', '=', $_GET['id'])->get() as $ip) {
echo '<tr><td>'.$ip->ipaddress.'</td><td>'.$ip->mask.'</td><td>';
if (count(Capsule::table('mod_pvewhmcs_vms')->where('ipaddress','=',$ip->ipaddress)->get())>0)
echo 'is in use' ;
else
echo '<a href="'.pvewhmcs_BASEURL.'&amp;tab=ippools&amp;action=removeip&amp;pool_id='.$ip->pool_id.'&amp;id='.$ip->id.'" onclick="return confirm(\'IP Address will be deleted from the pool, continue?\')"><img height="16" width="16" border="0" alt="Edit" src="images/delete.gif"></a>';
echo '<a href="'.pvewhmcs_BASEURL.'&amp;tab=ippools&amp;action=removeip&amp;pool_id='.$ip->pool_id.'&amp;id='.$ip->id.'" onclick="return confirm(\'IPv4 Address will be deleted from the pool, continue?\')"><img height="16" width="16" border="0" alt="Edit" src="images/delete.gif"></a>';
echo '</td></tr>';
}
echo '</table>' ;
@@ -1629,7 +1765,7 @@ function list_ips() {
function removeip($id,$pool_id) {
Capsule::table('mod_pvewhmcs_ip_addresses')->where('id', '=', $id)->delete();
header("Location: ".pvewhmcs_BASEURL."&tab=ippools&action=list_ips&id=".$pool_id);
$_SESSION['pvewhmcs']['infomsg']['title']='IP Address deleted.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Deleted selected item successfuly.' ;
$_SESSION['pvewhmcs']['infomsg']['title']='IPv4 Address deleted.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='Deleted selected item successfully.' ;
}
?>
?>

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
@@ -49,7 +50,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,7 +75,7 @@ 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",
@@ -115,6 +116,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 +130,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 +188,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 +218,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 +228,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 +236,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,13 +251,12 @@ 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['password'] = $params['customfields']['Password'];
} else {
@@ -257,15 +267,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 +288,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 +313,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 +326,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 +348,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 +411,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 +444,31 @@ function pvewhmcs_CreateAccount($params) {
}
}
/**
* Find the next available VMID starting from the given ID
* @param PVE2_API $proxmox Proxmox API instance
* @param string $node Node name
* @param int $start_vmid Starting VMID to search from
* @return int Next available VMID
* @throws Exception if no VMID available within reasonable range
*/
function pvewhmcs_find_next_available_vmid($proxmox, $node, $start_vmid) {
$vmid = $start_vmid;
$max_attempts = 1000;
$attempts = 0;
while (!is_null($proxmox->get('/nodes/' . $node . '/qemu/' . $vmid . '/status/current')) ||
!is_null($proxmox->get('/nodes/' . $node . '/lxc/' . $vmid . '/status/current'))) {
$vmid++;
$attempts++;
if ($attempts > $max_attempts) {
throw new Exception("Unable to find available VMID after $max_attempts attempts");
}
}
return (int)$vmid;
}
// PVE API FUNCTION, ADMIN: Test Connection with Proxmox node
function pvewhmcs_TestConnection(array $params) {
try {
@@ -760,7 +802,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');
@@ -835,19 +877,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,7 +907,7 @@ 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 {
@@ -872,97 +922,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 +1026,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 +1067,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 +1104,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 +1140,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 +1179,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 +1222,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 +1274,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 +1317,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 +1388,4 @@ function time2format($s) {
}
return $str;
}
?>
?>

View File

@@ -1 +1 @@
1.2.8
1.2.10

BIN
zVMIDimport.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB