CreateVmJob.php 9.6 KB

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