CloneQemuJob.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <?php
  2. namespace ModulesGarden\ProxmoxAddon\App\Jobs\Vps;
  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\ProxmoxApiException;
  7. use MGProvision\Proxmox\v2\repository\ClusterResourcesRepository;
  8. use ModulesGarden\ProxmoxAddon\App\Enum\Vps\CustomField;
  9. use ModulesGarden\ProxmoxAddon\App\Events\Vps\QemuUpdateEvent;
  10. use ModulesGarden\ProxmoxAddon\App\Events\Vps\VmCreatedEvent;
  11. use ModulesGarden\ProxmoxAddon\App\Factory\Ssh2Factory;
  12. use ModulesGarden\ProxmoxAddon\App\Models\CloudInitScript;
  13. use ModulesGarden\ProxmoxAddon\App\Models\TaskHistory;
  14. use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
  15. use ModulesGarden\ProxmoxAddon\App\Providers\SnippetProvider;
  16. use ModulesGarden\ProxmoxAddon\App\Repositories\ServerConfigurationRepository;
  17. use ModulesGarden\ProxmoxAddon\App\Services\CloudInitScriptConveter;
  18. use ModulesGarden\ProxmoxAddon\App\Services\Vps\ProductService;
  19. use ModulesGarden\ProxmoxAddon\App\Services\Vps\UserService;
  20. use ModulesGarden\ProxmoxAddon\App\Enum\Vps\ConfigurableOption;
  21. use function ModulesGarden\ProxmoxAddon\Core\Helper\fire;
  22. class CloneQemuJob extends BaseJob
  23. {
  24. use ProductService;
  25. use UserService;
  26. public function handle()
  27. {
  28. $this->initParams();
  29. $this->initServices();
  30. $this->setHostingId($this->getWhmcsParamByKey("serviceid"));
  31. //create task validation
  32. if ($this->isDone())
  33. {
  34. if(!$this->vm()->isRunning()){
  35. $this->deleteNetwork();
  36. }
  37. if($this->configuration()->isAdditionalDisk() && !$this->additionalDiskService->hasDisk() ){
  38. $this->additionalDiskService->create();
  39. }
  40. fire(new QemuUpdateEvent($this->vm()));
  41. try{
  42. if($this->agentService->isEnabled()){
  43. if(!$this->vm()->isRunning()){
  44. $this->log->info(sprintf("VM %s - Start", $this->vm()->getVmid()));
  45. $this->vm()->start();
  46. $this->sleep(5);
  47. return false;
  48. }
  49. $this->vm()->agent()->ping();
  50. $this->agentService ->getUserAndUpdate();
  51. $this->agentService ->passwordUpdate();
  52. $this->agentService ->configureNetwork();
  53. }
  54. }catch (ProxmoxApiException $ex){
  55. if(preg_match("/not running/", $ex->getMessage())){
  56. $this->log->info($ex->getMessage());
  57. }else{
  58. $this->log->error($ex->getMessage());
  59. }
  60. //sleep
  61. $this->sleep(5);
  62. return false;
  63. }
  64. fire(new VmCreatedEvent($this->vm()));
  65. return true;
  66. }
  67. elseif ($this->isTaskRunning())
  68. {
  69. //sleep
  70. $this->sleep(5);
  71. return false;
  72. }
  73. try
  74. {
  75. Api::beginTransaction();
  76. DB::beginTransaction();
  77. $osTemplate = $this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE, $this->configuration()->getOsTemplate() );
  78. //Support for configurable options i.e vmname|OS Name
  79. if (is_string($osTemplate) && !preg_match('/\//', $osTemplate))
  80. {
  81. $templateNode = $this->getNode()->getNode();
  82. $clusterRepository = new ClusterResourcesRepository();
  83. $clusterRepository->setApi($this->api());
  84. if(!$this->configuration()->isOsTemplatesInAllNodes()){
  85. $clusterRepository->findByNodes([$templateNode]);
  86. }
  87. $clusterRepository->findKvmTemplate();
  88. foreach ($clusterRepository->fetch() as $resurce)
  89. {
  90. if ($resurce->getName() == $osTemplate)
  91. {
  92. $templateVmid = $resurce->getVmid();
  93. $templateNode = $resurce->getNode();
  94. break;
  95. }
  96. }
  97. if (!$templateVmid)
  98. {
  99. throw new \Exception(sprintf("Unable to find KVM template: %s on node: %s", $osTemplate, $templateNode ));
  100. }
  101. //Support for configurable options like nodename/vmid|OS Name
  102. }
  103. else
  104. {
  105. if (preg_match('/\//', $osTemplate))
  106. {
  107. list($templateNode, $templateVmid) = explode("/", $osTemplate);
  108. }
  109. }
  110. //node
  111. $node = $this->getWhmcsCustomField(CustomField::NODE) ? $this->getWhmcsCustomField(CustomField::NODE) :$this->getNode()->getNode();
  112. //vmid
  113. $vmid = $this->nextVmid();
  114. $this->customFieldUpdate("vmid", $vmid);
  115. $this->customFieldUpdate("node", $node);
  116. //init container
  117. $container = [
  118. "newid" => $vmid,
  119. "full" => $this->configuration()->getCloneMode(),
  120. "target" => $node
  121. ];
  122. //description
  123. if ($this->configuration()->getDescription())
  124. {
  125. $container['description'] = $this->containerService->description();
  126. }
  127. //hostname
  128. $hostname = $this->containerService->hostname();
  129. if ($hostname)
  130. {
  131. $container['name'] = $hostname;
  132. }
  133. //Storage
  134. if (!$this->configuration()->isCloneOnTheSameStorage() && $this->configuration()->getDiskStorage() && $this->configuration()->getCloneMode() == "1")
  135. {
  136. $container['storage'] = $this->configuration()->getDiskStorage();
  137. }
  138. //pool
  139. if ($this->configuration()->getPool())
  140. {
  141. $container['pool'] = $this->configuration()->getPool();
  142. }
  143. //bwlimit
  144. if($this->configuration()->getBwLimit()){
  145. $container['bwlimit'] = $this->configuration()->getBwLimit();
  146. }
  147. //Create
  148. $template = new Kvm($templateNode, $templateVmid);
  149. $template->setApi($this->api());
  150. $taskId = $template->cloneVm($container);
  151. DB::commit();
  152. }
  153. catch (\Exception $ex)
  154. {
  155. DB::rollBack();
  156. Api::commit();
  157. $this->failed($ex->getMessage());
  158. throw $ex;
  159. }
  160. //task history
  161. $task = new TaskHistory();
  162. $task->fill([
  163. 'hosting_id' => $this->getWhmcsParamByKey("serviceid"),
  164. 'upid' => $taskId,
  165. 'name' => sprintf("VM %s - %s", $vmid, "Clone"),
  166. 'vmid' => $template->getVmid(),
  167. 'node' => $template->getNode(),
  168. 'status' => 0
  169. ])->save();
  170. //save task id
  171. $this->putModelDataAndSave(["taskId" => $taskId, "node" => $template->getNode(), "templateNode" => $templateNode]);
  172. //sleep
  173. $this->sleep();
  174. return false;
  175. }
  176. private function deleteNetwork(){
  177. $deleteNetwork = [];
  178. foreach ($this->vm()->getNetworkDevices() as $networkDevice){
  179. if(VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))->ofNet($networkDevice->getId())->count()){
  180. continue;
  181. }
  182. $deleteNetwork[]=$networkDevice->getId();
  183. }
  184. if(!empty($deleteNetwork)){
  185. $this->vm()->deleteConfig(implode(",",$deleteNetwork));
  186. }
  187. }
  188. }