VmUpdateProvider.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. <?php
  2. namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Providers;
  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\MountPoint;
  7. use MGProvision\Proxmox\v2\models\NetworkDeviceKvm;
  8. use MGProvision\Proxmox\v2\repository\FileRepository;
  9. use MGProvision\Proxmox\v2\repository\StorageRepository;
  10. use ModulesGarden\ProxmoxAddon\App\Events\Cloud\LxcUpdateEvent;
  11. use ModulesGarden\ProxmoxAddon\App\Events\Cloud\QemuUpdateEvent;
  12. use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Agent\ChangePasswordJob;
  13. use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Agent\ConfigureNetworkJob;
  14. use ModulesGarden\ProxmoxAddon\App\Models\VirtualInterface;
  15. use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
  16. use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
  17. use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
  18. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\AdditionalDiskService;
  19. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\AdditionalMountPointService;
  20. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\AgentService;
  21. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\IpSetIpFilterService;
  22. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
  23. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
  24. use ModulesGarden\ProxmoxAddon\App\Services\Cloud\VirtualInterfaceConverter;
  25. use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Providers\VmCreateProvider;
  26. use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
  27. use function ModulesGarden\ProxmoxAddon\Core\Helper\fire;
  28. use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
  29. use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
  30. class VmUpdateProvider extends VmCreateProvider
  31. {
  32. use ApiService;
  33. use ProductService;
  34. /**
  35. * VmUpdateProvider constructor.
  36. */
  37. public function __construct()
  38. {
  39. $this->model = VmModel::class;
  40. }
  41. public function read()
  42. {
  43. $this->vmModel = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
  44. $this->data = $this->vmModel->toArray();
  45. $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
  46. $config = $vm->config();
  47. $this->data['ciuser'] = $config['ciuser'];
  48. $this->data['cipassword'] = $config['cipassword'];
  49. $this->data['description'] = html_entity_decode($config['description']);
  50. $this->data['searchdomain'] = $config['searchdomain'];
  51. $ns = explode(" ",$config['nameserver']);
  52. $this->data['nameserver[0]'] = $ns[0];
  53. $this->data['nameserver[1]'] = $ns[1];
  54. if(!$this->configuration()->isOrderPublicIp()){
  55. $this->data['ipv4'] = $this->vmModel->ipv4Addresses->count();
  56. $this->data['ipv6'] = $this->vmModel->ipv6Addresses->count();
  57. }
  58. //sshkeys
  59. $this->data['sshkeys'] = rawurldecode($vm->config()['sshkeys']);
  60. //cpu Priority
  61. if($this->configuration()->hasCpuPriority()){
  62. for($i=1; $i<=5; $i++){
  63. $cpuunits = $this->configuration()->get('cpuunitsPriority'.$i);
  64. $cpulimit = $this->configuration()->get('cpulimitPriority'.$i);
  65. if($this->vmModel->cpulimit >= $cpulimit){
  66. $this->data['cpuPriority'] = $i;
  67. }
  68. if($this->vmModel->cpuunits >= $cpuunits){
  69. $this->data['cpuPriority'] = $i;
  70. }
  71. }
  72. }
  73. //iso
  74. if ($this->configuration()->isQemu() && $this->configuration()->isPermissionIsoImage()) {
  75. $this->availableValues['iso'] = ["none" => sl('lang')->abtr("None")];
  76. $storageRepository = new StorageRepository();
  77. $storageRepository->findByNodes([$vm->getNode()])
  78. ->findEnabed();
  79. $storages = $storageRepository->fetchAsArray();
  80. $isoRepository = new FileRepository();
  81. $isoRepository->findByNodes([$vm->getNode()])
  82. ->findByStorages($storages);
  83. $isoRepository->findIso();
  84. foreach ($isoRepository->fetch() as $entity) {
  85. if ($this->configuration()->isPermissionIsoImages() && !in_array($entity->getVolid(), $this->configuration()->getPermissionIsoImages())) {
  86. continue;
  87. }
  88. $this->availableValues['iso'][$entity->getVolid()] = $entity->getFriendlyName();
  89. }
  90. if( $vm->getCdRomRepository()->first()){
  91. $this->data['iso']= $vm->getCdRomRepository()->first()->getLocation();
  92. }
  93. }
  94. }
  95. public function update()
  96. {
  97. $this->vmModel = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
  98. $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
  99. $this->networkService = new NetworkService();
  100. if(!$this->configuration()->isOrderPublicIp()){
  101. $ipv4 = (int) $this->getFormDataValues()['ipv4'] - (int) $this->vmModel->ipv4Addresses->count();
  102. $ipv6 = (int)$this->getFormDataValues()['ipv6'] - (int) $this->vmModel->ipv6Addresses->count();
  103. $this->networkService->hasIp($ipv4, $ipv6, $this->vmModel->node, $this->configuration()->getBridge());
  104. $this->networkService->addIp($ipv4, $ipv6, $this->vmModel->node, $this->configuration()->getBridge());
  105. $this->networkService->unassignIpAddressesAndDeleteNetwork($ipv4, $ipv6);
  106. foreach (VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))
  107. ->ofVmId($this->vmModel->id)->ofNetNull()->get() as $vmIp){
  108. $vi = new VirtualInterface();
  109. $vi->ip = $vmIp->ip;
  110. $vi->ip_long = ip2long($vmIp->ip);
  111. $vi->vm_id = $this->vmModel->id;
  112. $vi->vn_id = 0;
  113. $vi->hosting_id = $this->getWhmcsParamByKey('serviceid');
  114. $vi->save();
  115. }
  116. }
  117. //load data
  118. $this->getFormDataValues();
  119. if ($vm instanceof Kvm)
  120. {
  121. //iso
  122. if ($vm->cdrom())
  123. {
  124. $vm->updateCdrom($this->formData['iso']);
  125. }
  126. //sshkeys
  127. if($this->configuration()->isPermissionSshkeys()){
  128. if ($this->formData['sshkeys'])
  129. {
  130. $vm->updateConfig(["sshkeys" => rawurlencode($this->formData['sshkeys'])]);
  131. } else if($vm->config()['sshkeys'])
  132. {
  133. $vm->deleteConfig('sshkeys');
  134. }
  135. }
  136. }
  137. try{
  138. Api::beginTransaction();
  139. DB::beginTransaction();
  140. $this->fillVmModel();
  141. if($this->getFormDataValues()['ciuser']){
  142. $vm->updateConfig(["ciuser" => $this->formData['ciuser']]);
  143. }
  144. if($this->getFormDataValues()['cipassword']){
  145. $vm->updateConfig(["cipassword" => $this->formData['cipassword']]);
  146. }
  147. if($this->configuration()->isCalculateSocketsAndCores()){
  148. $this->calculateSocketsAndCores();
  149. }
  150. $this->vmModel->save();
  151. if($this->configuration()->isQemu()){
  152. fire(new QemuUpdateEvent($this->vmModel, $this->formData));
  153. }
  154. if($this->configuration()->isLxc()){
  155. fire(new LxcUpdateEvent($this->vmModel, $this->formData));
  156. }
  157. $agentEnabled = (new AgentService())->isEnabled();
  158. if($agentEnabled && $this->configuration()->isAgentConfigureNetwork()){
  159. queue(ConfigureNetworkJob::class,
  160. ['hostingId' => $this->getWhmcsParamByKey('serviceid')],
  161. null,
  162. "hosting",
  163. $this->getWhmcsParamByKey("serviceid"),
  164. $this->vmModel->id
  165. );
  166. }
  167. if($agentEnabled && $this->configuration()->isAgentPassword()){
  168. queue(ChangePasswordJob::class,
  169. ['hostingId' => $this->getWhmcsParamByKey('serviceid')],
  170. null,
  171. "hosting",
  172. $this->getWhmcsParamByKey("serviceid"),
  173. $this->vmModel->id
  174. );
  175. }
  176. DB::commit();
  177. return (new HtmlDataJsonResponse())
  178. ->setMessageAndTranslate('Server has been updated')
  179. ->setCallBackFunction('pcVmUpdatedAjaxDone')
  180. ->addRefreshTargetId('serviceInformationDataTable')
  181. ->setCallBackFunction('mgLocationReload');
  182. }catch (\Exception $ex){
  183. DB::rollBack();
  184. Api::commit();
  185. return (new HtmlDataJsonResponse())
  186. ->setStatusError()
  187. ->setMessageAndTranslate($ex->getMessage());
  188. }
  189. }
  190. private function virtualNetworkUpdate()
  191. {
  192. try {
  193. $viIds = [];
  194. //delete
  195. for ($i = 0; $i <= 20; $i++) {
  196. if ($this->formData['virtualInterface' . $i]) {
  197. $viIds[] = $this->formData['virtualInterface' . $i]['id'];
  198. }
  199. }
  200. $virtualInterfaces = VirtualInterface::ofHostingId($this->getWhmcsParamByKey('serviceid'))
  201. ->ofVmId($this->vmModel->id);
  202. if ($viIds) {
  203. $virtualInterfaces->notId($viIds);
  204. }
  205. $this->networkService->deleteByIpAddresses($virtualInterfaces->get());
  206. DB::commit();
  207. DB::beginTransaction();
  208. //create
  209. $newVi = [];
  210. for ($i = 1; $i <= 20; $i++) {
  211. if (!$this->formData['virtualNetwork' . $i]) {
  212. continue;
  213. }
  214. $ip = $this->formData['virtualNetwork' . $i]['ip'];
  215. $virtualNetworkId = $this->formData['virtualNetwork' . $i]['id'];
  216. //lock public ip
  217. if ($virtualNetworkId == 'public') {
  218. VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))
  219. ->ofIp($ip)
  220. ->update(['vm_id' => $this->vmModel->id]);
  221. }
  222. $vi = new VirtualInterface();
  223. $vi->ip = $ip;
  224. $vi->ip_long = ip2long($ip);
  225. $vi->vm_id = $this->vmModel->id;
  226. $vi->vn_id = $virtualNetworkId == "public" ? 0 : $virtualNetworkId;
  227. $vi->hosting_id = $this->getWhmcsParamByKey('serviceid');
  228. $vi->save();
  229. $newVi[] = $vi;
  230. $viIds[] = $vi->id;
  231. }
  232. if ($newVi) {
  233. $config = (new VirtualInterfaceConverter($newVi, \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm()))->asConfig();
  234. if(!empty($config)){
  235. \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm()->updateConfig($config);
  236. }
  237. }
  238. DB::commit();
  239. } catch (\Exception $ex) {
  240. DB::rollBack();
  241. Api::commit();
  242. throw $ex;
  243. }
  244. }
  245. private function disksUpdate()
  246. {
  247. $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
  248. $vmModel = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
  249. $additonalDiskService = $this->configuration()->isQemu() ? new AdditionalDiskService() : new AdditionalMountPointService();
  250. //Update
  251. $diskIds=[];
  252. $resizeTask = null;
  253. for ($i = 0; $i <= 20; $i++) {
  254. if ($this->formData['disks' . $i]) {
  255. $id = $this->formData['disks' . $i]['id'];
  256. $size = $this->formData['disks' . $i]['size'];
  257. $backup = $this->formData['disks' . $i]['backup'] == "on" ? null : 0;
  258. $mp = $this->formData['disks' . $i]['mp'];
  259. $hdd = $vm->getHardDiskRepostiory()->findById($id);
  260. if($resizeTask && $this->configuration()->isLxc()){
  261. for($i=0; $i<=15; $i++){
  262. if($vm->node()->task($resizeTask)->isDone()){
  263. $resizeTask = null;
  264. break;
  265. }
  266. sleep(1);
  267. }
  268. }
  269. //Backup
  270. $hdd->setBackup($backup);
  271. //mp
  272. if($hdd instanceof MountPoint){
  273. $hdd->setBackup($this->formData['disks' . $i]['backup'] == "on" ? 1 : null);
  274. $hdd->setMp($mp);
  275. }
  276. $hdd->update();
  277. //resize
  278. if ((int)$hdd->getGb() < (int)$size)
  279. {
  280. $size = "+" . abs((int)$size - (int)$hdd->getGb()) . "G";
  281. $resizeTask = $hdd->resize($size);
  282. }
  283. $diskIds[] = $id;
  284. }
  285. }
  286. //delete
  287. foreach ($vm->getHardDiskRepostiory()->fetch() as $disk){
  288. if(!$disk->isMaster() && !in_array($disk->getId() ,$diskIds)){
  289. $disk->delete();
  290. }
  291. }
  292. $vm->getHardDiskRepostiory()->deleteUnused();
  293. //Create
  294. $additonalDiskService->create($this->formData);
  295. //Update disk size
  296. $vmModel->disks = $vm->getHardDiskRepostiory()->reset()->additionalSize();
  297. $vmModel->save();
  298. }
  299. }