11 Commits

Author SHA1 Message Date
Luke S Thompson
f44647c170 v1.2.1: noVNC OK, Tidy-up GUI 2023-06-19 16:55:22 +10:00
Luke S Thompson
bac101e6d8 noVNC working OK via dual-auth 2023-06-19 15:58:21 +10:00
Luke S Thompson
1c0fe39e28 VM Reboot action; noVNC next steps 2023-06-19 15:51:06 +10:00
Luke S Thompson
d1e6694b3c Client Area: Improve VM/CT spec display/language 2023-06-19 13:27:28 +10:00
Luke S Thompson
2d1a9a8461 Pre-removal: Demote TigerVNC from root to vnc 2023-06-19 13:14:57 +10:00
Luke S Thompson
9acf5ea188 noVNC: More ground-work on dual-ticket 2023-06-19 12:04:58 +10:00
Luke S Thompson
cb263ce100 v1.2.1 partial: noVNC overhaul beginnings; etc. 2023-06-19 10:47:13 +10:00
Luke S Thompson
1edc89a1e3 noVNC: Change backend proxy params 2023-06-18 20:34:43 +10:00
Luke S Thompson
0ea7243a69 v1.2.1: Fix VNC errors; minor tweaks 2023-06-18 20:16:53 +10:00
Luke S Thompson
98ec70eae6 noVNC: Attempt at resolving out-of-order data 2023-06-18 19:50:54 +10:00
Luke S Thompson
4030c94762 Client menu re-arrange; Admin health tweak 2023-06-18 17:54:36 +10:00
23 changed files with 206 additions and 39 deletions

View File

@@ -1,7 +1,27 @@
# Changelog
All notable changes to Proxmox VE for WHMCS will be documented in this file.
## [1.2.0b] - 2013-06-18
## [1.2.1b] - 2023-06-19
### Added
- Module Config tab, allowing for configuration of the VNC Secret
- Reboot command/action added to Client Area (ie. on/off/hard-off)
- Link from Health tab of Admin GUI to WHMCS Marketplace re: reviews
- Images for all supported Operating Systems & Kernel types (some fixed)
- Ground-work for noVNC overhaul, to support PVE Auth & VNC Tunnel tickets
### Changed
- Stop VM/CT (Client Area) renamed to Hard Stop, compared to Shut Down
- Modify the PHP API2 class, adding getTicket() so we can dual-auth (VNC)
- Move VNC Clients from root-level to vnc-only-level access to Proxmox VE
### Fixed
- noVNC render method updated to stop out-of-order data flow problem
- noVNC back-end vncproxy and vncwebsocket methods updated re: spec
- Client Area actions (Power Off/On, etc) fixed for LXC (QEMU OK)
- Error with both VNC methods. We are going to remove TigerVNC
## [1.2.0b] - 2023-06-18
### Added
- Link off to GitHub Issues for Support from the Module page in WHMCS

View File

@@ -15,12 +15,38 @@ https://marketplace.whmcs.com/product/6935-proxmox-ve-for-whmcs
- (WHMCS) Service ID >100
- (PHP) v8.x.x stable
- (Proxmox) VE v7/8
- (Proxmox) 2 users
**SID >100:** The WHMCS Service ID requirement is critical, as Proxmox reserves VMIDs <100.
_If you don't have enough services (any status) in WHMCS, create services until you reach SID 101._
**PROXMOX 8.x:** As this major release is in beta (as of June 2023), support is experimental.
### 🥽 noVNC CONSOLE TUNNELING:
To access VNC via WHMCS Client Area, you need to:
1. Follow the PVE User Requirement below
2. PVE and WHMCS on the same Domain Name*
3. Have valid PTR/rDNS for the PVE Address
**WIP NOTE:** noVNC has been overhauled. It is not guaranteed, nor the project at all. :-)
\* = You must use different Subdomains on the same Domain Name, for the cookie (anti-CSRF).
\* = If your Domain Name has a 2-part TLD (ie. co.uk) then you will need to amend the code.
### 👥 PROXMOX USER REQUIREMENT:
You must have a root (etc) account to Create/Access services. Configured via WHMCS Config > Servers.
Additionally, to improve security, for VNC you must have a Restricted User. "" via Module Config.
For the VNC User in Proxmox you need to:
1. Create User Group "VNC" via PVE > Datacenter / Permissions / Group
2. Create new User "vnc" > Datacenter / Permissions / Users - select Group: "VNC", Realm: pve
3. Create new Role -> Datacenter / Permissions / Roles - select Name: "VNC", Privileges: VM.Console (only)
4. Add permission to access VNC -> Datacenter / Node / VM / Permissions / Add Group Permissions - select Group: "VNC", Role: "VNC"
5. Configure the WHMCS > Modules > Proxmox VE for WHMCS > Module Config > VNC Secret with 'vnc' password.
### 🤬 ABUSE - ZERO TOLERANCE:

