CreateVmJob.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. namespace ModulesGarden\ProxmoxAddon\App\Jobs\Vps\Reinstall;
  3. use MGProvision\Proxmox\v2\models\Kvm;
  4. use MGProvision\Proxmox\v2\models\Node;
  5. use MGProvision\Proxmox\v2\ProxmoxApiException;
  6. use MGProvision\Proxmox\v2\repository\ClusterResourcesRepository;
  7. use MGProvision\Proxmox\v2\repository\FileRepository;
  8. use ModulesGarden\ProxmoxAddon\App\Events\Vps\LxcUpdateEvent;
  9. use ModulesGarden\ProxmoxAddon\App\Events\Vps\QemuUpdateEvent;
  10. use ModulesGarden\ProxmoxAddon\App\Events\Vps\VmReinstalledEvent;
  11. use ModulesGarden\ProxmoxAddon\App\Jobs\Vps\BaseJob;
  12. use ModulesGarden\ProxmoxAddon\App\Models\Job;
  13. use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
  14. use ModulesGarden\ProxmoxAddon\App\Services\Vps\AgentService;
  15. use ModulesGarden\ProxmoxAddon\App\Services\Vps\ContainerService;
  16. use ModulesGarden\ProxmoxAddon\App\Services\Vps\HighAvailabilityClusterService;
  17. use ModulesGarden\ProxmoxAddon\App\Services\Vps\HostingService;
  18. use ModulesGarden\ProxmoxAddon\App\Services\Vps\ProductService;
  19. use function ModulesGarden\ProxmoxAddon\Core\Helper\fire;
  20. use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
  21. use function ModulesGarden\ProxmoxAddon\Core\Helper\sl;
  22. class CreateVmJob extends BaseJob
  23. {
  24. use ProductService;
  25. use HostingService;
  26. /**
  27. * @var HighAvailabilityClusterService
  28. */
  29. protected $highAvailabilityClusterService;
  30. protected function initServices()
  31. {
  32. $this->highAvailabilityClusterService = new HighAvailabilityClusterService();
  33. $this->containerService = new ContainerService();
  34. $this->agentService = new AgentService();
  35. }
  36. public function handle($text = null)
  37. {
  38. $this->initParams();
  39. $this->initServices();
  40. //is done
  41. if ($this->isTask() && $this->getTask()->isDone()) {
  42. //update password
  43. if ($this->getModelData()['password'] ) {
  44. if($this->params['customfields']['cipassword']){
  45. $this->customFieldUpdate('cipassword', $this->getModelData()['password']);
  46. $this->params['customfields']['cipassword'] = decrypt($this->getModelData()['password']);
  47. }else{
  48. $this->hosting()->update(["password" => $this->getModelData()['password']]);
  49. $this->params['password'] = decrypt($this->getModelData()['password']);
  50. }
  51. sl("whmcsParams")->setParams($this->params);
  52. \ModulesGarden\Servers\ProxmoxVps\Core\Helper\sl("whmcsParams")->setParams($this->params);
  53. }
  54. //reinstalled event
  55. if ($this->configuration()->isLxc()) {
  56. fire(new LxcUpdateEvent($this->vm()));
  57. } elseif ($this->configuration()->isQemu()) {
  58. //Reset IP addresses usage
  59. VmIpAddress::ofHostingId($this->getWhmcsParamByKey("serviceid"))
  60. ->update([
  61. 'net' => null
  62. ]);
  63. $this->deleteNetwork();
  64. if(!$this->vm()->isRunning()){
  65. $this->deleteNetwork();
  66. }
  67. fire(new QemuUpdateEvent($this->vm()));
  68. //Agent
  69. try{
  70. if($this->agentService->isEnabled()){
  71. if(!$this->vm()->isRunning()){
  72. $this->log->info(sprintf("VM %s - Start", $this->vm()->getVmid()));
  73. $this->vm()->start();
  74. $this->sleep(40);
  75. return false;
  76. }
  77. $this->vm()->agent()->ping();
  78. $this->agentService ->getUserAndUpdate();
  79. $this->agentService ->passwordUpdate();
  80. $this->agentService ->configureNetwork();
  81. }
  82. }catch (ProxmoxApiException $ex){
  83. if(preg_match("/not running/", $ex->getMessage())){
  84. $this->log->info($ex->getMessage());
  85. }else{
  86. $this->log->error($ex->getMessage());
  87. }
  88. //sleep
  89. $this->sleep(30);
  90. return false;
  91. }
  92. }
  93. fire(new VmReinstalledEvent($this->vm()));
  94. return true;
  95. } else if ($this->isTask() && $this->getTask()->isRunning()) {
  96. $this->sleep(20);
  97. return false;
  98. } else if ($this->isTask() && $this->getTask()->isFalied()) {
  99. if ($this->configuration()->isBackupVmBeforeReinstall()) {
  100. $this->log->error($this->getTask()->getExitstatus());
  101. $this->restoreJob();
  102. $this->model->setStatus(Job::STATUS_FAILED);
  103. return;
  104. }
  105. throw new \Exception($this->getTask()->getExitstatus());
  106. } //create vm
  107. else if (!$this->isTask() && $this->configuration()->isLxc()) {
  108. try {
  109. $container = $this->getParentModelData()['container'];
  110. unset($container['lxc'], $container['parent']);
  111. //pool
  112. if ($this->configuration()->getPool())
  113. {
  114. $container['pool'] = $this->configuration()->getPool();
  115. }
  116. $node = new Node($this->vm()->getNode());
  117. $node->setApi($this->api());
  118. $taskId = $node->lxc()->create($container);
  119. //save task id
  120. $this->putModelDataAndSave(["taskId" => $taskId, "node" => $this->vm()->getNode()]);
  121. //task history
  122. $this->createTaskHistory($taskId, "Create");
  123. } catch (\Exception $ex) {
  124. $this->log->error($ex->getMessage());
  125. $this->restoreJob();
  126. return false;
  127. }
  128. //clone vm
  129. } else if (!$this->isTask() && $this->configuration()->isQemu()) {
  130. try {
  131. $osTemplate = $this->getModelData()['osTemplate'];
  132. //Support for configurable options i.e vmname|OS Name
  133. if (is_string($osTemplate) && !preg_match('/\//', $osTemplate)) {
  134. $templateNode = $this->vm()->getNode();
  135. $clusterRepository = new ClusterResourcesRepository();
  136. $clusterRepository->setApi($this->api());
  137. $clusterRepository->findByNodes([$templateNode])
  138. ->findKvmTemplate();
  139. foreach ($clusterRepository->fetch() as $resurce) {
  140. if ($resurce->getName() == $osTemplate && $templateNode == $resurce->getNode()) {
  141. $templateVmid = $resurce->getVmid();
  142. break;
  143. }
  144. }
  145. if (!$templateVmid) {
  146. throw new \Exception(sprintf("Unable to find KVM template: %s on node: %s", $osTemplate, $templateNode));
  147. }
  148. //Support for configurable options like nodename/vmid|OS Name
  149. } elseif (preg_match('/\//', $osTemplate)) {
  150. list($templateNode, $templateVmid) = explode("/", $osTemplate);
  151. }
  152. //init container
  153. $container = [
  154. "newid" => $this->vm()->getVmid(),
  155. "full" => $this->configuration()->getCloneMode(),
  156. "target" => $this->vm()->getNode()
  157. ];
  158. //description
  159. if ($this->configuration()->getDescription()) {
  160. $container['description'] = $this->containerService->description();
  161. }
  162. //hostname
  163. $hostname = $this->containerService->hostname();
  164. if ($hostname) {
  165. $container['name'] = $hostname;
  166. }
  167. //Storage
  168. if (!$this->configuration()->isCloneOnTheSameStorage() && $this->configuration()->getDiskStorage() && $this->configuration()->getCloneMode() == "1") {
  169. $container['storage'] = $this->configuration()->getDiskStorage();
  170. }
  171. //pool
  172. if ($this->configuration()->getPool()) {
  173. $container['pool'] = $this->configuration()->getPool();
  174. }
  175. //Create
  176. $template = new Kvm($templateNode, $templateVmid);
  177. $template->setApi($this->api());
  178. $taskId = $template->cloneVm($container);
  179. //save task id
  180. $this->putModelDataAndSave(["taskId" => $taskId, "node" => $this->vm()->getNode(), "templateNode" => $templateNode]);
  181. //task history
  182. $this->createTaskHistory($taskId, "Create");
  183. } catch (\Exception $ex) {
  184. if ($this->configuration()->isBackupVmBeforeReinstall()) {
  185. $this->log->error($ex->getMessage());
  186. $this->restoreJob();
  187. $this->model->setStatus(Job::STATUS_FAILED);
  188. return;
  189. }
  190. throw $ex;
  191. }
  192. }
  193. $this->sleep(20);
  194. return false;
  195. }
  196. private function restoreJob()
  197. {
  198. //create restore job
  199. $storage = $this->configuration()->getBackupStorage() ? $this->configuration()->getBackupStorage() : 'local';
  200. $fileRepository = new FileRepository();
  201. $fileRepository->findBackup($this->vm())
  202. ->findByStorages([$storage]);
  203. if (!$fileRepository->count()) {
  204. return;
  205. }
  206. queue(RestoreVm::class, [], null, "hosting", $this->getWhmcsParamByKey("serviceid"));
  207. $this->model->setStatus(Job::STATUS_CANCELLED)->save();
  208. return false;
  209. }
  210. private function deleteNetwork(){
  211. $deleteNetwork = [];
  212. foreach ($this->vm()->getNetworkDevices() as $networkDevice){
  213. if(VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))->ofNet($networkDevice->getId())->count()){
  214. continue;
  215. }
  216. $deleteNetwork[]=$networkDevice->getId();
  217. }
  218. if(!empty($deleteNetwork)){
  219. $this->vm()->deleteConfig(implode(",",$deleteNetwork));
  220. }
  221. }
  222. }