ChangePackage.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <?php
  2. /**********************************************************************
  3. * ProxmoxVPS developed. (26.03.19)
  4. * *
  5. *
  6. * CREATED BY MODULESGARDEN -> http://modulesgarden.com
  7. * CONTACT -> contact@modulesgarden.com
  8. *
  9. *
  10. * This software is furnished under a license and may be used and copied
  11. * only in accordance with the terms of such license and with the
  12. * inclusion of the above copyright notice. This software or any other
  13. * copies thereof may not be provided or otherwise made available to any
  14. * other person. No title to and ownership of the software is hereby
  15. * transferred.
  16. *
  17. *
  18. **********************************************************************/
  19. namespace ModulesGarden\Servers\ProxmoxVps\App\Http\Actions;
  20. use Illuminate\Database\Capsule\Manager as DB;
  21. use ModulesGarden\ProxmoxAddon\App\Events\Vps\LxcUpdateEvent;
  22. use ModulesGarden\ProxmoxAddon\App\Events\Vps\QemuUpdateEvent;
  23. use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\Agent\ConfigureNetworkJob;
  24. use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\LoadBalancer as LoadBalancer;
  25. use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\RebootVmJob;
  26. use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\Reinstall\BackupVmJob;
  27. use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\Reinstall\CreateVmJob;
  28. use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\Reinstall\DeleteVmJob;
  29. use ModulesGarden\ProxmoxAddon\App\Libs\Format;
  30. use ModulesGarden\ProxmoxAddon\App\Models\Job;
  31. use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\ToDoList;
  32. use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Upgrade;
  33. use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
  34. use ModulesGarden\ProxmoxAddon\App\Services\EmailService;
  35. use ModulesGarden\ProxmoxAddon\App\Services\LoadBalancerService;
  36. use ModulesGarden\ProxmoxAddon\App\Services\Utility;
  37. use ModulesGarden\ProxmoxAddon\App\Services\Vps\HostingService;
  38. use ModulesGarden\ProxmoxAddon\App\Services\Vps\IpSetIpFilterService;
  39. use ModulesGarden\ProxmoxAddon\App\Services\Vps\NetworkService;
  40. use ModulesGarden\ProxmoxAddon\App\Services\Vps\ProductService;
  41. use ModulesGarden\ProxmoxAddon\App\Services\Vps\UserService;
  42. use ModulesGarden\Servers\ProxmoxVps\App\Helpers\AppParams;
  43. use ModulesGarden\Servers\ProxmoxVps\App\Helpers\ProxmoxAddonValidator;
  44. use ModulesGarden\Servers\ProxmoxVps\Core\App\Controllers\Instances\AddonController;
  45. use ModulesGarden\Servers\ProxmoxVps\Core\UI\Traits\WhmcsParams;
  46. use function ModulesGarden\ProxmoxAddon\Core\Helper\fire;
  47. use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
  48. use function ModulesGarden\ProxmoxAddon\Core\Helper\sl;
  49. use ModulesGarden\Servers\ProxmoxVps\App\Enum\ConfigurableOption;
  50. class ChangePackage extends AddonController
  51. {
  52. use WhmcsParams;
  53. use ApiService;
  54. use ProductService;
  55. use UserService;
  56. use HostingService;
  57. /**
  58. * @var NetworkService
  59. */
  60. private $networkService;
  61. /**
  62. * @var IpSetIpFilterService
  63. */
  64. private $ipSetIpFilterService;
  65. /**
  66. * @var EmailService
  67. */
  68. private $emailService;
  69. /**
  70. * ChangePackage constructor.
  71. * @param $networkService
  72. */
  73. public function __construct()
  74. {
  75. $this->networkService = new NetworkService();
  76. $this->ipSetIpFilterService = new IpSetIpFilterService();
  77. $this->emailService = new EmailService();
  78. }
  79. public function execute($params = null)
  80. {
  81. if(!ProxmoxAddonValidator::isInstalled()){
  82. return ProxmoxAddonValidator::failAsString();
  83. }
  84. (new AppParams())->initFromWhmcsParams();
  85. try
  86. {
  87. $this->manuallyUpgrade();
  88. //Disk
  89. $this->diskSizeValidation();
  90. $this->createReinstallJob();
  91. //Add IP Addresses
  92. if (!Utility::isIpManagerProxmoxVPSIntegration())
  93. {
  94. list($requestIPv4, $requestIPv6) = $this->networkService->getIpAddressesRequest();
  95. $this->networkService->hasIp($requestIPv4, $requestIPv6, $this->vm()->getNode())
  96. ->addIp($requestIPv4, $requestIPv6, $this->vm()->getNode());
  97. }
  98. //Unassing ip addresses and delete network
  99. if(!Utility::isIpManagerProxmoxVPSIntegration())
  100. {
  101. $this->networkService->unassignIpAddressesAndDeleteNetwork();
  102. }
  103. //Load Balancer
  104. if (!Job::waiting()->ofHostingId($this->getWhmcsParamByKey("serviceid"))->ofJob(LoadBalancer\UpgradeVmJob::class)->count() && $this->configuration()->isLoadBalancer() && in_array($this->configuration()->getLoadBalancerOnUpgrade(), ["block", "migrate"]))
  105. {
  106. $loadBalancer = new LoadBalancerService($this->getWhmcsParamByKey('serverid'));
  107. $loadBalancer->setApi($this->api());
  108. //Disk
  109. $disk = $this->configuration()->getDiskSize();
  110. Utility::unitFormat($disk, "gb", 'bytes');
  111. if ($this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE))
  112. {
  113. $disk = $this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE);
  114. Utility::unitFormat($disk, $this->configuration()->getDiskUnit(), 'bytes');
  115. }
  116. //RAM
  117. $ram = $this->configuration()->getMemory();
  118. Utility::unitFormat($ram, "mb", 'bytes');
  119. if ($this->getWhmcsConfigOption(ConfigurableOption::MEMORY))
  120. {
  121. $ram = $this->getWhmcsConfigOption(ConfigurableOption::MEMORY);
  122. Utility::unitFormat($ram, $this->configuration()->getMemoryUnit(), 'bytes');
  123. }
  124. if ($this->configuration()->isQemu())
  125. {
  126. $socket = $this->getWhmcsConfigOption(ConfigurableOption::SOCKETS,$this->configuration()->getSockets() );
  127. $cores = $this->getWhmcsConfigOption(ConfigurableOption::CORES_PER_SOCKET, $this->configuration()->getCores()) ;
  128. $cpu = $socket * $cores;
  129. }
  130. else if ($this->configuration()->isLxc())
  131. {
  132. $cpu = $this->getWhmcsConfigOption(ConfigurableOption::CORES, $this->configuration()->getCores()) ;
  133. }
  134. $loadBalancer->setExcludeVmid($this->vm()->getVmid());
  135. //Upgrade on current node
  136. if ($this->configuration()->getLoadBalancerOnUpgrade() == "block")
  137. {
  138. $loadBalancerNodes = $loadBalancer->findByNode($this->vm()->getNode());
  139. $loadBalancerNodes = $loadBalancerNodes->findByRam($ram)
  140. ->findByCpu($cpu)
  141. ->findByDisk($disk);
  142. if ($loadBalancerNodes->isEmpty())
  143. {
  144. throw new \Exception("Load Balancer: Cannot find free resources on node: " . $this->vm()->getNode());
  145. }
  146. }
  147. else
  148. {
  149. if ($this->configuration()->getLoadBalancerOnUpgrade() == "migrate")
  150. { //Allow to upgrade process, after previous migration vm to the server with free space.
  151. $loadBalancerNodes = $loadBalancer->findByNode($this->vm()->getNode());
  152. $loadBalancerNodes = $loadBalancerNodes->findByRam($ram)
  153. ->findByCpu($cpu)
  154. ->findByDisk($disk);
  155. if ($loadBalancerNodes->isEmpty())
  156. {
  157. $loadBalancerNodes = $loadBalancer->findByVmCreate();
  158. $nodesForUser = $loadBalancer->findNotUser($this->getWhmcsParamByKey('userid'));
  159. if (!$nodesForUser->isEmpty())
  160. {
  161. $loadBalancerNodes = $nodesForUser;
  162. }
  163. $targetNode = $loadBalancerNodes->findByRam($ram)
  164. ->findByCpu($cpu)
  165. ->findByDisk($disk)
  166. ->findByVms(1)
  167. ->nodeLowLoad();
  168. if ($this->configuration()->isLoadBalancerShutdownOnUpgrade())
  169. {
  170. $job = queue(LoadBalancer\ShutdownVmJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid'), "targetNode" => $targetNode], null, "hosting", $this->getWhmcsParamByKey("serviceid"));
  171. }
  172. $job = queue(LoadBalancer\MigrateVmJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid'), "targetNode" => $targetNode], $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
  173. queue(LoadBalancer\UpgradeVmJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid'), "targetNode" => $targetNode], $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
  174. return true;
  175. }
  176. }
  177. }
  178. }
  179. if ($this->configuration()->isQemu())
  180. {
  181. $evnet = new QemuUpdateEvent($this->vm());
  182. $evnet->setChangeVmPassword(false);
  183. fire($evnet);
  184. }
  185. elseif ($this->configuration()->isLxc())
  186. {
  187. fire(new LxcUpdateEvent($this->vm()));
  188. }
  189. //hosting limit
  190. $this->saveUsageLimit();
  191. //reboot
  192. if ($this->configuration()->isRebootVmAfterChangePackage() &&
  193. $this->vm()->isRunning() &&
  194. !Job::waiting()->ofJob(RebootVmJob::class)->ofHostingId($this->getWhmcsParamByKey("serviceid"))->count())
  195. {
  196. $parentId = queue(RebootVmJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid')], null, "hosting", $this->getWhmcsParamByKey("serviceid"));
  197. }
  198. if($this->configuration()->isAgentConfigureNetwork()){
  199. $parentId = queue(ConfigureNetworkJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid')], $parentId, "hosting", $this->getWhmcsParamByKey("serviceid"));
  200. }
  201. //IP Filter
  202. if ($this->configuration()->isIpsetIpFilter())
  203. {
  204. $this->ipSetIpFilterService->create();
  205. }
  206. return "success";
  207. }
  208. catch (\Exception $ex)
  209. {
  210. return $ex->getMessage();
  211. }
  212. }
  213. private function manuallyUpgrade()
  214. {
  215. $scriptFile = substr($_SERVER['SCRIPT_NAME'], strrpos($_SERVER['SCRIPT_NAME'], DIRECTORY_SEPARATOR) + 1);
  216. if (!$this->configuration()->getUpgradeNotificationTemplateId() || $scriptFile == "clientsservices.php")
  217. {
  218. return;
  219. }
  220. if ($this->configuration()->isToDoList())
  221. {
  222. $title = sprintf('Manually Upgrade - Service ID: %s', $this->getWhmcsParamByKey('serviceid'));
  223. if (!ToDoList::ofTitle($title)->pending()->count())
  224. {
  225. $entity = new ToDoList();
  226. $entity->fill(
  227. [
  228. 'date' => date("Y-m-d H:i:s"),
  229. "duedate" => date("Y-m-d H:i:s"),
  230. 'title' => $title,
  231. "status" => "Pending",
  232. "description" => "An upgrade order has received its payment, automatic upgrades has been disabled and requires manually processing.",
  233. "admin" => 0,
  234. ]
  235. );
  236. $entity->save();
  237. }
  238. }
  239. //Send Admin notification
  240. $this->emailService->template($this->configuration()->getUpgradeNotificationTemplateId());
  241. global $customadminpath;
  242. $adminDir = $customadminpath ? $customadminpath : "admin";
  243. $adminAreaLink = $GLOBALS['CONFIG']['SystemURL'] . "/{$adminDir}";
  244. $hosting = $GLOBALS['CONFIG']['SystemURL'] . "/{$adminDir}/clientsservices.php?id=" . $this->getWhmcsParamByKey('serviceid');
  245. $emailVars = [
  246. "client_id" => $this->getWhmcsParamByKey('clientsdetails')['id'],
  247. "service_id" => $this->getWhmcsParamByKey('serviceid'),
  248. "service_product" => "<a href='{$hosting}/'>{$hosting}</a>",
  249. "service_domain" => $this->getWhmcsParamByKey('domain'),
  250. "whmcs_admin_link" => "<a href='{$adminAreaLink}/'>{$adminAreaLink}</a>",
  251. ];
  252. $this->emailService->vars($emailVars)->sendToAdmin();
  253. throw new \Exception("Automaticall upgrade has been disabled by admin");
  254. }
  255. private function createReinstallJob()
  256. {
  257. if (!$this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE))
  258. {
  259. return;
  260. }
  261. if (!Upgrade::ofHostingId($this->getWhmcsParamByKey('serviceid'))->pending()->today()->count())
  262. {
  263. return;
  264. }
  265. $pg = "tblproductconfiggroups";
  266. $pl = "tblproductconfiglinks";
  267. $po = "tblproductconfigoptions";
  268. $optionId = DB::table($po)
  269. ->select("{$po}.id")
  270. ->leftJoin($pg, "{$pg}.id", "=", "{$po}.gid")
  271. ->leftJoin($pl, "{$pl}.gid", "=", "{$pg}.id")
  272. ->where("{$pl}.pid", $this->getWhmcsParamByKey("pid"))
  273. ->where("{$po}.optionname", "like", "VM Template|%")
  274. ->value("id");
  275. if (!$optionId)
  276. {
  277. return;
  278. }
  279. if (!Upgrade::ofHostingId($this->getWhmcsParamByKey('serviceid'))->pending()->today()->ofOptionId($optionId)->count())
  280. {
  281. return;
  282. }
  283. if ($this->configuration()->isQemu())
  284. {
  285. if ($this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE)=== "0")
  286. {
  287. return;
  288. }
  289. }
  290. $arguments = [
  291. 'hostingId' => $this->getWhmcsParamByKey('serviceid'),
  292. "osTemplate" => $this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE),
  293. "password" => encrypt($this->getWhmcsParamByKey("password"))
  294. ];
  295. if ($this->configuration()->isBackupVmBeforeReinstall())
  296. {
  297. $job = queue(BackupVmJob::class, $arguments, null, "hosting", $this->getWhmcsParamByKey("serviceid"));
  298. }
  299. $job = queue(DeleteVmJob::class, $arguments, $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
  300. $job = queue(CreateVmJob::class, $arguments, $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
  301. }
  302. protected function diskSizeValidation(){
  303. $diskSize = $this->configuration()->getDiskSize();
  304. if ($this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE))
  305. {
  306. $diskSize = $this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE);
  307. Utility::unitFormat($diskSize, $this->configuration()->getDiskUnit(), 'bytes');
  308. }else{
  309. Utility::unitFormat($diskSize, "gb", 'bytes');
  310. }
  311. $masterHddSize = $this->vm()->getMasterHddSize();
  312. Utility::unitFormat($masterHddSize, "gb", 'bytes');
  313. if ($diskSize < $masterHddSize)
  314. {
  315. throw new \Exception(sprintf('Downgrading disk size is restricted. Request Disk size: %s, VM disk size: %s',
  316. Format::convertBytes($diskSize), Format::convertBytes($masterHddSize)));
  317. }
  318. }
  319. }