View File

@@ -1,6 +1,7 @@
CREATE TABLE IF NOT EXISTS `mod_pvewhmcs` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`config` text,
`config` varchar(255),
`vnc_secret` varchar(255),
PRIMARY KEY (`id`)
);
INSERT INTO `mod_pvewhmcs` (`id`, `config`) VALUES (1, NULL);

View File

@@ -133,6 +133,15 @@ class PVE2_API {
setrawcookie("PVEAuthCookie", $this->login_ticket['ticket'], 0, "/");
}
# Gets the PVE Access Ticket
public function getTicket() {
if ($this->login_ticket['ticket']) {
return $this->login_ticket['ticket'];
} else {
return false;
}
}
/*
* bool check_login_ticket ()
* Checks if the login ticket is valid still, returns false if not.

View File

@@ -7,7 +7,7 @@ function pvewhmcs_config() {
$configarray = array(
"name" => "Proxmox VE for WHMCS",
"description" => "Proxmox Virtual Environment + WHMCS",
"version" => "1.2.0",
"version" => "1.2.1",
"author" => "The Network Crew Pty Ltd",
'language' => 'English'
);
@@ -15,7 +15,7 @@ function pvewhmcs_config() {
}
function pvewhmcs_version(){
return "1.2.0";
return "1.2.1";
}
function pvewhmcs_activate() {
@@ -75,6 +75,7 @@ function pvewhmcs_output($vars) {
<li class="'.($_GET['tab']=="vmplans" ? "active" : "").'"><a id="tabLink1" data-toggle="tab" role="tab" href="#plans">VM Plans</a></li>
<li class="'.($_GET['tab']=="ippools" ? "active" : "").'"><a id="tabLink2" data-toggle="tab" role="tab" href="#ippools">IP Pools</a></li>
<li class="'.($_GET['tab']=="health" ? "active" : "").'"><a id="tabLink3" data-toggle="tab" role="tab" href="#health">Support / Health</a></li>
<li class="'.($_GET['tab']=="config" ? "active" : "").'"><a id="tabLink4" data-toggle="tab" role="tab" href="#config">Module Config</a></li>
</ul>
</div>
<div class="tab-content admin-tabs">
@@ -269,12 +270,62 @@ function pvewhmcs_output($vars) {
';
// Health Tab
echo '<div id="health" class="tab-pane '.($_GET['tab']=="health" ? "active" : "").'" >' ;
echo ('<h2>Technical Support:</h2>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. Thank you.<br><br>');
echo ('<h2>System Environment:</h2>Proxmox VE for WHMCS v' . pvewhmcs_version() . ' on PHP v' . phpversion() . ' (' . $_SERVER['SERVER_SOFTWARE'] . ')<br><br>');
echo ('<h2>Technical Support:</h2>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><br>');
echo ('<h2>Updates & Codebase:</h2><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 ('<h2>System Environment:</h2>Proxmox VE for WHMCS v' . pvewhmcs_version() . ' on PHP v' . phpversion() . ' (' . $_SERVER['SERVER_SOFTWARE'] . ')');
echo ('<h2>Product & Reviewing</h2><b>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 '</div>';
// Config Tab
$config= Capsule::table('mod_pvewhmcs')->where('id', '=', '1')->get()[0];
echo '<div id="config" class="tab-pane '.($_GET['tab']=="config" ? "active" : "").'" >' ;
echo '
<form method="post">
<table class="form" border="0" cellpadding="3" cellspacing="1" width="100%">
<tr>
<td class="fieldlabel">VNC Secret</td>
<td class="fieldarea">
<input type="text" size="35" name="vnc_secret" id="vnc_secret" value="'.$config->vnc_secret.'">
</td>
</tr>
</table>
<div class="btn-container">
<input type="submit" class="btn btn-primary" value="Save Changes" name="save_config" id="save_config">
<input type="reset" class="btn btn-default" value="Cancel Changes">
</div>
</form>
';
echo '</div>';
echo '</div>'; // end of tab-content
if (isset($_POST['save_config'])) {
save_config() ;
}
}
/* commit module config to DB */
function save_config() {
try {
Capsule::connection()->transaction(
function ($connectionManager)
{
/** @var \Illuminate\Database\Connection $connectionManager */
$connectionManager->table('mod_pvewhmcs')->update(
[
'vnc_secret' => $_POST['vnc_secret'],
]
);
}
);
$_SESSION['pvewhmcs']['infomsg']['title']='Module Config saved.' ;
$_SESSION['pvewhmcs']['infomsg']['message']='New options have been successfully saved.' ;
header("Location: ".pvewhmcs_BASEURL."&tab=config");
} catch (\Exception $e) {
echo "Uh oh! That didn't work, but I was able to rollback. {$e->getMessage()}";
}
}
/* adding a KVM plan */

