CloneQemuJob.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <?php
  2. namespace ModulesGarden\ProxmoxAddon\App\Jobs\Cloud;
  3. use Illuminate\Database\Capsule\Manager as DB;
  4. use MGProvision\Proxmox\v2\Api;
  5. use MGProvision\Proxmox\v2\models\Kvm;
  6. use MGProvision\Proxmox\v2\models\Lxc;
  7. use MGProvision\Proxmox\v2\ProxmoxApiException;
  8. use ModulesGarden\ProxmoxAddon\App\Events\Cloud\QemuUpdateEvent;
  9. use ModulesGarden\ProxmoxAddon\App\Events\Cloud\VmCreatedEvent;
  10. use ModulesGarden\ProxmoxAddon\App\Jobs\BaseJob;
  11. use ModulesGarden\ProxmoxAddon\App\Models\TaskHistory;
  12. use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
  13. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\AdditionalDiskService;
  14. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\AgentService;
  15. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ContainerService;
  16. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
  17. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
  18. use ModulesGarden\ProxmoxAddon\App\Services\EmailService;
  19. use function ModulesGarden\ProxmoxAddon\Core\Helper\fire;
  20. use function ModulesGarden\ProxmoxAddon\Core\Helper\sl;
  21. class CloneQemuJob extends BaseJob
  22. {
  23. use ProductService;
  24. use UserService;
  25. /**
  26. * @var \ModulesGarden\ProxmoxAddon\App\Services\Cloud\ContainerService
  27. */
  28. protected $containerService;
  29. /**
  30. * @var Kvm|Lxc
  31. */
  32. protected $vm;
  33. /**
  34. * @var AdditionalDiskService
  35. */
  36. protected $additionalDiskService;
  37. protected function initServices()
  38. {
  39. $this->emailService = new EmailService();
  40. $this->containerService = new ContainerService();
  41. $this->agentService = new AgentService();
  42. $this->additionalDiskService = new AdditionalDiskService();
  43. }
  44. public function handle()
  45. {
  46. $this->initParams();
  47. $this->initServices();
  48. //create task validation
  49. if ($this->isDone())
  50. {
  51. $this->initVm();
  52. if(!sl('Vm')->getVm()->isRunning()){
  53. $this->deleteNetwork();
  54. }
  55. if($this->getModelData()['additionalDiskSize1'] && !$this->additionalDiskService->hasDisk()){
  56. $this->additionalDiskService->create($this->getModelData());
  57. }
  58. fire(new QemuUpdateEvent($this->getVmModel(), $this->getModelData()));
  59. try{
  60. if($this->agentService->isEnabled()){
  61. if(!sl('Vm')->getVm()->isRunning()){
  62. $this->log->info(sprintf("VM %s - Start", sl('Vm')->getVm()->getVmid()));
  63. sl('Vm')->getVm()->start();
  64. $this->sleep(5);
  65. return false;
  66. }
  67. sl('Vm')->getVm()->agent()->ping();
  68. $this->agentService ->passwordUpdate();
  69. $this->agentService ->configureNetwork();
  70. }
  71. }catch (ProxmoxApiException $ex){
  72. if(preg_match("/not running/", $ex->getMessage())){
  73. $this->log->info($ex->getMessage());
  74. }else{
  75. $this->log->error($ex->getMessage());
  76. }
  77. //sleep
  78. $this->sleep(5);
  79. return false;
  80. }
  81. fire(new VmCreatedEvent($this->getVmModel()));
  82. return true;
  83. }
  84. elseif ($this->isTaskRunning())
  85. {
  86. //sleep
  87. $this->sleep(5);
  88. return false;
  89. }
  90. try
  91. {
  92. Api::beginTransaction();
  93. DB::beginTransaction();
  94. $osTemplate = $this->getModelData()['osTemplate'];
  95. //Support for configurable options i.e vmname|OS Name
  96. if (preg_match('/\//', $osTemplate))
  97. {
  98. list($templateNode, $templateVmid) = explode("/", $osTemplate);
  99. }
  100. //vmid
  101. $vmid = $this->nextVmid();
  102. $this->getVmModel();
  103. $this->vmModel->vmid = $vmid;
  104. $this->vmModel->save();
  105. //init container
  106. $container = [
  107. "newid" => $vmid,
  108. "full" => $this->configuration()->getCloneMode(),
  109. "target" => $this->vmModel->node
  110. ];
  111. //description
  112. $container['description'] = $this->getModelData()['description'];
  113. //hostname
  114. $container['name'] = $this->getModelData()['name'];
  115. //Storage
  116. if (!$this->configuration()->isCloneOnTheSameStorage() && $this->configuration()->getDiskStorage() && $this->configuration()->getCloneMode() == "1")
  117. {
  118. $container['storage'] = $this->configuration()->getDiskStorage();
  119. }
  120. //pool
  121. if ($this->configuration()->getPool())
  122. {
  123. $container['pool'] = $this->configuration()->getPool();
  124. }
  125. //bwlimit
  126. if($this->configuration()->getBwLimit()){
  127. $container['bwlimit'] = $this->configuration()->getBwLimit();
  128. }
  129. //Create
  130. $template = new Kvm($templateNode, $templateVmid);
  131. $template->setApi($this->api());
  132. $taskId = $template->cloneVm($container);
  133. DB::commit();
  134. }
  135. catch (\Exception $ex)
  136. {
  137. DB::rollBack();
  138. Api::commit();
  139. $this->failed($ex->getMessage());
  140. throw $ex;
  141. }
  142. //task history
  143. $task = new TaskHistory();
  144. $task->fill([
  145. 'hosting_id' => $this->getWhmcsParamByKey("serviceid"),
  146. 'upid' => $taskId,
  147. 'name' => sprintf("VM %s - %s", $vmid, "Clone"),
  148. 'vmid' => $template->getVmid(),
  149. 'node' => $template->getNode(),
  150. 'status' => 0
  151. ])->save();
  152. //save task id
  153. $this->putModelDataAndSave(["taskId" => $taskId, "node" => $template->getNode(), "templateNode" => $templateNode]);
  154. //sleep
  155. $this->sleep();
  156. return false;
  157. }
  158. private function deleteNetwork(){
  159. $deleteNetwork = [];
  160. foreach (sl('Vm')->getVm()->getNetworkDevices() as $networkDevice){
  161. if(VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))
  162. ->ofNet($networkDevice->getId())
  163. ->ofVmId(sl('Vm')->getVmModel()->id)
  164. ->count()){
  165. continue;
  166. }
  167. $deleteNetwork[]=$networkDevice->getId();
  168. }
  169. if(!empty($deleteNetwork)){
  170. sl('Vm')->getVm()->deleteConfig(implode(",",$deleteNetwork));
  171. }
  172. }
  173. }