CreateQemuJob.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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\HardDisk;
  6. use MGProvision\Proxmox\v2\models\Node;
  7. use MGProvision\Proxmox\v2\VmFactory;
  8. use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
  9. use ModulesGarden\ProxmoxAddon\App\Events\Cloud\VmCreatedEvent;
  10. use ModulesGarden\ProxmoxAddon\App\Jobs\BaseJob;
  11. use ModulesGarden\ProxmoxAddon\App\Models\NodeSetting;
  12. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\AdditionalDiskService;
  13. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ContainerService;
  14. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
  15. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
  16. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
  17. use ModulesGarden\ProxmoxAddon\App\Services\EmailService;
  18. use ModulesGarden\ProxmoxAddon\App\Traits\Cloud\VmNetwork;
  19. use function ModulesGarden\ProxmoxAddon\Core\Helper\fire;
  20. use function ModulesGarden\ProxmoxAddon\Core\Helper\sl;
  21. class CreateQemuJob extends BaseJob
  22. {
  23. use ProductService;
  24. use UserService;
  25. use VmNetwork;
  26. /**
  27. * @var NetworkService
  28. */
  29. protected $networkService;
  30. protected function initServices()
  31. {
  32. $this->emailService = new EmailService();
  33. $this->containerService = new ContainerService();
  34. $this->networkService = new NetworkService();
  35. $this->additionalDiskService = new AdditionalDiskService();
  36. }
  37. public function handle()
  38. {
  39. $this->initParams();
  40. $this->initServices();
  41. $this->setHostingId($this->getWhmcsParamByKey("serviceid"));
  42. //create task validation
  43. if ($this->isDone())
  44. {
  45. $this->initVm();
  46. if($this->getModelData()['additionalDiskSize1'] && !$this->additionalDiskService->hasDisk()){
  47. $this->additionalDiskService->create($this->getModelData());
  48. }
  49. fire(new VmCreatedEvent($this->getVmModel()));
  50. return true;
  51. }
  52. elseif ($this->isTaskRunning())
  53. {
  54. //sleep
  55. $this->sleep(5);
  56. return false;
  57. }
  58. try
  59. {
  60. Api::beginTransaction();
  61. DB::beginTransaction();
  62. //vmid
  63. $vmid = $this->nextVmid();
  64. $vmModel = $this->getVmModel();
  65. $vmModel->vmid = $vmid;
  66. $vmModel->save();
  67. sl('Vm')->setVm(null);
  68. sl('Vm')->setVmModel( $vmModel);
  69. $container = [
  70. 'vmid' => $vmid,
  71. 'name' => $this->getVmModel()->name,
  72. "ostype" => $this->getModelData()['ostype'] ? $this->getModelData()['ostype'] : $this->configuration()->getOsType(),
  73. ];
  74. //vcpus
  75. if ($this->getVmModel()->vcpus)
  76. {
  77. $container['vcpus'] = $this->getVmModel()->vcpus ;
  78. }
  79. //cpulimit
  80. if ($this->getVmModel()->cpulimit)
  81. {
  82. $container['cpulimit'] = $this->getVmModel()->cpulimit;
  83. }
  84. // Boot order device
  85. if ($this->configuration()->getBootOrder())
  86. {
  87. $container['boot'] = $this->configuration()->getBootOrder();
  88. }
  89. //numa
  90. if ($this->configuration()->isNuma())
  91. {
  92. $container['numa'] = 1;
  93. }
  94. //Memory
  95. if ($this->getVmModel()->memory)
  96. {
  97. $container['memory'] = $this->getVmModel()->memory;
  98. }
  99. //cpuunits
  100. if ($this->getVmModel()->cpuunits)
  101. {
  102. $container['cpuunits'] = $this->getVmModel()->cpuunits;
  103. }
  104. //Name servers
  105. $ns = [];
  106. for ($i = 0; $i <= 1; $i++)
  107. {
  108. $n = trim($this->getModelData()['nameserver'][$i]);
  109. if (!empty($n) && !filter_var($n, FILTER_VALIDATE_IP))
  110. {
  111. $n = gethostbyname($n);
  112. }
  113. if (!empty($n) && filter_var($n, FILTER_VALIDATE_IP))
  114. {
  115. $ns[] = $n;
  116. }
  117. }
  118. if ($ns)
  119. {
  120. $container['nameserver'] = implode(" ", $ns);
  121. }
  122. //sockets
  123. if ($this->getVmModel()->sockets)
  124. {
  125. $container['sockets'] = $this->getVmModel()->sockets;
  126. }
  127. //cores
  128. if ($this->getVmModel()->cores)
  129. {
  130. $container['cores'] = $this->getVmModel()->cores;
  131. }
  132. //description
  133. if ($this->getModelData()['description'])
  134. {
  135. $container['description'] = $this->getModelData()['description'];
  136. }
  137. //onboot
  138. if ($this->configuration()->isOnboot())
  139. {
  140. $container['onboot'] = 1;
  141. }
  142. //pool
  143. if ($this->configuration()->getPool())
  144. {
  145. $container['pool'] = $this->configuration()->getPool();
  146. }
  147. //startup
  148. if ($this->configuration()->getStartup())
  149. {
  150. $container['startup'] = $this->configuration()->getStartup();
  151. }
  152. //busDevces
  153. $busDevices = [
  154. "ide" => 0,
  155. "sata" => 0,
  156. "virtio" => 0,
  157. "scsi" => 0
  158. ];
  159. if (!$this->configuration()->getCdromType())
  160. {
  161. throw new \InvalidArgumentException("CD-ROM Type is empty, product configuration is not valid");
  162. }
  163. //CD-ROM primary ISO
  164. $type = $this->configuration()->getCdromType();
  165. $bus = $busDevices[$type];
  166. $busDevices[$type]++;
  167. $isoImage = $this->getModelData()['isoImage'] ? $this->getModelData()['isoImage'] : "none";
  168. $container[$type . $bus] = "{$isoImage},media=cdrom";
  169. //secondaryIsoImage
  170. if($this->getModelData()['secondaryIsoImage']){
  171. $bus = $busDevices[$type];
  172. $busDevices[$type]++;
  173. $container[$type . $bus] = "{$this->getModelData()['secondaryIsoImage']},media=cdrom";
  174. }
  175. //Disk
  176. $diskSize = $this->getVmModel()->disk;
  177. $type = $this->configuration()->getDiskType();
  178. $bus = $busDevices[$type];
  179. $busDevices[$type]++;
  180. $harDisk = new HardDisk($type . $bus);
  181. $dafaultStorage = NodeSetting::ofServer($this->getWhmcsParamByKey('serverid'))
  182. ->ofNode($this->getNode()->getNode())
  183. ->ofSetting('defaultStorage')
  184. ->value("value");
  185. $harDisk->setSize($diskSize)
  186. ->setStorage($dafaultStorage ? $dafaultStorage : $this->configuration()->getDiskStorage())
  187. ->setCache($this->configuration()->getDiskCache())
  188. ->setFormat($this->configuration()->getDiskFormat())
  189. ->setMbps_rd($this->configuration()->getMbpsRd())
  190. ->setMbps_wr($this->configuration()->getMbpsWr())
  191. ->setDiscard($this->configuration()->isDiscard() ? "on" : null)
  192. ->setIops_rd($this->configuration()->getIopsRd())
  193. ->setIops_rd_max($this->configuration()->getIopsRdMax())
  194. ->setIops_wr($this->configuration()->getIopsWr())
  195. ->setIops_wr_max($this->configuration()->getIopsWrMax())
  196. ->setReplicate($this->configuration()->isReplicate() ? 0 : null)
  197. ->setSsd($this->configuration()->isSsd() ? 1 : null);
  198. if($this->getWhmcsConfigOption(ConfigurableOption::STORAGE_DISK)){
  199. list($storage,$diskSize) = explode(":", $this->getWhmcsConfigOption(ConfigurableOption::STORAGE_DISK),2);
  200. $harDisk->setStorage($storage);
  201. }
  202. if ($this->configuration()->isIoThread() && in_array($type, ['virtio', 'scsi']))
  203. {
  204. $harDisk->setIothread($this->configuration()->isIoThread());
  205. }
  206. $container[$harDisk->getId()] = $harDisk->asConfig();
  207. //Network
  208. $container += $this->createNetwork();
  209. //acpi
  210. if ($this->configuration()->isAcpi())
  211. {
  212. $container['acpi'] = 1;
  213. }
  214. //agent
  215. if ($this->configuration()->isAgent())
  216. {
  217. $container['agent'] = 1;
  218. }
  219. //autostart
  220. if ($this->configuration()->isAutostart())
  221. {
  222. $container['autostart'] = 1;
  223. }
  224. //balloon
  225. if ($this->configuration()->getBalloon())
  226. {
  227. $container['balloon'] = $this->configuration()->getBalloon();
  228. }
  229. //shares
  230. if ($this->configuration()->getShares())
  231. {
  232. $container['shares'] = $this->configuration()->getShares();
  233. }
  234. //cdrom
  235. if ($this->configuration()->getCdrom())
  236. {
  237. $container['cdrom'] = $this->configuration()->getCdrom();
  238. }
  239. //cpu
  240. if ($this->configuration()->getCpu())
  241. {
  242. $container['cpu'] = $this->configuration()->getCpu();
  243. }
  244. //freeze
  245. if ($this->configuration()->isFreeze())
  246. {
  247. $container['freeze'] = 1;
  248. }
  249. //hotplug
  250. if ($this->configuration()->getHotplug())
  251. {
  252. $container['hotplug'] = $this->configuration()->getHotplug();
  253. }
  254. //keyboard
  255. if ($this->configuration()->getKeyboard())
  256. {
  257. $container['keyboard'] = $this->configuration()->getKeyboard();
  258. }
  259. //kvm
  260. if ($this->configuration()->isKvm())
  261. {
  262. $container['kvm'] = 1;
  263. }
  264. //localtime
  265. if ($this->configuration()->isLocaltime())
  266. {
  267. $container['localtime'] = 1;
  268. }
  269. //migrate_downtime
  270. if ($this->configuration()->getMigrateDowntime())
  271. {
  272. $container['migrate_downtime'] = $this->configuration()->getMigrateDowntime();
  273. }
  274. //migrate_speed
  275. if ($this->configuration()->getMigrateSpeed())
  276. {
  277. $container['migrate_speed'] = $this->configuration()->getMigrateSpeed();
  278. }
  279. //reboot
  280. if ($this->configuration()->isReboot())
  281. {
  282. $container['reboot'] = 1;
  283. }
  284. //startdate
  285. if ($this->configuration()->getStartdate())
  286. {
  287. $container['startdate'] = $this->configuration()->getStartdate();
  288. }
  289. //startup
  290. if ($this->configuration()->getStartup())
  291. {
  292. $container['startup'] = $this->configuration()->getStartup();
  293. }
  294. //tablet
  295. if ($this->configuration()->isTablet())
  296. {
  297. $container['tablet'] = 1;
  298. }
  299. //tdf
  300. if ($this->configuration()->isTdf())
  301. {
  302. $container['tdf'] = 1;
  303. }
  304. //watchdog
  305. if ($this->configuration()->getWatchdog())
  306. {
  307. $container['watchdog'] = $this->configuration()->getWatchdog();
  308. }
  309. //bootdisk
  310. if ($this->configuration()->getBootdisk())
  311. {
  312. $container['bootdisk'] = $this->configuration()->getBootdisk();
  313. }
  314. //scsihw
  315. if ($this->configuration()->getScsihw())
  316. {
  317. $container['scsihw'] = $this->configuration()->getScsihw();
  318. }
  319. //args
  320. if ($this->configuration()->getArgs())
  321. {
  322. $container['args'] = $this->configuration()->getArgs();
  323. }
  324. //vga
  325. $vga=[];
  326. if ($this->configuration()->getVga())
  327. {
  328. $vga[] = $this->configuration()->getVga();
  329. }
  330. if($container['vga']!="none" && $this->configuration()->getVgaMemory()){
  331. $vga[]="memory=".$this->configuration()->getVgaMemory();
  332. }
  333. if(!empty($vga)){
  334. $container['vga'] = implode(",",$vga);
  335. }
  336. //xterm.js Console
  337. if ($this->configuration()->isPermissionXtermjs())
  338. {
  339. $container['serial0'] = 'socket';
  340. }
  341. //cpu flags
  342. if ($this->configuration()->hasCpuFlags() && version_compare($this->api()->getVersion(), "5.2", '>'))
  343. {
  344. $container['cpu'] .= ',flags=' .$this->configuration()->getCpuFlagsAsSource();
  345. }
  346. //start
  347. if ($this->configuration()->isStart())
  348. {
  349. $container['start'] = 1;
  350. }
  351. //bios
  352. if ($this->configuration()->getBios())
  353. {
  354. $container['bios'] = $this->configuration()->getBios();
  355. }
  356. //machine
  357. if ($this->configuration()->getMachine())
  358. {
  359. $container['machine'] = $this->configuration()->getMachine();
  360. }
  361. //Create
  362. $nodeService = new Node($this->getVmModel()->node);
  363. $vm = $nodeService->kvm();
  364. $this->setVm($vm);
  365. $vm = (new VmFactory())->fromVmModel( $vmModel);
  366. //init vm
  367. sl('Vm')->setVm($vm);
  368. $taskId = $vm->create($container);
  369. DB::commit();
  370. }
  371. catch (\Exception $ex)
  372. {
  373. echo $ex->getMessage();
  374. DB::rollBack();
  375. Api::commit();
  376. throw $ex;
  377. }
  378. //task history
  379. $this->createTaskHistory($taskId, "Create");
  380. //save task id
  381. $this->putModelDataAndSave(["taskId" => $taskId, "node" => $nodeService->getNode()]);
  382. //sleep
  383. $this->sleep();
  384. return false;
  385. }
  386. }