CreateAccount.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. <?php
  2. /**********************************************************************
  3. * ProxmoxVPS developed. (26.03.19)
  4. * *
  5. *
  6. * CREATED BY MODULESGARDEN -> http://modulesgarden.com
  7. * CONTACT -> contact@modulesgarden.com
  8. *
  9. *
  10. * This software is furnished under a license and may be used and copied
  11. * only in accordance with the terms of such license and with the
  12. * inclusion of the above copyright notice. This software or any other
  13. * copies thereof may not be provided or otherwise made available to any
  14. * other person. No title to and ownership of the software is hereby
  15. * transferred.
  16. *
  17. *
  18. **********************************************************************/
  19. namespace ModulesGarden\Servers\ProxmoxVps\App\Http\Actions;
  20. use MGProvision\Proxmox\v2\models\Kvm;
  21. use MGProvision\Proxmox\v2\models\Node;
  22. use MGProvision\Proxmox\v2\repository\ClusterResourcesRepository;
  23. use ModulesGarden\ProxmoxAddon as addon;
  24. use ModulesGarden\ProxmoxAddon\App\Configuration\Addon\Update\AddonUpgradeService;
  25. use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
  26. use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
  27. use ModulesGarden\ProxmoxAddon\App\Services\Utility;
  28. use ModulesGarden\ProxmoxAddon\App\Services\Vps\HostingService;
  29. use ModulesGarden\ProxmoxAddon\App\Services\Vps\NetworkService;
  30. use ModulesGarden\ProxmoxAddon\App\Services\Vps\ProductService;
  31. use ModulesGarden\ProxmoxAddon\App\Services\Vps\UserService;
  32. use ModulesGarden\ProxmoxAddon\Core\Queue\Models\Job;
  33. use ModulesGarden\Servers\ProxmoxVps\App\Enum\CustomField;
  34. use ModulesGarden\Servers\ProxmoxVps\App\Helpers\AppParams;
  35. use ModulesGarden\Servers\ProxmoxVps\App\Helpers\ProxmoxAddonValidator;
  36. use ModulesGarden\Servers\ProxmoxVps\Core\App\Controllers\Instances\AddonController;
  37. use ModulesGarden\Servers\ProxmoxVps\Core\Models\Whmcs\Server;
  38. use ModulesGarden\Servers\ProxmoxVps\Core\UI\Traits\WhmcsParams;
  39. use ModulesGarden\ProxmoxAddon\App\Enum\Vps\ConfigurableOption;
  40. class CreateAccount extends AddonController
  41. {
  42. use WhmcsParams;
  43. use ProductService;
  44. use ApiService;
  45. use UserService;
  46. use HostingService;
  47. use addon\App\Traits\Vps\SnippetTrait;
  48. private $errors = [];
  49. /**
  50. * @var AddonUpgradeService
  51. */
  52. private $addonUpgradeService;
  53. /**
  54. * @var Kvm|null
  55. */
  56. private $templateVm;
  57. public function execute($params = null)
  58. {
  59. if(!ProxmoxAddonValidator::isInstalled()){
  60. return ProxmoxAddonValidator::failAsString();
  61. }
  62. (new AppParams())->initFromWhmcsParams();
  63. $this->addonUpgradeService = new AddonUpgradeService();
  64. $this->addonUpgradeService->run();
  65. try
  66. {
  67. //init nameservers
  68. $this->initNameServers();
  69. //Validate
  70. $this->validate();
  71. //Clone validate
  72. if ($this->configuration()->isQemu())
  73. {
  74. $this->cloneValidate();
  75. }
  76. //Check free resources
  77. $this->checkResources();
  78. //update hostname
  79. if($params['customfields']['proxmoxHostname']){
  80. $this->hosting()->domain = $params['customfields']['proxmoxHostname'];
  81. $this->hosting()->save();
  82. }
  83. //throw errors
  84. if ($this->errors)
  85. {
  86. throw new \Exception(implode(", ", $this->errors));
  87. }
  88. //Create User
  89. if (!$this->isUser())
  90. {
  91. $this->userCreate();
  92. }elseif($this->isUser() ){
  93. $this->createUserIfNotExist($this->getUser());
  94. }
  95. //Assing ip
  96. if (!Utility::isIpManagerProxmoxVPSIntegration())
  97. {
  98. if ($this->isCustomIpRequest() && $this->hasCustomIp())
  99. {
  100. $this->addCustomIp();
  101. }
  102. else
  103. {
  104. $networkService = new NetworkService();
  105. list($requestIPv4, $requestIPv6) = $networkService->getIpAddressesRequest();
  106. $node = $this->getNode()->getNode();
  107. $bridge = $this->configuration()->getBridge();
  108. $networkService->hasIp($requestIPv4, $requestIPv6, $node, $bridge)
  109. ->addIp($requestIPv4, $requestIPv6, $node, $bridge);
  110. $this->customFieldUpdate(CustomField::NODE, $node);
  111. }
  112. }
  113. //automaticaly configure administartor username for window
  114. if($this->templateVm instanceof Kvm &&
  115. $this->configuration()->isAgent() &&
  116. $this->configuration()->isAgentServicePassword() &&
  117. !$this->configuration()->isAgentTemplateUser() &&
  118. preg_match('/w/', $this->templateVm->config()['ostype'])){
  119. $ciuser = $this->templateVm->config()['ciuser'];
  120. $this->hosting()->update(['username' => $ciuser ?: 'Administrator' ]);
  121. }
  122. elseif($this->templateVm instanceof Kvm && $this->templateVm->config()['ciuser']){
  123. $ciuser = $this->templateVm->config()['ciuser'];
  124. $this->hosting()->update(['username' => $ciuser ]);
  125. }
  126. elseif($this->configuration()->isQemu() && $this->configuration()->getCiuser()){
  127. $this->hosting()->update(['username' =>$this->configuration()->getCiuser() ]);
  128. }
  129. //hosting limit
  130. $this->saveUsageLimit();
  131. //os
  132. if($this->isWhmcsConfigOption(ConfigurableOptioN::OS_TEMPLATE) && $this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE) !="0"){
  133. $osTemplate = $this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE);
  134. }else if( $this->isWhmcsConfigOption(ConfigurableOption::ARCHIVE) && $this->getWhmcsConfigOption(ConfigurableOption::ARCHIVE) !="0" ){
  135. $archive = $this->getWhmcsConfigOption(ConfigurableOption::ARCHIVE);
  136. } else if($this->isWhmcsConfigOption(ConfigurableOption::ISO_IMAGE) && $this->isWhmcsConfigOption(ConfigurableOption::ISO_IMAGE)!="0"){
  137. $osTemplate = null;
  138. }
  139. else if($this->configuration()->getOsTemplate() && $this->configuration()->getOsTemplate()!="0"){
  140. $osTemplate = $this->configuration()->getOsTemplate();
  141. } else if($this->configuration()->archive && $this->configuration()->archive!="0"){
  142. $archive = $this->configuration()->archive;
  143. }
  144. if(isset($archive) && $archive){ //archive
  145. list($backupNode, $volid) = explode(":", $archive, 2);
  146. }
  147. //Create task
  148. if ($this->configuration()->isLxc())
  149. {
  150. $taskName = addon\App\Jobs\Vps\CreateLxcJob::class;
  151. }
  152. else if ($this->configuration()->isQemu())
  153. {
  154. //default task
  155. $taskName = addon\App\Jobs\Vps\CreateQemuJob::class;
  156. //clone
  157. if (isset($osTemplate) && $osTemplate)
  158. {
  159. $taskName = addon\App\Jobs\Vps\CloneQemuJob::class;
  160. }elseif(isset($archive) && $archive){ //archive
  161. $taskName = addon\App\Jobs\Vps\RestoreArchiveJob::class;
  162. }
  163. }
  164. $arguments = [
  165. 'hostingId' => $this->getWhmcsParamByKey('serviceid'),
  166. ];
  167. //create snippet
  168. if($this->configuration()->isQemu() && $this->hasSnippet()){
  169. $parent = addon\Core\Helper\queue(addon\App\Jobs\Vps\CreateSnippet::class, $arguments, null, "hosting", $this->getWhmcsParamByKey("serviceid"));
  170. }
  171. $parent = addon\Core\Helper\queue($taskName, $arguments, $parent->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
  172. //Migrate Vm only for RestoreArchiveJob
  173. if($backupNode && $node && $backupNode != $node){
  174. $attributes = [
  175. "targetNode" => $node,
  176. "online" => 1,
  177. 'with-local-disks' => 1,
  178. 'restart' => 1
  179. ];
  180. addon\Core\Helper\queue(addon\App\Jobs\Vps\MigrateVmJob::class, $attributes, $parent->id, "hosting", $this->getWhmcsParamByKey("serviceid"));
  181. }
  182. return "success";
  183. }
  184. catch (\Exception $ex)
  185. {
  186. if (addon\App\Models\ModuleSettings::isDebug())
  187. {
  188. logModuleCall(
  189. 'ProxmoxVps',
  190. __CLASS__,
  191. [],
  192. null,
  193. $ex->getMessage() . " " . $ex->getTraceAsString()
  194. );
  195. }
  196. return $ex->getMessage();
  197. }
  198. }
  199. private function validate()
  200. {
  201. //vmid
  202. if ($this->getWhmcsCustomField(CustomField::VMID))
  203. {
  204. $this->errors[] = "Custom Field \"VMID\" is not empty";
  205. }
  206. //node
  207. if ($this->getWhmcsCustomField(CustomField::NODE))
  208. {
  209. $this->errors[] = "Custom Field \"Node\" is not empty";
  210. }
  211. if (!in_array($this->configuration()->getVirtualization(), ["qemu", "lxc"]))
  212. {
  213. $this->errors[] = 'Unknown virtualization type: ' . $this->configuration()->getVirtualization();
  214. }
  215. //Network bridge
  216. if (!$this->configuration()->getBridge())
  217. {
  218. $this->errors[] = "''Bridge' - is empty";
  219. }
  220. //lxc
  221. if ($this->configuration()->isLxc())
  222. {
  223. //OS Template
  224. if (!$this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE, $this->configuration()->getOsTemplate()) && !$this->getWhmcsConfigOption(ConfigurableOption::ARCHIVE, $this->configuration()->archive) )
  225. {
  226. $this->errors[] = "'OS Template' - is empty";
  227. }
  228. //Storage
  229. if (!$this->configuration()->getStorage())
  230. {
  231. $this->errors[] = "'Default Storage' - is empty";
  232. }
  233. $taskName = addon\App\Jobs\Vps\CreateLxcJob::class . '@handle';
  234. }
  235. else
  236. {
  237. if ($this->configuration()->isQemu())
  238. {
  239. //searchdomain
  240. if ($this->configuration()->getSearchdomain() && !preg_match('/^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$/', $this->configuration()->getSearchdomain()))
  241. {
  242. $this->errors[] = sprintf('DNS Domain \'%s\' is invalid', $this->configuration()->getSearchdomain());
  243. }
  244. //SSH Key
  245. if ($this->getWhmcsParamByKey('customfields')['sshkeys'] && !preg_match('/ssh\-/', $this->getWhmcsParamByKey('customfields')['sshkeys']))
  246. {
  247. $this->errors[] = ' SSH Public Key is invalid';
  248. }
  249. $taskName = addon\App\Jobs\Vps\CreateQemuJob::class . '@handle';
  250. $osTemplate = $this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE, $this->configuration()->getOsTemplate() );
  251. //clone
  252. if (!empty($osTemplate) && $osTemplate != "0")
  253. {
  254. $taskName = addon\App\Jobs\Vps\CloneQemuJob::class . '@handle';
  255. }
  256. }
  257. }
  258. $query = Job::where("job", $taskName)->whereIn("status", ['waiting', "running", ""])->where("rel_id", $this->getWhmcsParamByKey("serviceid"))->where("rel_type", "hosting")
  259. ->orWhere("job", $taskName)->where("status", 'error')->where("rel_id", $this->getWhmcsParamByKey("serviceid"))->where("rel_type", "hosting")->where("retry_count","<",100);
  260. if ( $query->count() )
  261. {
  262. $this->errors[] = "Job 'create' already exist";
  263. }
  264. //Name servers
  265. if ($this->configuration()->isLxc() || $this->configuration()->isCloudInitServiceNameservers())
  266. {
  267. $ns = [];
  268. for ($i = 1; $i <= 2; $i++)
  269. {
  270. $n = trim($this->hosting()->{"ns{$i}"});
  271. if (!empty($n) && !filter_var($n, FILTER_VALIDATE_IP))
  272. {
  273. $n = gethostbyname($n);
  274. }
  275. if (!empty($n) && !filter_var($n, FILTER_VALIDATE_IP))
  276. {
  277. $ns[] = "'{$n}'";
  278. }
  279. }
  280. if (!empty($ns))
  281. {
  282. $this->errors[] = sprintf(" Name Server value: %s does not look like a valid IP Address", implode(", ", $ns));
  283. }
  284. }
  285. //Disk size
  286. $diskSize = $this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE);
  287. if($this->getWhmcsConfigOption(ConfigurableOption::STORAGE)){
  288. list($storage,$diskSize) = explode(":", $this->getWhmcsConfigOption(ConfigurableOption::STORAGE),2);
  289. }
  290. if ($diskSize && $this->configuration()->getDiskUnit() == "mb" && $diskSize < 1024)
  291. {
  292. $this->errors[] = sprintf("Disk size of %sMB cannot be created", $diskSize);
  293. }
  294. $rate = $this->getWhmcsConfigOption(addon\App\Enum\Vps\ConfigurableOption::NETWORK_RATE) ? $this->getWhmcsConfigOption(addon\App\Enum\Vps\ConfigurableOption::NETWORK_RATE) :$this->configuration()->getRate();
  295. if ($rate && !is_numeric($rate))
  296. {
  297. $this->errors[] = sprintf("Network Rate - invalid format: %s ", $rate) ;
  298. }
  299. }
  300. private function initNameServers()
  301. {
  302. $this->setHostingId($this->getWhmcsParamByKey("serviceid"));
  303. if ($this->configuration()->isServerNameservers())
  304. {
  305. $server = Server::select('id', 'nameserver1ip', 'nameserver2ip')->findOrFail($this->getWhmcsParamByKey('serverid'));
  306. $this->hosting()->ns1 = trim($server->nameserver1ip);
  307. $this->hosting()->ns2 = trim($server->nameserver2ip);
  308. $this->hosting()->save();
  309. }
  310. else
  311. {
  312. if ($this->configuration()->isLxc() || $this->configuration()->isCloudInitServiceNameservers())
  313. {
  314. $domain = $this->getWhmcsCustomField(CustomField::HOSTNAME, $this->getWhmcsParamByKey('domain'));
  315. $update = [];
  316. for ($i = 1; $i <= 2; $i++)
  317. {
  318. $n = trim($this->hosting()->{"ns{$i}"});
  319. if (!empty($n) && !filter_var($n, FILTER_VALIDATE_IP))
  320. {
  321. $host = preg_match('/\./', $n) ? $n : "{$n}.{$domain}";
  322. $n = gethostbyname($host);
  323. if (!$n || !filter_var($n, FILTER_VALIDATE_IP))
  324. {
  325. throw new \Exception(sprintf("Nameserver '%s' cannot be resolved", $host));
  326. }
  327. }
  328. if (!empty($n) && filter_var($n, FILTER_VALIDATE_IP))
  329. {
  330. $update['ns' . $i] = $n;
  331. $this->hosting()->{"ns{$i}"} = $n;
  332. }
  333. }
  334. if ($update)
  335. {
  336. $this->hosting()->update($update);
  337. }
  338. }
  339. }
  340. }
  341. private function isCustomIpRequest()
  342. {
  343. //if there is custom ip on dedicated ip or assinged ips
  344. $model = $this->getWhmcsParamByKey('model');
  345. if (!$model)
  346. {
  347. $model = \WHMCS\Service\Service::where("id", $this->getWhmcsParamByKey('serviceid'))->first();
  348. }
  349. if (!$model->dedicatedip && !$model->assignedips)
  350. {
  351. return false;
  352. }
  353. $ips = $this->getCustomIp();
  354. if (!$ips)
  355. {
  356. return false;
  357. }
  358. foreach ($ips as $k => $ip)
  359. {
  360. if (!filter_var((string)$ip, FILTER_VALIDATE_IP))
  361. {
  362. throw new \Exception(sprintf("IP Address '%s' is not valid", $ip));
  363. }
  364. }
  365. return true;
  366. }
  367. private function getCustomIp()
  368. {
  369. $ips = [];
  370. $model = $this->getWhmcsParamByKey('model');
  371. if (!$model)
  372. {
  373. $model = \WHMCS\Service\Service::where("id", $this->getWhmcsParamByKey('serviceid'))->first();
  374. }
  375. if ($model->dedicatedip)
  376. {
  377. $ips[] = $model->dedicatedip;
  378. }
  379. if ($model->assignedips)
  380. {
  381. $ex = explode(PHP_EOL, $model->assignedips);
  382. foreach ($ex as $ip)
  383. {
  384. if (!$ip)
  385. {
  386. continue;
  387. }
  388. $ips[] = str_replace(["\r", "\n"], ["", ""], $ip);
  389. }
  390. }
  391. return array_diff($ips, [""]);
  392. }
  393. private function hasCustomIp()
  394. {
  395. $nodeName = $this->getNode()->getNode();
  396. $ipAddresses = $this->getCustomIp();
  397. $virtualization = $this->configuration()->isQemu() ? "KVM" : "LXC";
  398. $ipCollections = addon\App\Models\IpAddress::where('hosting_id', '0')
  399. ->where('private', '0')
  400. ->whereIn('ip', $ipAddresses)
  401. ->whereIn('sid', [$this->getWhmcsParamByKey('serverid'), '0'])
  402. ->whereIn('visualization', [$virtualization, 'Auto'])
  403. ->whereIn('node', [$nodeName, '0', ""]);
  404. $count = $ipCollections->count();
  405. return $count == count($ipAddresses);
  406. }
  407. private function addCustomIp()
  408. {
  409. $nodeName = $this->getNode()->getNode();
  410. $ipAddresses = $this->getCustomIp();
  411. $virtualization = $this->configuration()->isQemu() ? "KVM" : "LXC";
  412. addon\App\Models\IpAddress::where('hosting_id', '0')
  413. ->where('private', '0')
  414. ->whereIn('ip', $ipAddresses)
  415. ->whereIn('sid', [$this->getWhmcsParamByKey('serverid'), '0'])
  416. ->whereIn('visualization', [$virtualization, 'Auto'])
  417. ->whereIn('node', [$nodeName, '0', ""])
  418. ->update(["hosting_id" => $this->getWhmcsParamByKey('serviceid'), 'last_check' => Utility::timeStamp()]);
  419. //get ips
  420. $collection = addon\App\Models\IpAddress::where('hosting_id', $this->getWhmcsParamByKey('serviceid'))
  421. ->whereNotIn('ip', function ($query)
  422. {
  423. $query->select('ip')->from((new VmIpAddress)->getTable());
  424. });
  425. foreach ($collection->get() as $ip)
  426. {
  427. /*@var $ip VmIpAddress */
  428. $newIp = new VmIpAddress();
  429. $ipData = $ip->toArray();
  430. $ipData['hosting_id'] = $this->getWhmcsParamByKey('serviceid');
  431. $ipData['server_id'] = $this->getWhmcsParamByKey('serverid');
  432. $newIp->fill($ipData)->save();
  433. }
  434. return $this;
  435. }
  436. private function checkResources()
  437. {
  438. if (!$this->configuration()->isCheckResources())
  439. {
  440. return;
  441. }
  442. //get free space
  443. $storage = $this->configuration()->isQemu() ? $this->configuration()->getDiskStorage() : $this->configuration()->getStorage();
  444. $resurces = $this->getNode()->getFreeSpace($storage);
  445. //Memory
  446. if ($this->getWhmcsConfigOption(ConfigurableOption::MEMORY))
  447. {
  448. $memoryBytes = $this->getWhmcsConfigOption(ConfigurableOption::MEMORY);
  449. Utility::unitFormat($memoryBytes, $this->configuration()->getMemoryUnit(), 'bytes');
  450. }
  451. else
  452. {
  453. $memoryBytes = $this->configuration()->getMemory();
  454. Utility::unitFormat($memoryBytes, "mb", 'bytes');
  455. }
  456. //Validation
  457. if ($memoryBytes && $resurces['memory'] && $memoryBytes > $resurces['memory'])
  458. {
  459. $this->errors[] = sprintf("Unable to allocate %s of Memory. Memory available: %s",
  460. addon\App\Libs\Format::convertBytes($memoryBytes), addon\App\Libs\Format::convertBytes($resurces['memory']));
  461. }
  462. //SWAP
  463. if ($this->configuration()->isLxc())
  464. {
  465. if ($this->getWhmcsConfigOption(ConfigurableOption::SWAP))
  466. {
  467. $swapBytes = $this->getWhmcsConfigOption(ConfigurableOption::SWAP);
  468. Utility::unitFormat($swapBytes, strtolower($this->configuration()->getSwapUnit()), 'bytes');
  469. }
  470. else
  471. {
  472. $swapBytes = $this->configuration()->getSwap();
  473. Utility::unitFormat($swapBytes, "mb", 'bytes');
  474. }
  475. //Validation
  476. if ($swapBytes && $resurces['swap'] && $swapBytes > $resurces['swap'])
  477. {
  478. $this->errors[] = sprintf("Unable to allocate %s of SWAP. SWAP available: %s",
  479. addon\App\Libs\Format::convertBytes($swapBytes), addon\App\Libs\Format::convertBytes($resurces['swap']));
  480. }
  481. }
  482. //Disk
  483. if($this->getWhmcsConfigOption(ConfigurableOption::STORAGE)){
  484. list($storage,$diskBytes ) = explode(":", $this->getWhmcsConfigOption(ConfigurableOption::STORAGE),2);
  485. Utility::unitFormat($diskBytes , $this->configuration()->getDiskUnit(), 'bytes');
  486. }
  487. elseif ($this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE))
  488. {
  489. $diskBytes = $this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE);
  490. Utility::unitFormat($diskBytes, $this->configuration()->getDiskUnit(), 'bytes');
  491. }
  492. else
  493. {
  494. $diskBytes = $this->configuration()->getDiskSize();
  495. Utility::unitFormat($diskBytes, "gb", 'bytes');
  496. }
  497. //Validation
  498. if ($diskBytes && $resurces['storage'] && $diskBytes > $resurces['storage'])
  499. {
  500. $this->errors[] = sprintf("Unable to allocate %s of Disk Space. Disk Space available: %s",
  501. addon\App\Libs\Format::convertBytes($diskBytes), addon\App\Libs\Format::convertBytes($resurces['storage']));
  502. }
  503. }
  504. private function cloneValidate()
  505. {
  506. $osTemplate = $this->getWhmcsConfigOption(ConfigurableOption::OS_TEMPLATE, $this->configuration()->getOsTemplate() );
  507. if (empty($osTemplate) && $osTemplate == "0")
  508. {
  509. return;
  510. }
  511. //Support for configurable options i.e vmname|OS Name
  512. if (is_string($osTemplate) && !preg_match('/\//', $osTemplate))
  513. {
  514. $templateNode = $this->getNode()->getNode();
  515. $clusterRepository = new ClusterResourcesRepository();
  516. $clusterRepository->setApi($this->api());
  517. if(!$this->configuration()->isOsTemplatesInAllNodes()){
  518. $clusterRepository->findByNodes([$templateNode]);
  519. }
  520. $clusterRepository->findKvmTemplate();
  521. foreach ($clusterRepository->fetch() as $resurce)
  522. {
  523. if ($resurce->getName() == $osTemplate )
  524. {
  525. $templateVmid = $resurce->getVmid();
  526. $templateNode = $resurce->getNode();
  527. break;
  528. }
  529. }
  530. if (!$templateVmid)
  531. {
  532. $this->errors[] = sprintf("Unable to find KVM template: %s on node: %s", $osTemplate, $this->getNode()->getNode());
  533. return;
  534. }
  535. //Support for configurable options like nodename/vmid|OS Name
  536. }
  537. else
  538. {
  539. if (preg_match('/\//', $osTemplate))
  540. {
  541. list($templateNode, $templateVmid) = explode("/", $osTemplate);
  542. }
  543. }
  544. if (!in_array($templateNode, (array)$this->api()->get_node_list()))
  545. {
  546. $this->errors[] = sprintf("Unable to find node %s on cluster %s", $templateNode, $this->api()->getPveHostname());
  547. return;
  548. }
  549. //template exist on node?
  550. $node = new Node($templateNode);
  551. $node->setApi($this->api());
  552. if (!$node->hasKvm($templateVmid))
  553. {
  554. $this->errors[] = sprintf("KVM template VMID '%s' does not exist on node '%s'", $templateVmid, $templateNode);
  555. return;
  556. }
  557. //Disk size validation
  558. $this->templateVm = new Kvm($templateNode, $templateVmid);
  559. $this->templateVm->setApi($this->api());
  560. //Disk
  561. $diskSize = $this->configuration()->getDiskSize();
  562. if($this->getWhmcsConfigOption(ConfigurableOption::STORAGE)){
  563. list($storage,$diskSize) = explode(":", $this->getWhmcsConfigOption(ConfigurableOption::STORAGE),2);
  564. Utility::unitFormat($diskSize, $this->configuration()->getDiskUnit(), 'bytes');
  565. }
  566. else if ($this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE))
  567. {
  568. $diskSize = $this->getWhmcsConfigOption(ConfigurableOption::DISK_SIZE);
  569. Utility::unitFormat($diskSize, $this->configuration()->getDiskUnit(), 'bytes');
  570. }else{
  571. Utility::unitFormat($diskSize, "gb", 'bytes');
  572. }
  573. if ($this->templateVm->getMasterHardDisk()->getBytes() > $diskSize)
  574. {
  575. $this->errors[] = sprintf('Downgrading disk size is restricted. Request Disk size: %s, VM disk size: %s', addon\App\Libs\Format::convertBytes($diskSize), addon\App\Libs\Format::convertBytes($this->templateVm->getMasterHardDisk()->getBytes()));
  576. }
  577. }
  578. }