View File

@@ -57,19 +57,19 @@
<table class="table table-bordered table-striped">
<tr>
<td>Network Addressing</td><td>{$vm_config['ipv4']}&nbsp;Subnet Mask:&nbsp;{$vm_config['netmask4']}&nbsp;Gateway:&nbsp;{$vm_config['gateway4']}</td>
<td>Network 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>OS (Type)</td>
<td>{$vm_config['ostype']}</td>
<td>Kernel/System:&nbsp;{$vm_config['ostype']}</td>
</tr>
<tr>
<td>CPU (Spec)</td>
<td>{$vm_config['sockets']}&nbsp;{$vm_config['cpu']}&nbsp;{$vm_config['cores']}&nbsp;core(s).</td>
<td>{$vm_config['sockets']}&nbsp;socket/s,&nbsp;{$vm_config['cores']}&nbsp;core/s ({$vm_config['cpu']})</td>
</tr>
<tr>
<td>Memory (RAM)</td>
<td>{$vm_config['memory']}&nbsp;MB</td>
<td>{$vm_config['memory']}MB</td>
</tr>
<tr>
<td>Network Interface #1</td>
@@ -86,8 +86,8 @@
{$disk=(","|explode:$vm_config['ide0'])}
{$disk[1]}
{$rootfs[1]}
{$vm_config['scsi0']}
{$vm_config['virtio0']}
{($vm_config['scsi0']|replace:',':'<br/>')}
{($vm_config['virtio0']|replace:',':'<br/>')}
</td>
</tr>
</table>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,24 @@
<?php
// FILE: novnc_router.php
// TASK: Take WHMCS request, add browser cookie, then redirect to noVNC
if (isset($_GET['pveticket']) && isset($_GET['host']) && isset($_GET['path']) && isset($_GET['vncticket'])) {
$pveticket = $_GET['pveticket'];
$vncticket = $_GET['vncticket'];
$host = $_GET['host'];
$path = $_GET['path'];
// Get the requesting hostname/domain from request
$whmcsdomain = parse_url($_SERVER['HTTP_HOST']);
$domainonly = preg_replace("/^(.*?)\.(.*)$/","$2",$whmcsdomain['path']);
setrawcookie('PVEAuthCookie', $pveticket, 0, '/', $domainonly);
// Create the final noVNC URL with the re-encoded vncticket
$hostname = gethostbyaddr($host);
$redirect_url = '/modules/servers/pvewhmcs/novnc/vnc.html?autoconnect=true&encrypt=true&host=' . $hostname . '&port=8006&password=' . urlencode($vncticket) . '&path=' . urlencode($path);
header('Location: ' . $redirect_url);
exit;
} else {
echo 'Error: Missing required info to route your request. Please try again.';
}
?>

View File

