ChangePackage.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  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. logModuleCall(
  119. 'proxmoxVPS',
  120. __FUNCTION__,
  121. $ram,
  122. 'Debug 1',
  123. $this->get_object_vars()
  124. );
  125. Utility::unitFormat($ram, "mb", 'bytes');
  126. if ($this->getWhmcsConfigOption(ConfigurableOption::MEMORY))
  127. {
  128. $ram = $this->getWhmcsConfigOption(ConfigurableOption::MEMORY);
  129. logModuleCall(
  130. 'proxmoxVPS',
  131. __FUNCTION__,
  132. $ram,
  133. 'Debug 2',
  134. $this->get_object_vars()
  135. );
  136. Utility::unitFormat($ram, $this->configuration()->getMemoryUnit(), 'bytes');
  137. logModuleCall(
  138. 'proxmoxVPS',
  139. __FUNCTION__,
  140. $ram,
  141. 'Debug 3',
  142. $this->get_object_vars()
  143. );
  144. }
  145. if ($this->configuration()->isQemu())
  146. {
  147. $socket = $this->getWhmcsConfigOption(ConfigurableOption::SOCKETS,$this->configuration()->getSockets() );
  148. $cores = $this->getWhmcsConfigOption(ConfigurableOption::CORES_PER_SOCKET, $this->configuration()->getCores()) ;
  149. $cpu = $socket * $cores;
  150. }
  151. else if ($this->configuration()->isLxc())
  152. {
  153. $cpu = $this->getWhmcsConfigOption(ConfigurableOption::CORES, $this->configuration()->getCores()) ;
  154. }
  155. $loadBalancer->setExcludeVmid($this->vm()->getVmid());
  156. //Upgrade on current node
  157. if ($this->configuration()->getLoadBalancerOnUpgrade() == "block")
  158. {
  159. $loadBalancerNodes = $loadBalancer->findByNode($this->vm()->getNode());
  160. $loadBalancerNodes = $loadBalancerNodes->findByRam($ram)
  161. ->findByCpu($cpu)
  162. ->findByDisk($disk);
  163. if ($loadBalancerNodes->isEmpty())
  164. {
  165. throw new \Exception("Load Balancer: Cannot find free resources on node: " . $this->vm()->getNode());
  166. }
  167. }
  168. else
  169. {
  170. if ($this->configuration()->getLoadBalancerOnUpgrade() == "migrate")
  171. { //Allow to upgrade process, after previous migration vm to the server with free space.
  172. $loadBalancerNodes = $loadBalancer->findByNode($this->vm()->getNode());
  173. $loadBalancerNodes = $loadBalancerNodes->findByRam($ram)
  174. ->findByCpu($cpu)
  175. ->findByDisk($disk);
  176. if ($loadBalancerNodes->isEmpty())
  177. {
  178. $loadBalancerNodes = $loadBalancer->findByVmCreate();
  179. $nodesForUser = $loadBalancer->findNotUser($this->getWhmcsParamByKey('userid'));
  180. if (!$nodesForUser->isEmpty())
  181. {
  182. $loadBalancerNodes = $nodesForUser;
  183. }
  184. $targetNode = $loadBalancerNodes->findByRam($ram)
  185. ->findByCpu($cpu)
  186. ->findByDisk($disk)
  187. ->findByVms(1)
  188. ->nodeLowLoad();
  189. if ($this->configuration()->isLoadBalancerShutdownOnUpgrade())
  190. {
  191. $job = queue(LoadBalancer\ShutdownVmJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid'), "targetNode" => $targetNode], null, "hosting", $this->getWhmcsParamByKey("serviceid"));
  192. }
  193. $job = queue(LoadBalancer\MigrateVmJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid'), "targetNode" => $targetNode], $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
  194. queue(LoadBalancer\UpgradeVmJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid'), "targetNode" => $targetNode], $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
  195. return true;
  196. }
  197. }
  198. }
  199. }
  200. if ($this->configuration()->isQemu())
  201. {
  202. $evnet = new QemuUpdateEvent($this->vm());
  203. $evnet->setChangeVmPassword(false);
  204. fire($evnet);
  205. }
  206. elseif ($this->configuration()->isLxc())
  207. {
  208. fire(new LxcUpdateEvent($this->vm()));
  209. }
  210. //hosting limit
  211. $this->saveUsageLimit();
  212. //reboot
  213. if ($this->configuration()->isRebootVmAfterChangePackage() &&
  214. $this->vm()->isRunning() &&
  215. !Job::waiting()->ofJob(RebootVmJob::class)->ofHostingId($this->getWhmcsParamByKey("serviceid"))->count())
  216. {
  217. $parentId = queue(RebootVmJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid')], null, "hosting", $this->getWhmcsParamByKey("serviceid"));
  218. }
  219. if($this->configuration()->isAgentConfigureNetwork()){
  220. $parentId = queue(ConfigureNetworkJob::class, ['hostingId' => $this->getWhmcsParamByKey('serviceid')], $parentId, "hosting", $this->getWhmcsParamByKey("serviceid"));
  221. }
  222. //IP Filter
  223. if ($this->configuration()->isIpsetIpFilter())
  224. {
  225. $this->ipSetIpFilterService->create();
  226. }
  227. return "success";
  228. }
  229. catch (\Exception $ex)
  230. {
  231. return $ex->getMessage();
  232. }
  233. }
  234. private function manuallyUpgrade()
  235. {
  236. $scriptFile = substr($_SERVER['SCRIPT_NAME'], strrpos($_SERVER['SCRIPT_NAME'], DIRECTORY_SEPARATOR) + 1);
  237. if (!$this->configuration()->getUpgradeNotificationTemplateId() || $scriptFile == "clientsservices.php")
  238. {
  239. return;
  240. }
  241. if ($this->configuration()->isToDoList())
  242. {
  243. $title = sprintf('Manually Upgrade - Service ID: %s', $this->getWhmcsParamByKey('serviceid'));
  244. if (!ToDoList::ofTitle($title)->pending()->count())
  245. {
  246. $entity = new ToDoList();
  247. $entity->fill(
  248. [
  249. 'date' => date("Y-m-d H:i:s"),
  250. "duedate" => date("Y-m-d H:i:s"),
  251. 'title' => $title,
  252. "status" => "Pending",
  253. "description" => "An upgrade order has received its payment, automatic upgrades has been disabled and requires manually processing.",
  254. "admin" => 0,
  255. ]
  256. );
  257. $entity->save();
  258. }
  259. }
  260. //Send Admin notification
  261. $this->emailService->template($this->configuration()->getUpgradeNotificationTemplateId());
  262. global $customadminpath;
  263. $adminDir = $customadminpath ? $customadminpath : "admin";
  264. $adminAreaLink = $GLOBALS['CONFIG']['SystemURL'] . "/{$adminDir}";
  265. $hosting = $GLOBALS['CONFIG']['SystemURL'] . "/{$adminDir}/clientsservices.php?id=" . $this->getWhmcsParamByKey('serviceid');
  266. $emailVars = [
  267. "client_id" => $this->getWhmcsParamByKey('clientsdetails')['id'],
  268. "service_id" => $this->getWhmcsParamByKey('serviceid'),
  269. "service_product" => "<a href='{$hosting}/'>{$hosting}</a>",
  270. "service_domain" => $this->getWhmcsParamByKey('domain'),
  271. "whmcs_admin_link" => "<a href='{$adminAreaLink}/'>{$adminAreaLink}</a>",
  272. ];
  273. $this->emailService->vars($emailVars)->sendToAdmin();
  274. throw new \Exception("Automaticall upgrade has been disabled by admin");
  275. }
  276. private function createReinstallJob()
  277. {
  278. if (!$this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE))
  279. {
  280. return;
  281. }
  282. if (!Upgrade::ofHostingId($this->getWhmcsParamByKey('serviceid'))->pending()->today()->count())
  283. {
  284. return;
  285. }
  286. $pg = "tblproductconfiggroups";
  287. $pl = "tblproductconfiglinks";
  288. $po = "tblproductconfigoptions";
  289. $optionId = DB::table($po)
  290. ->select("{$po}.id")
  291. ->leftJoin($pg, "{$pg}.id", "=", "{$po}.gid")
  292. ->leftJoin($pl, "{$pl}.gid", "=", "{$pg}.id")
  293. ->where("{$pl}.pid", $this->getWhmcsParamByKey("pid"))
  294. ->where("{$po}.optionname", "like", "VM Template|%")
  295. ->value("id");
  296. if (!$optionId)
  297. {
  298. return;
  299. }
  300. if (!Upgrade::ofHostingId($this->getWhmcsParamByKey('serviceid'))->pending()->today()->ofOptionId($optionId)->count())
  301. {
  302. return;
  303. }
  304. if ($this->configuration()->isQemu())
  305. {
  306. if ($this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE)=== "0")
  307. {
  308. return;
  309. }
  310. }
  311. $arguments = [
  312. 'hostingId' => $this->getWhmcsParamByKey('serviceid'),
  313. "osTemplate" => $this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE),
  314. "password" => encrypt($this->getWhmcsParamByKey("password"))
  315. ];
  316. if ($this->configuration()->isBackupVmBeforeReinstall())
  317. {
  318. $job = queue(BackupVmJob::class, $arguments, null, "hosting", $this->getWhmcsParamByKey("serviceid"));
  319. }
  320. $job = queue(DeleteVmJob::class, $arguments, $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
  321. $job = queue(CreateVmJob::class, $arguments, $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
  322. }
  323. protected function diskSizeValidation(){
  324. $diskSize = $this->configuration()->getDiskSize();
  325. if ($this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE))
  326. {
  327. $diskSize = $this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE);
  328. Utility::unitFormat($diskSize, $this->configuration()->getDiskUnit(), 'bytes');
  329. }else{
  330. Utility::unitFormat($diskSize, "gb", 'bytes');
  331. }
  332. $masterHddSize = $this->vm()->getMasterHddSize();
  333. Utility::unitFormat($masterHddSize, "gb", 'bytes');
  334. if ($diskSize < $masterHddSize)
  335. {
  336. throw new \Exception(sprintf('Downgrading disk size is restricted. Request Disk size: %s, VM disk size: %s',
  337. Format::convertBytes($diskSize), Format::convertBytes($masterHddSize)));
  338. }
  339. }
  340. }