http://modulesgarden.com
* CONTACT -> contact@modulesgarden.com
*
*
* This software is furnished under a license and may be used and copied
* only in accordance with the terms of such license and with the
* inclusion of the above copyright notice. This software or any other
* copies thereof may not be provided or otherwise made available to any
* other person. No title to and ownership of the software is hereby
* transferred.
*
*
**********************************************************************/
namespace ModulesGarden\Servers\ProxmoxVps\App\Http\Actions;
use Illuminate\Database\Capsule\Manager as DB;
use ModulesGarden\ProxmoxAddon\App\Events\Vps\LxcUpdateEvent;
use ModulesGarden\ProxmoxAddon\App\Events\Vps\QemuUpdateEvent;
use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\Agent\ConfigureNetworkJob;
use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\LoadBalancer as LoadBalancer;
use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\RebootVmJob;
use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\Reinstall\BackupVmJob;
use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\Reinstall\CreateVmJob;
use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\Reinstall\DeleteVmJob;
use ModulesGarden\ProxmoxAddon\App\Libs\Format;
use ModulesGarden\ProxmoxAddon\App\Models\Job;
use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\ToDoList;
use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Upgrade;
use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
use ModulesGarden\ProxmoxAddon\App\Services\EmailService;
use ModulesGarden\ProxmoxAddon\App\Services\LoadBalancerService;
use ModulesGarden\ProxmoxAddon\App\Services\Utility;
use ModulesGarden\ProxmoxAddon\App\Services\Vps\HostingService;
use ModulesGarden\ProxmoxAddon\App\Services\Vps\IpSetIpFilterService;
use ModulesGarden\ProxmoxAddon\App\Services\Vps\NetworkService;
use ModulesGarden\ProxmoxAddon\App\Services\Vps\ProductService;
use ModulesGarden\ProxmoxAddon\App\Services\Vps\UserService;
use ModulesGarden\Servers\ProxmoxVps\App\Helpers\AppParams;
use ModulesGarden\Servers\ProxmoxVps\App\Helpers\ProxmoxAddonValidator;
use ModulesGarden\Servers\ProxmoxVps\Core\App\Controllers\Instances\AddonController;
use ModulesGarden\Servers\ProxmoxVps\Core\UI\Traits\WhmcsParams;
use function ModulesGarden\ProxmoxAddon\Core\Helper\fire;
use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
use function ModulesGarden\ProxmoxAddon\Core\Helper\sl;
use ModulesGarden\Servers\ProxmoxVps\App\Enum\ConfigurableOption;
class ChangePackage extends AddonController
{
use WhmcsParams;
use ApiService;
use ProductService;
use UserService;
use HostingService;
/**
* @var NetworkService
*/
private $networkService;
/**
* @var IpSetIpFilterService
*/
private $ipSetIpFilterService;
/**
* @var EmailService
*/
private $emailService;
/**
* ChangePackage constructor.
* @param $networkService
*/
public function __construct()
{
$this->networkService = new NetworkService();
$this->ipSetIpFilterService = new IpSetIpFilterService();
$this->emailService = new EmailService();
}
public function execute($params = null)
{
if(!ProxmoxAddonValidator::isInstalled()){
return ProxmoxAddonValidator::failAsString();
}
(new AppParams())->initFromWhmcsParams();
try
{
$this->manuallyUpgrade();
//Disk
$this->diskSizeValidation();
$this->createReinstallJob();
//Add IP Addresses
if (!Utility::isIpManagerProxmoxVPSIntegration())
{
list($requestIPv4, $requestIPv6) = $this->networkService->getIpAddressesRequest();
$this->networkService->hasIp($requestIPv4, $requestIPv6, $this->vm()->getNode())
->addIp($requestIPv4, $requestIPv6, $this->vm()->getNode());
}
//Unassing ip addresses and delete network
if(!Utility::isIpManagerProxmoxVPSIntegration())
{
$this->networkService->unassignIpAddressesAndDeleteNetwork();
}
//Load Balancer
if (!Job::waiting()->ofHostingId($this->getWhmcsParamByKey("serviceid"))->ofJob(LoadBalancer\UpgradeVmJob::class)->count() && $this->configuration()->isLoadBalancer() && in_array($this->configuration()->getLoadBalancerOnUpgrade(), ["block", "migrate"]))
{
$loadBalancer = new LoadBalancerService($this->getWhmcsParamByKey('serverid'));
$loadBalancer->setApi($this->api());
//Disk
$disk = $this->configuration()->getDiskSize();
Utility::unitFormat($disk, "gb", 'bytes');
if ($this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE))
{
$disk = $this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE);
Utility::unitFormat($disk, $this->configuration()->getDiskUnit(), 'bytes');
}
//RAM
$ram = $this->configuration()->getMemory();
Utility::unitFormat($ram, "mb", 'bytes');
if ($this->getWhmcsConfigOption(ConfigurableOption::MEMORY))
{
$ram = $this->getWhmcsConfigOption(ConfigurableOption::MEMORY);
Utility::unitFormat($ram, $this->configuration()->getMemoryUnit(), 'bytes');
}
if ($this->configuration()->isQemu())
{
$socket = $this->getWhmcsConfigOption(ConfigurableOption::SOCKETS,$this->configuration()->getSockets() );
$cores = $this->getWhmcsConfigOption(ConfigurableOption::CORES_PER_SOCKET, $this->configuration()->getCores()) ;
$cpu = $socket * $cores;
}
else if ($this->configuration()->isLxc())
{
$cpu = $this->getWhmcsConfigOption(ConfigurableOption::CORES, $this->configuration()->getCores()) ;
}
$loadBalancer->setExcludeVmid($this->vm()->getVmid());
//Upgrade on current node
if ($this->configuration()->getLoadBalancerOnUpgrade() == "block")
{
$loadBalancerNodes = $loadBalancer->findByNode($this->vm()->getNode());
$loadBalancerNodes = $loadBalancerNodes->findByRam($ram)
->findByCpu($cpu)
->findByDisk($disk);
if ($loadBalancerNodes->isEmpty())
{
throw new \Exception("Load Balancer: Cannot find free resources on node: " . $this->vm()->getNode());
}
}
else
{
if ($this->configuration()->getLoadBalancerOnUpgrade() == "migrate")
{ //Allow to upgrade process, after previous migration vm to the server with free space.
$loadBalancerNodes = $loadBalancer->findByNode($this->vm()->getNode());
$loadBalancerNodes = $loadBalancerNodes->findByRam($ram)
->findByCpu($cpu)
->findByDisk($disk);
if ($loadBalancerNodes->isEmpty())
{
$loadBalancerNodes = $loadBalancer->findByVmCreate();
$nodesForUser = $loadBalancer->findNotUser($this->getWhmcsParamByKey('userid'));
if (!$nodesForUser->isEmpty())
{
$loadBalancerNodes = $nodesForUser;
}
$targetNode = $loadBalancerNodes->findByRam($ram)
->findByCpu($cpu)
->findByDisk($disk)
->findByVms(1)
->nodeLowLoad();
if ($this->configuration()->isLoadBalancerShutdownOnUpgrade())
{
$job = queue(LoadBalancer\ShutdownVmJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid'), "targetNode" => $targetNode], null, "hosting", $this->getWhmcsParamByKey("serviceid"));
}
$job = queue(LoadBalancer\MigrateVmJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid'), "targetNode" => $targetNode], $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
queue(LoadBalancer\UpgradeVmJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid'), "targetNode" => $targetNode], $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
return true;
}
}
}
}
if ($this->configuration()->isQemu())
{
$evnet = new QemuUpdateEvent($this->vm());
$evnet->setChangeVmPassword(false);
fire($evnet);
}
elseif ($this->configuration()->isLxc())
{
fire(new LxcUpdateEvent($this->vm()));
}
//hosting limit
$this->saveUsageLimit();
//reboot
if ($this->configuration()->isRebootVmAfterChangePackage() &&
$this->vm()->isRunning() &&
!Job::waiting()->ofJob(RebootVmJob::class)->ofHostingId($this->getWhmcsParamByKey("serviceid"))->count())
{
$parentId = queue(RebootVmJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid')], null, "hosting", $this->getWhmcsParamByKey("serviceid"));
}
if($this->configuration()->isAgentConfigureNetwork()){
$parentId = queue(ConfigureNetworkJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid')], $parentId, "hosting", $this->getWhmcsParamByKey("serviceid"));
}
//IP Filter
if ($this->configuration()->isIpsetIpFilter())
{
$this->ipSetIpFilterService->create();
}
return "success";
}
catch (\Exception $ex)
{
return $ex->getMessage();
}
}
private function manuallyUpgrade()
{
$scriptFile = substr($_SERVER['SCRIPT_NAME'], strrpos($_SERVER['SCRIPT_NAME'], DIRECTORY_SEPARATOR) + 1);
if (!$this->configuration()->getUpgradeNotificationTemplateId() || $scriptFile == "clientsservices.php")
{
return;
}
if ($this->configuration()->isToDoList())
{
$title = sprintf('Manually Upgrade - Service ID: %s', $this->getWhmcsParamByKey('serviceid'));
if (!ToDoList::ofTitle($title)->pending()->count())
{
$entity = new ToDoList();
$entity->fill(
[
'date' => date("Y-m-d H:i:s"),
"duedate" => date("Y-m-d H:i:s"),
'title' => $title,
"status" => "Pending",
"description" => "An upgrade order has received its payment, automatic upgrades has been disabled and requires manually processing.",
"admin" => 0,
]
);
$entity->save();
}
}
//Send Admin notification
$this->emailService->template($this->configuration()->getUpgradeNotificationTemplateId());
global $customadminpath;
$adminDir = $customadminpath ? $customadminpath : "admin";
$adminAreaLink = $GLOBALS['CONFIG']['SystemURL'] . "/{$adminDir}";
$hosting = $GLOBALS['CONFIG']['SystemURL'] . "/{$adminDir}/clientsservices.php?id=" . $this->getWhmcsParamByKey('serviceid');
$emailVars = [
"client_id" => $this->getWhmcsParamByKey('clientsdetails')['id'],
"service_id" => $this->getWhmcsParamByKey('serviceid'),
"service_product" => "{$hosting}",
"service_domain" => $this->getWhmcsParamByKey('domain'),
"whmcs_admin_link" => "{$adminAreaLink}",
];
$this->emailService->vars($emailVars)->sendToAdmin();
throw new \Exception("Automaticall upgrade has been disabled by admin");
}
private function createReinstallJob()
{
if (!$this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE))
{
return;
}
if (!Upgrade::ofHostingId($this->getWhmcsParamByKey('serviceid'))->pending()->today()->count())
{
return;
}
$pg = "tblproductconfiggroups";
$pl = "tblproductconfiglinks";
$po = "tblproductconfigoptions";
$optionId = DB::table($po)
->select("{$po}.id")
->leftJoin($pg, "{$pg}.id", "=", "{$po}.gid")
->leftJoin($pl, "{$pl}.gid", "=", "{$pg}.id")
->where("{$pl}.pid", $this->getWhmcsParamByKey("pid"))
->where("{$po}.optionname", "like", "VM Template|%")
->value("id");
if (!$optionId)
{
return;
}
if (!Upgrade::ofHostingId($this->getWhmcsParamByKey('serviceid'))->pending()->today()->ofOptionId($optionId)->count())
{
return;
}
if ($this->configuration()->isQemu())
{
if ($this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE)=== "0")
{
return;
}
}
$arguments = [
'hostingId' => $this->getWhmcsParamByKey('serviceid'),
"osTemplate" => $this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE),
"password" => encrypt($this->getWhmcsParamByKey("password"))
];
if ($this->configuration()->isBackupVmBeforeReinstall())
{
$job = queue(BackupVmJob::class, $arguments, null, "hosting", $this->getWhmcsParamByKey("serviceid"));
}
$job = queue(DeleteVmJob::class, $arguments, $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
$job = queue(CreateVmJob::class, $arguments, $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
}
protected function diskSizeValidation(){
$diskSize = $this->configuration()->getDiskSize();
if ($this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE))
{
$diskSize = $this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE);
Utility::unitFormat($diskSize, $this->configuration()->getDiskUnit(), 'bytes');
}else{
Utility::unitFormat($diskSize, "gb", 'bytes');
}
$masterHddSize = $this->vm()->getMasterHddSize();
Utility::unitFormat($masterHddSize, "gb", 'bytes');
if ($diskSize < $masterHddSize)
{
throw new \Exception(sprintf('Downgrading disk size is restricted. Request Disk size: %s, VM disk size: %s',
Format::convertBytes($diskSize), Format::convertBytes($masterHddSize)));
}
}
}