@@ -521,11 +521,12 @@ function get_server_pass_from_whmcs($enc_pass){
function pvewhmcs_ClientAreaCustomButtonArray() {
$buttonarray = array(
"<img src='./modules/servers/pvewhmcs/img/tigervnc.png'/> TigerVNC (Java)" => "javaVNC",
"<img src='./modules/servers/pvewhmcs/img/novnc.png'/> noVNC (HTML5)" => "noVNC",
"<i class='fa fa-2x fa-flag-checkered'></i> Start VM/CT" => "vmStart",
"<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-power-off'></i> Shut Down" => "vmShutdown",
"<i class='fa fa-2x fa-stop'></i> Stop VM/CT" => "vmStop",
"<i class='fa fa-2x fa-stop'></i> Hard Stop" => "vmStop",
"<i class='fa fa-2x fa-chart-bar'></i> Statistics" => "vmStat",
);
return $buttonarray;
@@ -712,11 +713,10 @@ function pvewhmcs_vmStat($params) {
function pvewhmcs_noVNC($params) {
$serverip = $params["serverip"];
$serverusername = $params["serverusername"];
$serverpassword = $params["serverpassword"];
$proxmox=new PVE2_API($serverip, $serverusername, "pam", $serverpassword);
$serverusername = 'vnc';
$serverpassword = Capsule::table('mod_pvewhmcs')->where('id', '1')->value('vnc_secret');
$proxmox=new PVE2_API($serverip, $serverusername, "pve", $serverpassword);
if ($proxmox->login()) {
//$proxmox->setCookie() ;
# Get first node name.
$nodes = $proxmox->get_node_list();
$first_node = $nodes[0];
@@ -724,23 +724,29 @@ function pvewhmcs_noVNC($params) {
$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' )) ;
$path = 'api2/json/websocket?port=' . $vm_vncproxy['port'] . '&user=' . $serverusername . '@pam' . '&vmid=' . $params['serviceid'] . '&vncticket=' . urlencode($vm_vncproxy['ticket']);
// 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);
$url = '/modules/servers/pvewhmcs/novnc_router.php?host=' . $serverip . '&pveticket=' . urlencode($pveticket) . '&path=' . urlencode($path) . '&vncticket=' . urlencode($vncticket);
$vncreply='<center><strong>Console (noVNC) prepared for usage. <a href="'.$url.'" target="_blanK">Click here</a> to open the noVNC window.</strong></center>' ;
$url='./modules/servers/pvewhmcs/novnc/novnc_pve.php?host='.$serverip.'&port=8006&ticket='.$vm_vncproxy['ticket'].'&path='.urlencode($path) ;
echo '<script>window.open("'.$url.'")</script>';
return $vncreply;
//echo '<script>window.open("./modules/servers/pvewhmcs/noVNC/vnc.php?node=pve&console=lxc&vmid=136&port='.$vm_vncwebsocket['port'].'&ticket='.$vm_vncproxy['ticket'].'")</script>';
} else {
$vncreply='Failed to prepare noVNC. Please contact Technical Support.';
return $vncreply;
}
}
function pvewhmcs_javaVNC($params){
$serverip = $params["serverip"];
$serverusername = $params["serverusername"];
$serverpassword = $params["serverpassword"];
$proxmox=new PVE2_API($serverip, $serverusername, "pam", $serverpassword);
$serverusername = 'vnc';
$serverpassword = Capsule::table('mod_pvewhmcs')->where('id', '1')->value('vnc_secret');
$proxmox=new PVE2_API($serverip, $serverusername, "pve", $serverpassword);
if ($proxmox->login()) {
//$proxmox->setCookie();
# Get first node name.
$nodes = $proxmox->get_node_list();
$first_node = $nodes[0];
@@ -748,7 +754,8 @@ function pvewhmcs_javaVNC($params){
$guest=Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
$vm_vncproxy=$proxmox->post('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/vncproxy') ;
$vncparams = array();
$vm_vncproxy=$proxmox->post('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/vncproxy', $vncparams) ;
$javaVNCparams=array() ;
$javaVNCparams[0]=$serverip ;
@@ -757,10 +764,14 @@ function pvewhmcs_javaVNC($params){
$javaVNCparams[3]=$vm_vncproxy['user'] ;
$javaVNCparams[4]=$vm_vncproxy['ticket'] ;
echo '<script>window.open("modules/servers/pvewhmcs/tigervnc.php?'.http_build_query($javaVNCparams).'","VNC","location=0,toolbar=0,menubar=0,scrollbars=1,resizable=1,width=802,height=624")</script>';
return true ;
$url='./modules/servers/pvewhmcs/tigervnc.php?'.http_build_query($javaVNCparams).'' ;
$vncreply='<center><strong>Console (TigerVNC) prepared for usage. <a href="'.$url.'" target="_blanK">Click here</a> to open the TigerVNC window.</strong></center>' ;
// echo '<script>window.open("modules/servers/pvewhmcs/tigervnc.php?'.http_build_query($javaVNCparams).'","VNC","location=0,toolbar=0,menubar=0,scrollbars=1,resizable=1,width=802,height=624")</script>';
return $vncreply;
} else {
$vncreply='Failed to prepare TigerVNC. Please contact Technical Support.';
return $vncreply;
}
return false;
}
function pvewhmcs_vmStart($params) {
@@ -777,14 +788,13 @@ function pvewhmcs_vmStart($params) {
$serverpassword = localAPI('DecryptPassword', $api_data);
$proxmox=new PVE2_API($serverip, $serverusername, "pam", $serverpassword['password']);
if ($proxmox->login()) {
//$proxmox->setCookie();
# Get first node name.
$nodes = $proxmox->get_node_list();
$first_node = $nodes[0];
unset($nodes);
$guest=Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
$pve_cmdparam = array();
$pve_cmdparam['timeout'] = '60';
// $pve_cmdparam['timeout'] = '60';
if ($proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/start' , $pve_cmdparam))
return true ;
@@ -792,6 +802,34 @@ function pvewhmcs_vmStart($params) {
return false;
}
function pvewhmcs_vmReboot($params) {
// Gather access credentials for PVE, as these are no longer passed for Client Area
$pveservice=Capsule::table('tblhosting')->find($params['serviceid']) ;
$pveserver=Capsule::table('tblservers')->where('id','=',$pveservice->server)->get()[0] ;
$serverip = $pveserver->ipaddress;
$serverusername = $pveserver->username;
$api_data = array(
'password2' => $pveserver->password,
);
$serverpassword = localAPI('DecryptPassword', $api_data);
$proxmox=new PVE2_API($serverip, $serverusername, "pam", $serverpassword['password']);
if ($proxmox->login()) {
# Get first node name.
$nodes = $proxmox->get_node_list();
$first_node = $nodes[0];
unset($nodes);
$guest=Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
$pve_cmdparam = array();
// $pve_cmdparam['timeout'] = '60';
if ($proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/reboot' , $pve_cmdparam))
return true ;
}
return false;
}
function pvewhmcs_vmShutdown($params) {
// Gather access credentials for PVE, as these are no longer passed for Client Area
$pveservice=Capsule::table('tblhosting')->find($params['serviceid']) ;
@@ -806,14 +844,13 @@ function pvewhmcs_vmShutdown($params) {
$serverpassword = localAPI('DecryptPassword', $api_data);
$proxmox=new PVE2_API($serverip, $serverusername, "pam", $serverpassword['password']);
if ($proxmox->login()) {
//$proxmox->setCookie();
# Get first node name.
$nodes = $proxmox->get_node_list();
$first_node = $nodes[0];
unset($nodes);
$guest=Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
$pve_cmdparam = array();
$pve_cmdparam['timeout'] = '60';
// $pve_cmdparam['timeout'] = '60';
if ($proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/shutdown' , $pve_cmdparam))
return true ;
@@ -835,14 +872,13 @@ function pvewhmcs_vmStop($params) {
$serverpassword = localAPI('DecryptPassword', $api_data);
$proxmox=new PVE2_API($serverip, $serverusername, "pam", $serverpassword['password']);
if ($proxmox->login()) {
//$proxmox->setCookie();
# Get first node name.
$nodes = $proxmox->get_node_list();
$first_node = $nodes[0];
unset($nodes);
$guest=Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
$pve_cmdparam = array();
$pve_cmdparam['timeout'] = '60';
// $pve_cmdparam['timeout'] = '60';
if ($proxmox->post('/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/status/stop' , $pve_cmdparam))
return true ;
@@ -899,4 +935,4 @@ function time2format($s) {
}
return $str;
}
?>
?>