Selaa lähdekoodia

init mit original modulsgarden source code

root 4 vuotta sitten
commit
1bdf52d807
500 muutettua tiedostoa jossa 29725 lisäystä ja 0 poistoa
  1. 160 0
      ProxmoxCloudVps.php
  2. 14 0
      app/Config/Packages/Provisioning.php
  3. 308 0
      app/Config/Packages/WhmcsService.php
  4. 7 0
      app/Config/configuration.yml
  5. 1 0
      app/Config/cron.yml
  6. 1 0
      app/Config/di/buildWithDefaultMethod.yml
  7. 1 0
      app/Config/di/interface.yml
  8. 2 0
      app/Config/di/register.yml
  9. 9 0
      app/Config/di/rewrite.yml
  10. 0 0
      app/Config/di/services.yml
  11. 3 0
      app/Config/events.php
  12. 3 0
      app/Config/hooks.yml
  13. 7 0
      app/Config/menu/admin.yml
  14. 1 0
      app/Config/menu/client.yml
  15. 8 0
      app/Config/sidebars.yml
  16. 1 0
      app/Config/ui/admin/home/index.yml
  17. 23 0
      app/Configuration/Addon/Activate/After.php
  18. 23 0
      app/Configuration/Addon/Activate/Before.php
  19. 23 0
      app/Configuration/Addon/Config/After.php
  20. 23 0
      app/Configuration/Addon/Config/Before.php
  21. 23 0
      app/Configuration/Addon/Deactivate/After.php
  22. 23 0
      app/Configuration/Addon/Deactivate/Before.php
  23. 0 0
      app/Configuration/Addon/Others/.gitkeep
  24. 22 0
      app/Configuration/Addon/Update/After.php
  25. 22 0
      app/Configuration/Addon/Update/Before.php
  26. 29 0
      app/Configuration/Addon/Update/Patch/M2M7P0.php
  27. 31 0
      app/Cron/MainCron.php
  28. 0 0
      app/Database/data.sql
  29. 0 0
      app/Database/schema.sql
  30. 30 0
      app/Enum/ConfigurableOption.php
  31. 17 0
      app/Enum/CustomField.php
  32. 15 0
      app/Enum/JobPeriod.php
  33. 23 0
      app/Factory/VmModelFactory.php
  34. 20 0
      app/Helpers/AppParams.php
  35. 37 0
      app/Helpers/BuildUrl.php
  36. 15 0
      app/Helpers/ErrorCodesLib.php
  37. 11 0
      app/Helpers/ProxmoxAddonNotInstalledException.php
  38. 30 0
      app/Helpers/ProxmoxAddonValidator.php
  39. 67 0
      app/Helpers/UrlServiceHelper.php
  40. 40 0
      app/Hooks/AdminAreaFooterOutput.php
  41. 31 0
      app/Hooks/AdminProductConfigFieldsSave.php
  42. 57 0
      app/Hooks/ClientAreaPrimarySidebar.php
  43. 31 0
      app/Hooks/ProductDelete.php
  44. 44 0
      app/Hooks/ServiceDelete.php
  45. 62 0
      app/Http/Actions/AdminServicesTabFields.php
  46. 83 0
      app/Http/Actions/ChangePackage.php
  47. 75 0
      app/Http/Actions/ChangeUserRole.php
  48. 53 0
      app/Http/Actions/ConfigOptions.php
  49. 101 0
      app/Http/Actions/CreateAccount.php
  50. 37 0
      app/Http/Actions/MetaData.php
  51. 62 0
      app/Http/Actions/ResetBandwidth.php
  52. 100 0
      app/Http/Actions/SuspendAccount.php
  53. 114 0
      app/Http/Actions/TerminateAccount.php
  54. 69 0
      app/Http/Actions/TestConnection.php
  55. 100 0
      app/Http/Actions/UnsuspendAccount.php
  56. 49 0
      app/Http/Admin/Home.php
  57. 52 0
      app/Http/Admin/Product.php
  58. 63 0
      app/Http/Client/BaseClientController.php
  59. 143 0
      app/Http/Client/Console.php
  60. 52 0
      app/Http/Client/CustomTemplate.php
  61. 57 0
      app/Http/Client/Home.php
  62. 72 0
      app/Http/Client/SshKey.php
  63. 87 0
      app/Http/Client/Vm.php
  64. 50 0
      app/UI/AccountSummary/Providers/AccountSummaryProvider.php
  65. 22 0
      app/UI/Admin/AccountResources/AccountResourcesContainer.php
  66. 89 0
      app/UI/Admin/IpSet/Pages/IpSetDataTable.php
  67. 34 0
      app/UI/Admin/Product/Buttons/VirtualizationChangButton.php
  68. 137 0
      app/UI/Admin/Product/Forms/MainForm.php
  69. 34 0
      app/UI/Admin/Product/Forms/VirtualizationChangeForm.php
  70. 53 0
      app/UI/Admin/Product/Modals/VirtualizationChangeModal.php
  71. 482 0
      app/UI/Admin/Product/Providers/ProductProvider.php
  72. 52 0
      app/UI/Admin/Product/Sections/BackupSection.php
  73. 43 0
      app/UI/Admin/Product/Sections/ConfigurableOptionUnitSection.php
  74. 42 0
      app/UI/Admin/Product/Sections/ConsoleSection.php
  75. 73 0
      app/UI/Admin/Product/Sections/CpuPrioritySection.php
  76. 69 0
      app/UI/Admin/Product/Sections/FirewallOptionSection.php
  77. 57 0
      app/UI/Admin/Product/Sections/FirewallSection.php
  78. 54 0
      app/UI/Admin/Product/Sections/HighAvailabilityClusterSection.php
  79. 55 0
      app/UI/Admin/Product/Sections/LoadBalancerSection.php
  80. 171 0
      app/UI/Admin/Product/Sections/Lxc/ClientAreaSection.php
  81. 52 0
      app/UI/Admin/Product/Sections/Lxc/ConfigurableOptionUnitsSection.php
  82. 103 0
      app/UI/Admin/Product/Sections/Lxc/ConfigurationSection.php
  83. 91 0
      app/UI/Admin/Product/Sections/Lxc/DefaultConfigurationSection.php
  84. 67 0
      app/UI/Admin/Product/Sections/Lxc/MountPointSection.php
  85. 78 0
      app/UI/Admin/Product/Sections/Lxc/NetworkSection.php
  86. 60 0
      app/UI/Admin/Product/Sections/Lxc/ServerSection.php
  87. 44 0
      app/UI/Admin/Product/Sections/MainSection.php
  88. 66 0
      app/UI/Admin/Product/Sections/MiscellaneousSection.php
  89. 85 0
      app/UI/Admin/Product/Sections/Qemu/AdditonalDisk.php
  90. 63 0
      app/UI/Admin/Product/Sections/Qemu/AdditonalDiskSpeedSection.php
  91. 92 0
      app/UI/Admin/Product/Sections/Qemu/AdvancedSection.php
  92. 54 0
      app/UI/Admin/Product/Sections/Qemu/BootSection.php
  93. 226 0
      app/UI/Admin/Product/Sections/Qemu/ClientAreaSection.php
  94. 37 0
      app/UI/Admin/Product/Sections/Qemu/CloudInitSection.php
  95. 47 0
      app/UI/Admin/Product/Sections/Qemu/ConfigurableOptionUnitsSection.php
  96. 176 0
      app/UI/Admin/Product/Sections/Qemu/ConfigurationSection.php
  97. 89 0
      app/UI/Admin/Product/Sections/Qemu/DefaultConfigurationSection.php
  98. 79 0
      app/UI/Admin/Product/Sections/Qemu/DiskSection.php
  99. 61 0
      app/UI/Admin/Product/Sections/Qemu/DiskSpeedSection.php
  100. 34 0
      app/UI/Admin/Product/Sections/Qemu/GuestAgentSection.php
  101. 76 0
      app/UI/Admin/Product/Sections/Qemu/NetworkSection.php
  102. 65 0
      app/UI/Admin/Product/Sections/Qemu/ServerSection.php
  103. 46 0
      app/UI/Admin/Product/Sections/TwiceColumnSection.php
  104. 40 0
      app/UI/Admin/Product/Sections/UserSection.php
  105. 97 0
      app/UI/Admin/QemuGuestAgent/Pages/NetworkInterfacesDataTable.php
  106. 24 0
      app/UI/Admin/Templates/accountResources/accountResourcesContainer.tpl
  107. 25 0
      app/UI/Admin/Templates/assets/css/integration.css
  108. 134 0
      app/UI/Admin/Templates/assets/css/module_styles.css
  109. BIN
      app/UI/Admin/Templates/assets/img/buttons/backup.png
  110. BIN
      app/UI/Admin/Templates/assets/img/buttons/backupJob.png
  111. BIN
      app/UI/Admin/Templates/assets/img/buttons/disk.png
  112. BIN
      app/UI/Admin/Templates/assets/img/buttons/firewall.png
  113. BIN
      app/UI/Admin/Templates/assets/img/buttons/firewallOption.png
  114. BIN
      app/UI/Admin/Templates/assets/img/buttons/graph.png
  115. BIN
      app/UI/Admin/Templates/assets/img/buttons/network.png
  116. BIN
      app/UI/Admin/Templates/assets/img/buttons/novnc.png
  117. BIN
      app/UI/Admin/Templates/assets/img/buttons/rebootButton.png
  118. BIN
      app/UI/Admin/Templates/assets/img/buttons/reinstall.png
  119. BIN
      app/UI/Admin/Templates/assets/img/buttons/shutdownButton.png
  120. BIN
      app/UI/Admin/Templates/assets/img/buttons/snapshot.png
  121. BIN
      app/UI/Admin/Templates/assets/img/buttons/spice.png
  122. BIN
      app/UI/Admin/Templates/assets/img/buttons/startButton.png
  123. BIN
      app/UI/Admin/Templates/assets/img/buttons/stopButton.png
  124. BIN
      app/UI/Admin/Templates/assets/img/buttons/taskHistory.png
  125. BIN
      app/UI/Admin/Templates/assets/img/buttons/vnc.png
  126. BIN
      app/UI/Admin/Templates/assets/img/buttons/xtermjs.png
  127. 37 0
      app/UI/Admin/Templates/assets/js/home/index.js
  128. 45 0
      app/UI/Admin/Templates/assets/js/hooks/server.js
  129. 51 0
      app/UI/Admin/Templates/assets/js/product/index.js
  130. 113 0
      app/UI/Admin/User/Pages/UserDataTable.php
  131. 35 0
      app/UI/Backup/Buttons/CreateButton.php
  132. 36 0
      app/UI/Backup/Buttons/DeleteButton.php
  133. 36 0
      app/UI/Backup/Buttons/DeleteMassButton.php
  134. 36 0
      app/UI/Backup/Buttons/RestoreButton.php
  135. 84 0
      app/UI/Backup/Forms/CreateForm.php
  136. 52 0
      app/UI/Backup/Forms/DeleteForm.php
  137. 48 0
      app/UI/Backup/Forms/DeleteMassForm.php
  138. 51 0
      app/UI/Backup/Forms/RestoreForm.php
  139. 35 0
      app/UI/Backup/Modals/CreateModal.php
  140. 35 0
      app/UI/Backup/Modals/DeleteMassModal.php
  141. 35 0
      app/UI/Backup/Modals/DeleteModal.php
  142. 35 0
      app/UI/Backup/Modals/RestoreModal.php
  143. 100 0
      app/UI/Backup/Pages/BackupDataTable.php
  144. 119 0
      app/UI/Backup/Providers/BackupProvider.php
  145. 35 0
      app/UI/BackupJob/Buttons/CreateButton.php
  146. 36 0
      app/UI/BackupJob/Buttons/DeleteButton.php
  147. 85 0
      app/UI/BackupJob/Buttons/MailtoSwitchButton.php
  148. 35 0
      app/UI/BackupJob/Buttons/UpdateButton.php
  149. 120 0
      app/UI/BackupJob/Forms/CreateForm.php
  150. 51 0
      app/UI/BackupJob/Forms/DeleteForm.php
  151. 124 0
      app/UI/BackupJob/Forms/UpdateForm.php
  152. 35 0
      app/UI/BackupJob/Modals/CreateModal.php
  153. 35 0
      app/UI/BackupJob/Modals/DeleteModal.php
  154. 35 0
      app/UI/BackupJob/Modals/UpdateModal.php
  155. 125 0
      app/UI/BackupJob/Pages/BackupJobDataTable.php
  156. 133 0
      app/UI/BackupJob/Providers/BackupJobProvider.php
  157. 21 0
      app/UI/Client/Templates/assets/css/integration.css
  158. 157 0
      app/UI/Client/Templates/assets/css/module_styles.css
  159. BIN
      app/UI/Client/Templates/assets/img/buttons/backup.png
  160. BIN
      app/UI/Client/Templates/assets/img/buttons/backupJob.png
  161. BIN
      app/UI/Client/Templates/assets/img/buttons/disk.png
  162. BIN
      app/UI/Client/Templates/assets/img/buttons/firewall.png
  163. BIN
      app/UI/Client/Templates/assets/img/buttons/firewallOption.png
  164. BIN
      app/UI/Client/Templates/assets/img/buttons/graph.png
  165. BIN
      app/UI/Client/Templates/assets/img/buttons/network.png
  166. BIN
      app/UI/Client/Templates/assets/img/buttons/novnc.png
  167. BIN
      app/UI/Client/Templates/assets/img/buttons/rebootButton.png
  168. BIN
      app/UI/Client/Templates/assets/img/buttons/reinstall.png
  169. BIN
      app/UI/Client/Templates/assets/img/buttons/shutdownButton.png
  170. BIN
      app/UI/Client/Templates/assets/img/buttons/snapshot.png
  171. BIN
      app/UI/Client/Templates/assets/img/buttons/spice.png
  172. BIN
      app/UI/Client/Templates/assets/img/buttons/sshKey.png
  173. BIN
      app/UI/Client/Templates/assets/img/buttons/startButton.png
  174. BIN
      app/UI/Client/Templates/assets/img/buttons/stopButton.png
  175. BIN
      app/UI/Client/Templates/assets/img/buttons/taskHistory.png
  176. BIN
      app/UI/Client/Templates/assets/img/buttons/vnc.png
  177. BIN
      app/UI/Client/Templates/assets/img/buttons/xtermjs.png
  178. 54 0
      app/UI/Client/Templates/assets/js/home/index.js
  179. 190 0
      app/UI/Client/Templates/assets/js/vm/create.js
  180. 196 0
      app/UI/Client/Templates/assets/js/vm/index.js
  181. 39 0
      app/UI/CustomTemplate/Buttons/CreateButton.php
  182. 36 0
      app/UI/CustomTemplate/Buttons/DeleteButton.php
  183. 36 0
      app/UI/CustomTemplate/Buttons/UpdateButton.php
  184. 59 0
      app/UI/CustomTemplate/Forms/CreateForm.php
  185. 53 0
      app/UI/CustomTemplate/Forms/DeleteForm.php
  186. 57 0
      app/UI/CustomTemplate/Forms/UpdateForm.php
  187. 37 0
      app/UI/CustomTemplate/Modals/CreateModal.php
  188. 35 0
      app/UI/CustomTemplate/Modals/DeleteModal.php
  189. 39 0
      app/UI/CustomTemplate/Modals/UpdateModal.php
  190. 92 0
      app/UI/CustomTemplate/Pages/CustomTemplateDataTable.php
  191. 46 0
      app/UI/CustomTemplate/Providers/DeleteTemplateVmProvider.php
  192. 119 0
      app/UI/CustomTemplate/Providers/TemplateVmProvider.php
  193. 53 0
      app/UI/CustomTemplate/Providers/UpdateTemplateVmProvider.php
  194. 64 0
      app/UI/Disk/Buttons/BackupSwitchButton.php
  195. 35 0
      app/UI/Disk/Buttons/CreateButton.php
  196. 37 0
      app/UI/Disk/Buttons/DeleteButton.php
  197. 35 0
      app/UI/Disk/Buttons/UpdateButton.php
  198. 84 0
      app/UI/Disk/Forms/CreateForm.php
  199. 51 0
      app/UI/Disk/Forms/DeleteForm.php
  200. 71 0
      app/UI/Disk/Forms/UpdateForm.php
  201. 35 0
      app/UI/Disk/Modals/CreateModal.php
  202. 35 0
      app/UI/Disk/Modals/DeleteModal.php
  203. 35 0
      app/UI/Disk/Modals/UpdateModal.php
  204. 145 0
      app/UI/Disk/Pages/DiskDataTable.php
  205. 181 0
      app/UI/Disk/Providers/DiskProvider.php
  206. 84 0
      app/UI/Disk/Validators/DiskSizeValidator.php
  207. 36 0
      app/UI/Firewall/Buttons/CreateGroupButton.php
  208. 33 0
      app/UI/Firewall/Buttons/CreateRuleButton.php
  209. 36 0
      app/UI/Firewall/Buttons/DeleteButton.php
  210. 59 0
      app/UI/Firewall/Buttons/EnableSwitchButton.php
  211. 54 0
      app/UI/Firewall/Buttons/UpdateRuleButton.php
  212. 44 0
      app/UI/Firewall/Forms/CreateGroupForm.php
  213. 42 0
      app/UI/Firewall/Forms/CreateRuleForm.php
  214. 50 0
      app/UI/Firewall/Forms/DeleteForm.php
  215. 86 0
      app/UI/Firewall/Forms/GroupForm.php
  216. 206 0
      app/UI/Firewall/Forms/RuleForm.php
  217. 45 0
      app/UI/Firewall/Forms/UpdateGroupForm.php
  218. 44 0
      app/UI/Firewall/Forms/UpdateRuleForm.php
  219. 35 0
      app/UI/Firewall/Modals/CreateGroupModal.php
  220. 35 0
      app/UI/Firewall/Modals/CreateRuleModal.php
  221. 35 0
      app/UI/Firewall/Modals/DeleteModal.php
  222. 35 0
      app/UI/Firewall/Modals/UpdateGroupModal.php
  223. 35 0
      app/UI/Firewall/Modals/UpdateRuleModal.php
  224. 178 0
      app/UI/Firewall/Pages/FirewallDataTable.php
  225. 108 0
      app/UI/Firewall/Providers/FirewallProvider.php
  226. 38 0
      app/UI/FirewallOption/Buttons/UpdateButton.php
  227. 121 0
      app/UI/FirewallOption/Forms/UpdateForm.php
  228. 35 0
      app/UI/FirewallOption/Modals/UpdateModal.php
  229. 84 0
      app/UI/FirewallOption/Pages/FirewallOption.php
  230. 83 0
      app/UI/FirewallOption/Providers/FirewallOptionProvider.php
  231. 5 0
      app/UI/FirewallOption/Templates/pages/firewallOption.tpl
  232. 69 0
      app/UI/FirewallOption/Templates/pages/firewallOption_components.js
  233. 50 0
      app/UI/FirewallOption/Templates/pages/firewallOption_components.tpl
  234. 40 0
      app/UI/Graph/Pages/BaseSmallGraph.php
  235. 109 0
      app/UI/Graph/Pages/CpuGraph.php
  236. 90 0
      app/UI/Graph/Pages/CpuSmallGraph.php
  237. 117 0
      app/UI/Graph/Pages/DiskGraph.php
  238. 99 0
      app/UI/Graph/Pages/DiskSmallGraph.php
  239. 96 0
      app/UI/Graph/Pages/GraphData.php
  240. 112 0
      app/UI/Graph/Pages/MemoryGraph.php
  241. 98 0
      app/UI/Graph/Pages/MemorySmallGraph.php
  242. 117 0
      app/UI/Graph/Pages/NetworkGraph.php
  243. 99 0
      app/UI/Graph/Pages/NetworkSmallGraph.php
  244. 12 0
      app/UI/Home/Buttons/AbstractActionButton.php
  245. 42 0
      app/UI/Home/Buttons/DeleteVmButton.php
  246. 42 0
      app/UI/Home/Buttons/RebootButton.php
  247. 80 0
      app/UI/Home/Buttons/RedirectButton.php
  248. 42 0
      app/UI/Home/Buttons/ShutdownButton.php
  249. 27 0
      app/UI/Home/Buttons/SshKeyButton.php
  250. 42 0
      app/UI/Home/Buttons/StartButton.php
  251. 42 0
      app/UI/Home/Buttons/StopButton.php
  252. 42 0
      app/UI/Home/Forms/DeleteVmForm.php
  253. 42 0
      app/UI/Home/Forms/RebootForm.php
  254. 42 0
      app/UI/Home/Forms/ShutdownForm.php
  255. 29 0
      app/UI/Home/Forms/SshKeyForm.php
  256. 42 0
      app/UI/Home/Forms/StartForm.php
  257. 42 0
      app/UI/Home/Forms/StopForm.php
  258. 37 0
      app/UI/Home/Modals/DeleteVmModal.php
  259. 36 0
      app/UI/Home/Modals/RebootModal.php
  260. 36 0
      app/UI/Home/Modals/ShutdownModal.php
  261. 52 0
      app/UI/Home/Modals/SshKeyModal.php
  262. 36 0
      app/UI/Home/Modals/StartModal.php
  263. 36 0
      app/UI/Home/Modals/StopModal.php
  264. 34 0
      app/UI/Home/Pages/AccountSummary.php
  265. 25 0
      app/UI/Home/Pages/ErrorContainer.php
  266. 122 0
      app/UI/Home/Pages/ServiceActions.php
  267. 52 0
      app/UI/Home/Pages/ServiceDetails.php
  268. 107 0
      app/UI/Home/Pages/ServiceManagement.php
  269. 69 0
      app/UI/Home/Pages/VmBuild.php
  270. 22 0
      app/UI/Home/Providers/SshKeyProvider.php
  271. 121 0
      app/UI/Home/Providers/StatusProvider.php
  272. 31 0
      app/UI/Home/Templates/pages/accountSummary.tpl
  273. 5 0
      app/UI/Home/Templates/pages/errorContainer.tpl
  274. 15 0
      app/UI/Home/Templates/pages/manageService.tpl
  275. 37 0
      app/UI/Home/Templates/pages/serviceActions.tpl
  276. 15 0
      app/UI/Home/Templates/pages/serviceDetails.tpl
  277. 17 0
      app/UI/Home/Templates/pages/serviceManagement.tpl
  278. 5 0
      app/UI/Home/Templates/pages/vmBuild.tpl
  279. 35 0
      app/UI/IpAddress/Buttons/CreateButton.php
  280. 37 0
      app/UI/IpAddress/Buttons/DeleteButton.php
  281. 73 0
      app/UI/IpAddress/Forms/CreateForm.php
  282. 53 0
      app/UI/IpAddress/Forms/DeleteForm.php
  283. 35 0
      app/UI/IpAddress/Modals/CreateModal.php
  284. 35 0
      app/UI/IpAddress/Modals/DeleteModal.php
  285. 109 0
      app/UI/IpAddress/Pages/IpAddressDataTable.php
  286. 135 0
      app/UI/IpAddress/Providers/IpAddressProvider.php
  287. 66 0
      app/UI/MountPoint/Buttons/BackupSwitchButton.php
  288. 35 0
      app/UI/MountPoint/Buttons/CreateButton.php
  289. 37 0
      app/UI/MountPoint/Buttons/DeleteButton.php
  290. 35 0
      app/UI/MountPoint/Buttons/UpdateButton.php
  291. 70 0
      app/UI/MountPoint/Forms/CreateForm.php
  292. 51 0
      app/UI/MountPoint/Forms/DeleteForm.php
  293. 66 0
      app/UI/MountPoint/Forms/UpdateForm.php
  294. 35 0
      app/UI/MountPoint/Modals/CreateModal.php
  295. 35 0
      app/UI/MountPoint/Modals/DeleteModal.php
  296. 35 0
      app/UI/MountPoint/Modals/UpdateModal.php
  297. 134 0
      app/UI/MountPoint/Pages/MountPointDataTable.php
  298. 160 0
      app/UI/MountPoint/Providers/MountPointProvider.php
  299. 81 0
      app/UI/MountPoint/Validators/DiskSizeValidator.php
  300. 37 0
      app/UI/Network/Buttons/CreateButton.php
  301. 42 0
      app/UI/Network/Buttons/DeleteButton.php
  302. 38 0
      app/UI/Network/Buttons/InfoButton.php
  303. 53 0
      app/UI/Network/Forms/CreateForm.php
  304. 52 0
      app/UI/Network/Forms/DeleteForm.php
  305. 38 0
      app/UI/Network/Modals/CreateModal.php
  306. 37 0
      app/UI/Network/Modals/DeleteModal.php
  307. 68 0
      app/UI/Network/Modals/InfoModal.php
  308. 155 0
      app/UI/Network/Pages/NetworkLxcDataTable.php
  309. 158 0
      app/UI/Network/Pages/NetworkQemuDataTable.php
  310. 53 0
      app/UI/Network/Pages/NetworkTab.php
  311. 124 0
      app/UI/Network/Providers/NetworkProvider.php
  312. 142 0
      app/UI/Network/Templates/modals/infoModal.tpl
  313. 38 0
      app/UI/Reinstall/Buttons/IsoInstallButton.php
  314. 38 0
      app/UI/Reinstall/Buttons/TemplateInstallButton.php
  315. 57 0
      app/UI/Reinstall/Forms/IsoInstallForm.php
  316. 70 0
      app/UI/Reinstall/Forms/TemplateInstallForm.php
  317. 35 0
      app/UI/Reinstall/Modals/IsoInstallModal.php
  318. 36 0
      app/UI/Reinstall/Modals/TemplateInstallModal.php
  319. 47 0
      app/UI/Reinstall/Pages/GraphsTab.php
  320. 42 0
      app/UI/Reinstall/Pages/IsoDataTable.php
  321. 38 0
      app/UI/Reinstall/Pages/IsoRawDataTable.php
  322. 72 0
      app/UI/Reinstall/Pages/IsoTrait.php
  323. 42 0
      app/UI/Reinstall/Pages/ReinstallTab.php
  324. 40 0
      app/UI/Reinstall/Pages/TemplateDataTable.php
  325. 19 0
      app/UI/Reinstall/Pages/TemplateRawDataTable.php
  326. 116 0
      app/UI/Reinstall/Pages/TemplateTrait.php
  327. 174 0
      app/UI/Reinstall/Providers/IsoInstallProvider.php
  328. 152 0
      app/UI/Reinstall/Providers/TemplateInstallProvider.php
  329. 36 0
      app/UI/ServiceGraph/Pages/BaseGraph.php
  330. 100 0
      app/UI/ServiceGraph/Pages/ServiceCpuGraph.php
  331. 102 0
      app/UI/ServiceGraph/Pages/ServiceDiskGraph.php
  332. 18 0
      app/UI/ServiceGraph/Pages/ServiceGraphs.php
  333. 101 0
      app/UI/ServiceGraph/Pages/ServiceMemoryGraph.php
  334. 102 0
      app/UI/ServiceGraph/Pages/ServiceNetworkGraph.php
  335. 39 0
      app/UI/ServiceInformation/Buttons/SshPrivateKeyDownloadButton.php
  336. 37 0
      app/UI/ServiceInformation/Buttons/UpdateButton.php
  337. 35 0
      app/UI/ServiceInformation/Forms/SshPublicKeyDownloadForm.php
  338. 90 0
      app/UI/ServiceInformation/Forms/UpdateForm.php
  339. 62 0
      app/UI/ServiceInformation/Modals/SshPublicKeyDownloadModal.php
  340. 37 0
      app/UI/ServiceInformation/Modals/UpdateModal.php
  341. 209 0
      app/UI/ServiceInformation/Pages/ServiceInformation.php
  342. 143 0
      app/UI/ServiceInformation/Providers/UpdateProvider.php
  343. 5 0
      app/UI/ServiceInformation/Templates/pages/serviceInformation.tpl
  344. 66 0
      app/UI/ServiceInformation/Templates/pages/serviceInformation_components.js
  345. 46 0
      app/UI/ServiceInformation/Templates/pages/serviceInformation_components.tpl
  346. 35 0
      app/UI/Snapshot/Buttons/CreateButton.php
  347. 35 0
      app/UI/Snapshot/Buttons/CreateJobButton.php
  348. 36 0
      app/UI/Snapshot/Buttons/DeleteButton.php
  349. 36 0
      app/UI/Snapshot/Buttons/DeleteJobButton.php
  350. 36 0
      app/UI/Snapshot/Buttons/DeleteJobMassButton.php
  351. 36 0
      app/UI/Snapshot/Buttons/DeleteMassButton.php
  352. 36 0
      app/UI/Snapshot/Buttons/RollbackButton.php
  353. 35 0
      app/UI/Snapshot/Buttons/UpdateButton.php
  354. 35 0
      app/UI/Snapshot/Buttons/UpdateJobButton.php
  355. 74 0
      app/UI/Snapshot/Forms/CreateForm.php
  356. 50 0
      app/UI/Snapshot/Forms/CreateJobForm.php
  357. 50 0
      app/UI/Snapshot/Forms/DeleteForm.php
  358. 51 0
      app/UI/Snapshot/Forms/DeleteJobForm.php
  359. 49 0
      app/UI/Snapshot/Forms/DeleteJobMassForm.php
  360. 49 0
      app/UI/Snapshot/Forms/DeleteMassForm.php
  361. 103 0
      app/UI/Snapshot/Forms/JobForm.php
  362. 49 0
      app/UI/Snapshot/Forms/RollbackForm.php
  363. 54 0
      app/UI/Snapshot/Forms/UpdateForm.php
  364. 50 0
      app/UI/Snapshot/Forms/UpdateJobForm.php
  365. 35 0
      app/UI/Snapshot/Modals/CreateJobModal.php
  366. 35 0
      app/UI/Snapshot/Modals/CreateModal.php
  367. 35 0
      app/UI/Snapshot/Modals/DeleteJobMassModal.php
  368. 35 0
      app/UI/Snapshot/Modals/DeleteJobModal.php
  369. 35 0
      app/UI/Snapshot/Modals/DeleteMassModal.php
  370. 35 0
      app/UI/Snapshot/Modals/DeleteModal.php
  371. 35 0
      app/UI/Snapshot/Modals/RollbackModal.php
  372. 35 0
      app/UI/Snapshot/Modals/UpdateJobModal.php
  373. 35 0
      app/UI/Snapshot/Modals/UpdateModal.php
  374. 128 0
      app/UI/Snapshot/Pages/JobRawDataTable.php
  375. 34 0
      app/UI/Snapshot/Pages/SnapshotDataTable.php
  376. 19 0
      app/UI/Snapshot/Pages/SnapshotRawDataTable.php
  377. 39 0
      app/UI/Snapshot/Pages/SnapshotTab.php
  378. 120 0
      app/UI/Snapshot/Pages/SnapshotTrait.php
  379. 121 0
      app/UI/Snapshot/Providers/JobProvider.php
  380. 142 0
      app/UI/Snapshot/Providers/SnapshotProvider.php
  381. 37 0
      app/UI/TaskHistory/Buttons/InfoButton.php
  382. 50 0
      app/UI/TaskHistory/Forms/InfoForm.php
  383. 45 0
      app/UI/TaskHistory/Modals/InfoModal.php
  384. 119 0
      app/UI/TaskHistory/Pages/TaskHistoryDataTable.php
  385. 45 0
      app/UI/TaskHistory/Providers/TaskHistoryProvider.php
  386. 76 0
      app/UI/Validators/CidrValidator.php
  387. 89 0
      app/UI/Validators/CpulimitValidator.php
  388. 53 0
      app/UI/Validators/HostnameValidator.php
  389. 66 0
      app/UI/Validators/IpAddressValidator.php
  390. 94 0
      app/UI/Validators/NumberValidator.php
  391. 59 0
      app/UI/Validators/PasswordValidator.php
  392. 90 0
      app/UI/Validators/PortValidator.php
  393. 57 0
      app/UI/Validators/SnapshotValidator.php
  394. 57 0
      app/UI/Validators/SshPublicKeyValidator.php
  395. 57 0
      app/UI/Validators/StartTimeValidator.php
  396. 66 0
      app/UI/Validators/VirtualIpAddressValidator.php
  397. 35 0
      app/UI/VirtualInterface/Buttons/CreateButton.php
  398. 40 0
      app/UI/VirtualInterface/Buttons/DeleteButton.php
  399. 49 0
      app/UI/VirtualInterface/Fields/IpSelect.php
  400. 37 0
      app/UI/VirtualInterface/Fields/NetworkSelect.php
  401. 62 0
      app/UI/VirtualInterface/Forms/CreateForm.php
  402. 51 0
      app/UI/VirtualInterface/Forms/DeleteForm.php
  403. 35 0
      app/UI/VirtualInterface/Modals/CreateModal.php
  404. 35 0
      app/UI/VirtualInterface/Modals/DeleteModal.php
  405. 98 0
      app/UI/VirtualInterface/Pages/VirtualInterfaceDataTable.php
  406. 165 0
      app/UI/VirtualInterface/Providers/VirtualInterfaceProvider.php
  407. 35 0
      app/UI/VirtualNetwork/Buttons/CreateButton.php
  408. 39 0
      app/UI/VirtualNetwork/Buttons/DeleteButton.php
  409. 36 0
      app/UI/VirtualNetwork/Buttons/UpdateButton.php
  410. 69 0
      app/UI/VirtualNetwork/Forms/CreateForm.php
  411. 51 0
      app/UI/VirtualNetwork/Forms/DeleteForm.php
  412. 55 0
      app/UI/VirtualNetwork/Forms/UpdateForm.php
  413. 35 0
      app/UI/VirtualNetwork/Modals/CreateModal.php
  414. 35 0
      app/UI/VirtualNetwork/Modals/DeleteModal.php
  415. 41 0
      app/UI/VirtualNetwork/Modals/UpdateModal.php
  416. 92 0
      app/UI/VirtualNetwork/Pages/VirtualNetworkDataTable.php
  417. 119 0
      app/UI/VirtualNetwork/Providers/VirtualNetworkProvider.php
  418. 30 0
      app/UI/Vm/Pages/BackupTab.php
  419. 23 0
      app/UI/Vm/Pages/DetailTab.php
  420. 31 0
      app/UI/Vm/Pages/FirewallTab.php
  421. 96 0
      app/UI/Vm/Pages/VmTabs.php
  422. 3 0
      app/UI/Vm/Templates/pages/detailTab.tpl
  423. 50 0
      app/UI/VmCreate/Fields/IsoImageSelect.php
  424. 125 0
      app/UI/VmCreate/Fields/OsTemplateSelect.php
  425. 50 0
      app/UI/VmCreate/Fields/SecondaryIsoImageSelect.php
  426. 53 0
      app/UI/VmCreate/Forms/VmCreateForm.php
  427. 343 0
      app/UI/VmCreate/Providers/VmCreateProvider.php
  428. 34 0
      app/UI/VmCreate/Sections/AccountSummary.php
  429. 76 0
      app/UI/VmCreate/Sections/AdditionalDiskSection.php
  430. 173 0
      app/UI/VmCreate/Sections/Lxc/GeneralSection.php
  431. 223 0
      app/UI/VmCreate/Sections/Qemu/GeneralSection.php
  432. 44 0
      app/UI/VmCreate/Sections/TopSection.php
  433. 66 0
      app/UI/VmCreate/Sections/VirtualNetworkSection.php
  434. 28 0
      app/UI/VmCreate/Templates/sections/accountSummary.tpl
  435. 70 0
      app/UI/VmCreate/Templates/sections/additionalDiskSection.tpl
  436. 43 0
      app/UI/VmCreate/Templates/sections/lxc/generalSection.tpl
  437. 43 0
      app/UI/VmCreate/Templates/sections/qemu/generalSection.tpl
  438. 58 0
      app/UI/VmCreate/Templates/sections/topSection.tpl
  439. 81 0
      app/UI/VmCreate/Templates/sections/virtualNetworkSection.tpl
  440. 84 0
      app/UI/VmCreate/Validators/DiskSizeValidator.php
  441. 31 0
      app/UI/VmCreate/Validators/IsoImageValidator.php
  442. 42 0
      app/UI/VmCreate/Validators/NameserverValidator.php
  443. 62 0
      app/UI/VmCreate/Validators/PasswordValidator.php
  444. 28 0
      app/UI/VmCreate/Validators/SearchdomainValidator.php
  445. 60 0
      app/UI/VmCreate/Validators/SshPublicKeyValidator.php
  446. 31 0
      app/UI/VmCreate/Validators/UserValidator.php
  447. 62 0
      app/UI/VmUpdate/Forms/VmUpdateForm.php
  448. 368 0
      app/UI/VmUpdate/Providers/VmUpdateProvider.php
  449. 95 0
      app/UI/VmUpdate/Sections/Lxc/AdditionalDiskSection.php
  450. 23 0
      app/UI/VmUpdate/Sections/Lxc/GeneralCombinedSection.php
  451. 150 0
      app/UI/VmUpdate/Sections/Lxc/GeneralSection.php
  452. 95 0
      app/UI/VmUpdate/Sections/Qemu/AdditionalDiskSection.php
  453. 27 0
      app/UI/VmUpdate/Sections/Qemu/GeneralCombinedSection.php
  454. 181 0
      app/UI/VmUpdate/Sections/Qemu/GeneralSection.php
  455. 75 0
      app/UI/VmUpdate/Sections/VirtualNetworkSection.php
  456. 123 0
      app/UI/VmUpdate/Templates/sections/lxc/additionalDiskSection.tpl
  457. 43 0
      app/UI/VmUpdate/Templates/sections/lxc/generalCombinedSection.tpl
  458. 107 0
      app/UI/VmUpdate/Templates/sections/qemu/additionalDiskSection.tpl
  459. 44 0
      app/UI/VmUpdate/Templates/sections/qemu/generalCombinedSection.tpl
  460. 122 0
      app/UI/VmUpdate/Templates/sections/virtualNetworkSection.tpl
  461. 40 0
      app/UI/Vms/Buttons/DeleteButton.php
  462. 107 0
      app/UI/Vms/Buttons/EditButton.php
  463. 38 0
      app/UI/Vms/Buttons/ImportButton.php
  464. 38 0
      app/UI/Vms/Buttons/MigrateButton.php
  465. 53 0
      app/UI/Vms/Forms/DeleteForm.php
  466. 61 0
      app/UI/Vms/Forms/ImportForm.php
  467. 59 0
      app/UI/Vms/Forms/MigrateForm.php
  468. 35 0
      app/UI/Vms/Modals/DeleteModal.php
  469. 37 0
      app/UI/Vms/Modals/ImportModal.php
  470. 36 0
      app/UI/Vms/Modals/MigrateModal.php
  471. 161 0
      app/UI/Vms/Pages/VmsDataTable.php
  472. 43 0
      app/UI/Vms/Providers/DeleteVmProvider.php
  473. 89 0
      app/UI/Vms/Providers/ImportVmProvider.php
  474. 99 0
      app/UI/Vms/Providers/MigrateProvider.php
  475. 20 0
      commands/commands.php
  476. 41 0
      composer.json
  477. 25 0
      core/Api/AbstractApi.php
  478. 158 0
      core/Api/AbstractApi/Curl.php
  479. 193 0
      core/Api/AbstractApi/Curl/Request.php
  480. 92 0
      core/Api/AbstractApi/Curl/Response.php
  481. 22 0
      core/Api/AbstractApi/Parser.php
  482. 186 0
      core/Api/Http.php
  483. 90 0
      core/Api/Whmcs.php
  484. 172 0
      core/App/AppContext.php
  485. 53 0
      core/App/AppParamsContainer.php
  486. 94 0
      core/App/Application.php
  487. 19 0
      core/App/Controllers/AppController.php
  488. 36 0
      core/App/Controllers/AppControllers/Addon.php
  489. 13 0
      core/App/Controllers/AppControllers/Api.php
  490. 13 0
      core/App/Controllers/AppControllers/Cron.php
  491. 13 0
      core/App/Controllers/AppControllers/Hooks.php
  492. 34 0
      core/App/Controllers/AppControllers/Http.php
  493. 71 0
      core/App/Controllers/Instances/Addon/Activate.php
  494. 149 0
      core/App/Controllers/Instances/Addon/Config.php
  495. 319 0
      core/App/Controllers/Instances/Addon/ConfigOptions.php
  496. 44 0
      core/App/Controllers/Instances/Addon/Deactivate.php
  497. 48 0
      core/App/Controllers/Instances/Addon/Upgrade.php
  498. 119 0
      core/App/Controllers/Instances/AddonController.php
  499. 11 0
      core/App/Controllers/Instances/Api/ApiController.php
  500. 40 0
      core/App/Controllers/Instances/Http/AddonIntegration.php

+ 160 - 0
ProxmoxCloudVps.php

@@ -0,0 +1,160 @@
+<?php
+
+use Illuminate\Database\Capsule\Manager as DB;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\AppContext;
+
+if (!defined("WHMCS"))
+{
+    die("This file cannot be accessed directly");
+}
+
+if (!defined('DS'))
+{
+    define('DS', DIRECTORY_SEPARATOR);
+}
+
+require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'WhmcsErrorIntegration.php';
+
+
+
+
+
+function ProxmoxCloudVps_CreateAccount(array $params)
+{
+    require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
+    
+    
+    
+    $appContext = new AppContext();
+    return $appContext->runApp(__FUNCTION__, $params);
+}
+
+function ProxmoxCloudVps_SuspendAccount(array $params)
+{
+    require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
+    
+    
+    
+    $appContext = new AppContext();    
+    
+    return $appContext->runApp(__FUNCTION__, $params);
+}
+
+function ProxmoxCloudVps_UnsuspendAccount(array $params)
+{
+    require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
+    
+    
+    
+    $appContext = new AppContext();    
+    
+    return $appContext->runApp(__FUNCTION__, $params);
+}
+
+function ProxmoxCloudVps_TerminateAccount(array $params)
+{
+    require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
+    
+    
+    
+    $appContext = new AppContext();    
+    
+    return $appContext->runApp(__FUNCTION__, $params);
+}
+
+
+function ProxmoxCloudVps_ChangePackage(array $params)
+{
+    require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
+    
+    
+    
+    $appContext = new AppContext();    
+    
+    return $appContext->runApp(__FUNCTION__, $params);
+}
+
+function ProxmoxCloudVps_TestConnection(array $params)
+{
+    require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
+    
+    $appContext = new AppContext();
+    return $appContext->runApp(__FUNCTION__, $params);
+}
+
+function ProxmoxCloudVps_UsageUpdate(array $params)
+{
+
+}
+
+function ProxmoxCloudVps_ConfigOptions(array $params)
+{
+    require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
+    
+    $appContext = new AppContext();    
+    
+    return $appContext->runApp(__FUNCTION__, $params);
+}
+
+function ProxmoxCloudVps_MetaData()
+{
+    require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
+    
+    $appContext = new AppContext();    
+    
+   return $appContext->runApp(__FUNCTION__, []);
+}
+
+/**
+ * FUNCTION ProxmoxCloudVps_AdminCustomButtonArray
+ * This function can be used to define custom functions.
+ * @param type $params
+ * @return string
+ */
+function ProxmoxCloudVps_AdminCustomButtonArray($params) {
+    $buttons = array(
+        "Change User Role" => "ChangeUserRole",
+        "Reset Bandwidth" => "ResetBandwidth",
+    );
+    return $buttons;
+}
+
+function ProxmoxCloudVps_ChangeUserRole($params)
+{
+    require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
+    $appContext = new AppContext();
+    return $appContext->runApp(__FUNCTION__, $params);
+}
+
+function ProxmoxCloudVps_ResetBandwidth($params)
+{
+    require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
+    $appContext = new AppContext();
+    return $appContext->runApp(__FUNCTION__, $params);
+}
+
+function ProxmoxCloudVps_AdminServicesTabFields($params)
+{
+    require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
+    $appContext = new AppContext();
+    return $appContext->runApp(__FUNCTION__, $params);
+}
+
+
+
+function ProxmoxCloudVps_ClientArea($params)
+{
+    if($params['status']!='Active'){
+        return;
+    }
+
+
+    require_once __DIR__ . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATOR . 'App' . DIRECTORY_SEPARATOR . 'AppContext.php';
+
+    
+
+    $appContext = new AppContext();
+
+    return $appContext->runApp('clientarea', $params);
+}
+

+ 14 - 0
app/Config/Packages/Provisioning.php

@@ -0,0 +1,14 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Config\Packages;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Packages\AppPackageConfiguration;
+
+class Provisioning extends AppPackageConfiguration
+{
+    const APP_CONFIGURATION =
+        [
+            self::PACKAGE_STATUS => self::PACKAGE_STATUS_ACTIVE
+        ];
+}

+ 308 - 0
app/Config/Packages/WhmcsService.php

@@ -0,0 +1,308 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Config\Packages;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
+use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\CustomField;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Libs\AwsIntegration\ClientWrapper;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Models\AvailableImages\Repository;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\ProductConfig\Providers\Config;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Packages\AppPackageConfiguration;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\RequestObjectHandler;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\Packages\WhmcsService\Config\Enum;
+
+class WhmcsService extends AppPackageConfiguration
+{
+    use RequestObjectHandler;
+    use WhmcsParams;
+    use ProductService;
+    use ApiService;
+
+    const APP_CONFIGURATION =
+        [
+            self::PACKAGE_STATUS => self::PACKAGE_STATUS_ACTIVE,
+
+            Enum::CUSTOM_FIELDS => [
+                [
+                    Enum::FIELD_NAME       => 'VLAN Tag|VLAN Tag',
+                    Enum::FIELD_TYPE       => Enum::FIELD_TYPE_TEXT_BOX,
+                    Enum::FIELD_ADMIN_ONLY => Enum::FIELD_ADMIN_ONLY_ON
+                ],
+                [
+                    Enum::FIELD_NAME       => 'Authentication|Authentication',
+                    Enum::FIELD_TYPE       => Enum::FIELD_TYPE_TEXT_BOX,
+                    Enum::FIELD_ADMIN_ONLY => Enum::FIELD_ADMIN_ONLY_ON
+                ],
+                [
+                    Enum::FIELD_NAME       => CustomField::ADVANCED_USER.'|Advanced User',
+                    Enum::FIELD_TYPE       => Enum::FIELD_TYPE_TICK_BOX,
+                    Enum::FIELD_ADMIN_ONLY => Enum::FIELD_ADMIN_ONLY_ON,
+                    Enum::FIELD_RELATION_TYPE => Enum::FIELD_RELATION_TYPE_CLIENT
+                ],
+            ],
+        ];
+
+
+    public function networkRateGetSubOptions()
+    {
+        return [
+            [
+                Enum::OPTION_SUB_NAME  => "0|Unlimited",
+                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+            ],
+            [
+                Enum::OPTION_SUB_NAME  => '5|5 (MB/s) (' . (5 * 8) . ' Mbps)',
+                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+            ],
+            [
+                Enum::OPTION_SUB_NAME  => '10|10 (MB/s) (' . (10 * 8) . ' Mbps)',
+                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+            ],
+            [
+                Enum::OPTION_SUB_NAME  => '20|20 (MB/s) (' . (20 * 8) . ' Mbps)',
+                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+            ],
+            [
+                Enum::OPTION_SUB_NAME  => '30|30 (MB/s) (' . (30 * 8) . ' Mbps)',
+                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+            ],
+            [
+                Enum::OPTION_SUB_NAME  => '40|40 (MB/s) (' . (40 * 8) . ' Mbps)',
+                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+            ],
+            [
+                Enum::OPTION_SUB_NAME  => '50|50 (MB/s) (' . (50 * 8) . ' Mbps)',
+                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+            ],
+        ];
+    }
+
+    public function getConfigurableOptions()
+    {
+        $configOptions = [];
+        if ($this->configuration()->isQemu())
+        {
+            $configOptions[] = [
+                Enum::OPTION_NAME         => ConfigurableOption::SOCKETS.'|CPU Sockets',
+                Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+                Enum::OPTION_QUANTITY_MIN => 1,
+                Enum::OPTION_QUANTITY_MAX => 100,
+                Enum::CONFIG_SUB_OPTIONS  => [
+                    [
+                        Enum::OPTION_SUB_NAME  => 'Unit|Unit',
+                        Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                    ]
+                ]
+            ];
+            $configOptions[] = [
+                Enum::OPTION_NAME         => ConfigurableOption::CORES.'|CPU Cores',
+                Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+                Enum::OPTION_QUANTITY_MIN => 1,
+                Enum::OPTION_QUANTITY_MAX => 10,
+                Enum::CONFIG_SUB_OPTIONS  => [
+                    [
+                        Enum::OPTION_SUB_NAME  => 'Unit|Unit',
+                        Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                    ]
+                ]
+            ];
+        }
+        $configOptions[] = [
+            Enum::OPTION_NAME         =>  ConfigurableOption::CPU_LIMIT.'|CPU Limit',
+            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+            Enum::OPTION_QUANTITY_MIN => 0,
+            Enum::OPTION_QUANTITY_MAX => 100,
+            Enum::CONFIG_SUB_OPTIONS  => [
+                [
+                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
+                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                ]
+            ]
+        ];
+        $configOptions[] = [
+            Enum::OPTION_NAME         => ConfigurableOption::CPU_UNITS.'|CPU Weight Limit',
+            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+            Enum::OPTION_QUANTITY_MIN => 1024,
+            Enum::OPTION_QUANTITY_MAX => 99999,
+            Enum::CONFIG_SUB_OPTIONS  => [
+                [
+                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
+                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                ]
+            ]
+        ];
+        $unit            = strtoupper($this->configuration()->getMemoryUnit());
+        $min             = 128;
+        $max             = 1024 * 10;
+        if ($this->configuration()->getMemoryUnit() == 'gb')
+        {
+            $min = 1;
+            $max = 10;
+        }
+        $configOptions[] = [
+            Enum::OPTION_NAME         => ConfigurableOption::MEMORY.'|Memory',
+            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+            Enum::OPTION_QUANTITY_MIN => $min,
+            Enum::OPTION_QUANTITY_MAX => $max,
+            Enum::CONFIG_SUB_OPTIONS  => [
+                [
+                    Enum::OPTION_SUB_NAME  => "{$unit}|{$unit}",
+                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                ]
+            ]
+        ];
+        if ($this->configuration()->isLxc())
+        {
+            $unit = strtoupper($this->configuration()->getSwapUnit());
+            $min  = 128;
+            $max  = 1024 * 10;
+            if ($this->configuration()->getSwapUnit() == 'gb')
+            {
+                $min = 1;
+                $max = 10;
+            }
+            $configOptions[] = [
+                Enum::OPTION_NAME         => ConfigurableOption::SWAP.'|SWAP',
+                Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+                Enum::OPTION_QUANTITY_MIN => $min,
+                Enum::OPTION_QUANTITY_MAX => $max,
+                Enum::CONFIG_SUB_OPTIONS  => [
+                    [
+                        Enum::OPTION_SUB_NAME  => "{$unit}|{$unit}",
+                        Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                    ]
+                ]
+            ];
+        }
+        $unit = strtoupper($this->configuration()->getStorageUnit());
+        $min  = 128;
+        $max  = 1024 * 1000;
+        if ($this->configuration()->getStorageUnit() == 'gb' || $this->configuration()->getStorageUnit() == 'tb')
+        {
+            $min = 1;
+            $max = 1000;
+        }
+        $configOptions[] = [
+            Enum::OPTION_NAME         => ConfigurableOption::STORAGE.'|Storage',
+            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+            Enum::OPTION_QUANTITY_MIN => $min,
+            Enum::OPTION_QUANTITY_MAX => $max,
+            Enum::CONFIG_SUB_OPTIONS  => [
+                [
+                    Enum::OPTION_SUB_NAME  => "{$unit}|{$unit}",
+                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                ]
+            ]
+        ];
+        $configOptions[] = [
+            Enum::OPTION_NAME         => ConfigurableOption::IPV4.'|IPv4 Addresses',
+            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+            Enum::OPTION_QUANTITY_MIN => 0,
+            Enum::OPTION_QUANTITY_MAX => 100,
+            Enum::CONFIG_SUB_OPTIONS  => [
+                [
+                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
+                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                ]
+            ]
+        ];
+        $configOptions[] = [
+            Enum::OPTION_NAME         => ConfigurableOption::IPV6.'|IPv6 Addresses',
+            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+            Enum::OPTION_QUANTITY_MIN => 0,
+            Enum::OPTION_QUANTITY_MAX => 100,
+            Enum::CONFIG_SUB_OPTIONS  => [
+                [
+                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
+                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                ]
+            ]
+        ];
+        $configOptions[] = [
+            Enum::OPTION_NAME         =>  ConfigurableOption::BACKUPS_SIZE.'|Backups Size',
+            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+            Enum::OPTION_QUANTITY_MIN => 0,
+            Enum::OPTION_QUANTITY_MAX => 10 * 100,
+            Enum::CONFIG_SUB_OPTIONS  => [
+                [
+                    Enum::OPTION_SUB_NAME  => 'GB|GB',
+                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                ]
+            ]
+        ];
+        $configOptions[] = [
+            Enum::OPTION_NAME         =>  ConfigurableOption::BACKUPS_FILES.'|Backups Files Limit',
+            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+            Enum::OPTION_QUANTITY_MIN => 0,
+            Enum::OPTION_QUANTITY_MAX => 100,
+            Enum::CONFIG_SUB_OPTIONS  => [
+                [
+                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
+                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                ]
+            ]
+        ];
+        $configOptions[] = [
+            Enum::OPTION_NAME         =>  ConfigurableOption::SNAPSHOTS.'|Snapshots',
+            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+            Enum::OPTION_QUANTITY_MIN => 0,
+            Enum::OPTION_QUANTITY_MAX => 100,
+            Enum::CONFIG_SUB_OPTIONS  => [
+                [
+                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
+                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                ]
+            ]
+        ];
+        $configOptions[] = [
+            Enum::OPTION_NAME         => ConfigurableOption::BANDWIDTH.'|Bandwidth',
+            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+            Enum::OPTION_QUANTITY_MIN => 0,
+            Enum::OPTION_QUANTITY_MAX => 10 * 100,
+            Enum::CONFIG_SUB_OPTIONS  => [
+                [
+                    Enum::OPTION_SUB_NAME  => 'GB|GB',
+                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                ]
+            ]
+        ];
+        $configOptions[] = [
+            Enum::OPTION_NAME => ConfigurableOption::NETWORK_RATE.'|Network Rate',
+            Enum::OPTION_TYPE => Enum::OPTION_TYPE_DROPDOWN,
+        ];
+
+        if ($this->configuration()->isQemu())
+        {
+            $configOptions[] = [
+                Enum::OPTION_NAME         => ConfigurableOption::VCPUS.'|VCPUs',
+                Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+                Enum::OPTION_QUANTITY_MIN => 0,
+                Enum::OPTION_QUANTITY_MAX => 100,
+                Enum::CONFIG_SUB_OPTIONS  => [
+                    [
+                        Enum::OPTION_SUB_NAME  => 'vCPU|vCPU',
+                        Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                    ]
+                ]
+            ];
+
+        }
+        $configOptions[] = [
+            Enum::OPTION_NAME         =>  ConfigurableOption::VIRTUAL_NETWORKS.'|Virtual Networks',
+            Enum::OPTION_TYPE         => Enum::OPTION_TYPE_QUANTITY,
+            Enum::OPTION_QUANTITY_MIN => 0,
+            Enum::OPTION_QUANTITY_MAX => 100,
+            Enum::CONFIG_SUB_OPTIONS  => [
+                [
+                    Enum::OPTION_SUB_NAME  => 'Unit|Unit',
+                    Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                ]
+            ]
+        ];
+        return $configOptions;
+    }
+}

+ 7 - 0
app/Config/configuration.yml

@@ -0,0 +1,7 @@
+version: '2.7.0'
+systemName: 'ProxmoxCloudVps'
+name: 'Proxmox Cloud VPS'
+description: 'Proxmox Cloud VPS For WHMCS.<br>For more info visit our <a href="http://www.docs.modulesgarden.com/CHANGE_ME" style="color: #4169E1;" target="_blank">Wiki</a>.'
+clientareaName: 'MG Demo'
+author: '<a href="http://www.modulesgarden.com" targer="_blank">ModulesGarden</a>'
+moduleIcon: 'ip_manager'

+ 1 - 0
app/Config/cron.yml

@@ -0,0 +1 @@
+list:

+ 1 - 0
app/Config/di/buildWithDefaultMethod.yml

@@ -0,0 +1 @@
+class: []

+ 1 - 0
app/Config/di/interface.yml

@@ -0,0 +1 @@
+interface: []

+ 2 - 0
app/Config/di/register.yml

@@ -0,0 +1,2 @@
+class:
+  - {namespace: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\Core\\UI\\Widget\\Sidebar\\SidebarService',                               alias: "sidebar", singleton: true ,auto: false}

+ 9 - 0
app/Config/di/rewrite.yml

@@ -0,0 +1,9 @@
+class:
+  - {old: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\Core\\Configuration\\Addon\\Config\\After',     new: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\App\\Configuration\\Addon\\Config\\After'}
+  - {old: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\Core\\Configuration\\Addon\\Activate\\After',   new: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\App\\Configuration\\Addon\\Activate\\After'}
+  - {old: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\Core\\Configuration\\Addon\\Deactivate\\After', new: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\App\\Configuration\\Addon\\Deactivate\\After'}
+  - {old: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\Core\\Configuration\\Addon\\Update\\After',     new: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\App\\Configuration\\Addon\\Update\\After'}
+  - {old: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\Core\\Configuration\\Addon\\Config\\Before',    new: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\App\\Configuration\\Addon\\Config\\Before'}
+  - {old: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\Core\\Configuration\\Addon\\Activate\\Before',  new: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\App\\Configuration\\Addon\\Activate\\Before'}
+  - {old: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\Core\\Configuration\\Addon\\Deactivate\\Before',new: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\App\\Configuration\\Addon\\Deactivate\\Before'}
+  - {old: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\Core\\Configuration\\Addon\\Update\\Before',    new: '\\ModulesGarden\\Servers\\ProxmoxCloudVps\\App\\Configuration\\Addon\\Update\\Before'}

+ 0 - 0
app/Config/di/services.yml


+ 3 - 0
app/Config/events.php

@@ -0,0 +1,3 @@
+<?php
+
+return [];

+ 3 - 0
app/Config/hooks.yml

@@ -0,0 +1,3 @@
+name:
+  AdminAreaFooterOutput: false,
+  ClientAreaPrimarySidebar: true

+ 7 - 0
app/Config/menu/admin.yml

@@ -0,0 +1,7 @@
+home:
+  icon: 'lu-nav__link-icon lu-zmdi lu-zmdi-home'
+LoggerManager:
+  icon: 'lu-nav__link-icon lu-zmdi lu-zmdi-assignment'
+documentation:
+  icon: 'lu-nav__link-icon lu-zmdi lu-zmdi-file-text'
+  externalUrl: "https://www.docs.modulesgarden.com/Domain_Orders_Extended_For_WHMCS"

+ 1 - 0
app/Config/menu/client.yml

@@ -0,0 +1 @@
+[]

+ 8 - 0
app/Config/sidebars.yml

@@ -0,0 +1,8 @@
+Service Details Overview:
+  customTemplate:
+   uri: 'clientarea.php?action=productdetails&id={$hostingId}&modop=custom&a=management&mg-page=customTemplate'
+   order: 801
+virtualMachinesProxmoxCloudVps:
+  vmcreate:
+    uri: 'clientarea.php?action=productdetails&id={$hostingId}&modop=custom&a=management&mg-page=vm&mg-action=create'
+    order: 701

+ 1 - 0
app/Config/ui/admin/home/index.yml

@@ -0,0 +1 @@
+

+ 23 - 0
app/Configuration/Addon/Activate/After.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Configuration\Addon\Activate;
+
+/**
+ * Runs after module activation actions
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+class After extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Activate\After
+{
+
+    /**
+     * @param array $params
+     * @return array
+     */
+    public function execute(array $params = [])
+    {
+        $return = parent::execute($params);
+
+        return $return;
+    }
+}

+ 23 - 0
app/Configuration/Addon/Activate/Before.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Configuration\Addon\Activate;
+
+/**
+ * Runs before module activation actions
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+class Before extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Activate\Before
+{
+
+    /**
+     * @param array $params
+     * @return array
+     */
+    public function execute(array $params = [])
+    {
+        $return = parent::execute($params);
+
+        return $return;
+    }
+}

+ 23 - 0
app/Configuration/Addon/Config/After.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Configuration\Addon\Config;
+
+/**
+ * Runs after loading module configuration
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+class After extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Config\After
+{
+
+    /**
+     * @param array $params
+     * @return array
+     */
+    public function execute(array $params = [])
+    {
+        $return = parent::execute($params);
+
+        return $return;
+    }
+}

+ 23 - 0
app/Configuration/Addon/Config/Before.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Configuration\Addon\Config;
+
+/**
+ * Runs before loading module configuration
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+class Before extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Config\Before
+{
+
+    /**
+     * @param array $params
+     * @return array
+     */
+    public function execute(array $params = [])
+    {
+        $return = parent::execute($params);
+
+        return $return;
+    }
+}

+ 23 - 0
app/Configuration/Addon/Deactivate/After.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Configuration\Addon\Deactivate;
+
+/**
+ * Runs after addon deactivation
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+class After extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Deactivate\After
+{
+
+    /**
+     * @param array $params
+     * @return array
+     */
+    public function execute(array $params = [])
+    {
+        $return = parent::execute($params);
+
+        return $return;
+    }
+}

+ 23 - 0
app/Configuration/Addon/Deactivate/Before.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Configuration\Addon\Deactivate;
+
+/**
+ * Runs before addon deactivation
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+class Before extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Deactivate\Before
+{
+
+    /**
+     * @param array $params
+     * @return array
+     */
+    public function execute(array $params = [])
+    {
+        $return = parent::execute($params);
+
+        return $return;
+    }
+}

+ 0 - 0
app/Configuration/Addon/Others/.gitkeep


+ 22 - 0
app/Configuration/Addon/Update/After.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Configuration\Addon\Update;
+
+/**
+ * runs after module update actions
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+class After extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Update\After
+{
+
+    /**
+     * @param array $params
+     * @return array
+     */
+    public function execute(array $params = [])
+    {
+        $return = parent::execute($params);
+        return $return;
+    }
+}

+ 22 - 0
app/Configuration/Addon/Update/Before.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Configuration\Addon\Update;
+
+/**
+ * runs before module update actions
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+class Before extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Update\Before
+{
+
+    /**
+     * @return array
+     */
+    public function execute($version)
+    {
+        $return = parent::execute($version);
+
+        return $return;
+    }
+}

+ 29 - 0
app/Configuration/Addon/Update/Patch/M2M7P0.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Configuration\Addon\Update\Patch;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Update\Patch\AbstractPatch;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+/**
+ * Description of M2M6P0
+ *
+ * @author <slawomir@modulesgarden.com>
+ */
+class M2M7P0 extends AbstractPatch
+{
+    public function execute()
+    {
+        if ($this->runSchema())
+        {
+            sl('logger')
+                ->addDebug("Correctly installed update {$this->getVersion()} .", []);
+        }
+        else
+        {
+            sl('errorManager')
+                ->addError(self::class, "Incorrectly installed update {$this->getVersion()} .", []);
+        }
+
+    }
+}

+ 31 - 0
app/Cron/MainCron.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Cron;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ModuleConstants;
+use Symfony\Component\Console\Input\ArgvInput;
+use Symfony\Component\Console\Output\ConsoleOutput;
+use Symfony\Component\Console\Style\SymfonyStyle;
+
+class MainCron extends \ModulesGarden\ProxmoxAddon\Core\CommandLine\CronManager
+{
+
+    public function  run(){
+
+        ProxmoxAddonValidator::isInstalledOrFail();
+        $this->loadCommandsControllers($this->getCommands());
+        $input = new ArgvInput();
+        $output = new ConsoleOutput();
+        $this->configureIO($input, $output);
+        $io = new SymfonyStyle($input, $output);
+        $io->error(sprintf("This cron is depracted since version 3.0.0, please run: %s",
+            ModuleConstants::getFullPathWhmcs() . DS .'modules'. DS .'addons'. DS .'proxmoxAddon'.DS.'cron'.DS.'cron.php'));
+        //queue
+        $command = $this ->find('queue');
+        $command->run(  $input, $output , $io );
+        //update-server-usage
+        $command = $this ->find('update-server-usage');
+        $command->run(  $input, $output, $io  );
+    }
+}

+ 0 - 0
app/Database/data.sql


+ 0 - 0
app/Database/schema.sql


+ 30 - 0
app/Enum/ConfigurableOption.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Enum;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Enum\Enum;
+
+/**
+ * @deprecated
+ */
+final  class ConfigurableOption extends Enum
+{
+    const SOCKETS          = "CPU Sockets Limit";
+    const CORES_PER_SOCKET     = "The number of cores per socket";
+    const CORES            = "CPU Cores Limit";
+    const CPU_LIMIT        = "cpuLimit";
+    const CPU_UNITS        = "CPU Weight Limit";
+    const MEMORY           = "Memory Limit";
+    const STORAGE          = "Storage Limit";
+    const IPV4             = "IP Addresses Limit";
+    const IPV6             = "IPv6 Addresses Limit";
+    const SWAP             = "SWAP Limit";
+    const BACKUPS_SIZE     = "Backups Size Limit";
+    const BACKUPS_FILES    = "Backups Files Limit";
+    const SNAPSHOTS        = "snapshots";
+    const NETWORK_RATE     = "networkRate";
+    const VCPUS            = "vcpus";
+    const BANDWIDTH        = 'Bandwidth';
+    const VIRTUAL_NETWORKS = 'virtualNetworks';
+    const DISK_SIZE        = "Disk Space";
+}

+ 17 - 0
app/Enum/CustomField.php

@@ -0,0 +1,17 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Enum;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Enum\Enum;
+
+/**
+ * @deprecated
+ */
+class CustomField extends  Enum
+{
+    const AUTHENTICATION = 'Authentication';
+    const TAG = 'VLAN Tag';
+    const ADVANCED_USER  = 'proxmoxCloudVpsAdvancedUser';
+}

+ 15 - 0
app/Enum/JobPeriod.php

@@ -0,0 +1,15 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Enum;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Enum\Enum;
+
+final class JobPeriod extends  Enum
+{
+    const DAILY = 'daily';
+    const HOURLY =  'hourly';
+    const DAYS_OF_WEEK = ['Monday', 'Tuesday',  'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ];
+
+}

+ 23 - 0
app/Factory/VmModelFactory.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Factory;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\RequestObjectHandler;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+
+class VmModelFactory
+{
+    use WhmcsParams;
+    use RequestObjectHandler;
+
+    /**
+     * @return VmModel
+     */
+    public function fromRequest(){
+        return VmModel::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                 ->ofId($this->getRequestValue('vm'))
+                 ->firstOrFail();
+    }
+
+}

+ 20 - 0
app/Helpers/AppParams.php

@@ -0,0 +1,20 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers;
+
+
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class AppParams
+{
+
+    public function initFromWhmcsParams(){
+        \ModulesGarden\ProxmoxAddon\Core\Helper\sl('whmcsParams')->setParams(sl('whmcsParams')->getWhmcsParams());
+    }
+
+    public function initFromParams($params){
+        \ModulesGarden\ProxmoxAddon\Core\Helper\sl('whmcsParams')->setParams($params);
+    }
+
+}

+ 37 - 0
app/Helpers/BuildUrl.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers;
+
+/*
+File:   BuildUrl.php
+Date:   28.05.2020
+Author: Tomasz Bielecki (tomasz.bi@modulesgarden.com)
+Class BuildUrl
+*/
+
+class BuildUrl extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\BuildUrl
+{
+
+    public static function getSelfUrl()
+    {
+        $host   = $GLOBALS['CONFIG']['SystemURL'] ? $GLOBALS['CONFIG']['SystemURL'] : $_SERVER['HTTP_HOST'];
+        $url = \parse_url( $host );
+        $surfix = $_SERVER['PHP_SELF'];
+
+        $parms = $_GET;
+        $url = "{$url['scheme']}://{$url['host']}{$surfix}";
+        if($parms)
+        {
+            $url = $url.'?'.http_build_query($parms);
+        }
+
+        return $url;
+    }
+
+
+    public static function isClientArea()
+    {
+        return defined('CLIENTAREA');
+    }
+
+}

+ 15 - 0
app/Helpers/ErrorCodesLib.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\ErrorCodes\ErrorCodes;
+
+class ErrorCodesLib extends ErrorCodes
+{
+    const YOUR_APP_000001 = [
+        self::MESSAGE     => 'Your error message',
+        self::CODE        => 'YOUR_APP_000001',
+        self::DEV_MESSAGE => "Your error message left for other developers, the error genesis explanation...",
+        self::LOG         => true //optional, determines if the error should be logged despite of inactive debug mode 
+    ];
+}

+ 11 - 0
app/Helpers/ProxmoxAddonNotInstalledException.php

@@ -0,0 +1,11 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers;
+
+
+class  ProxmoxAddonNotInstalledException extends \Exception
+{
+
+
+}

+ 30 - 0
app/Helpers/ProxmoxAddonValidator.php

@@ -0,0 +1,30 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers;
+
+
+class ProxmoxAddonValidator
+{
+    const ERROR_MESSAGE = 'ProxmoxAddon is not installed or activated';
+
+    public static function isInstalled(){
+
+        if(!class_exists('\ModulesGarden\ProxmoxAddon\Core\ModuleConstants') ){
+            return false;
+        }
+        return !is_null(\ModulesGarden\ProxmoxAddon\Core\ModuleConstants::getModuleRootDir());
+    }
+
+    public static function isInstalledOrFail(){
+        if(!self::isInstalled()){
+            throw new ProxmoxAddonNotInstalledException(self::ERROR_MESSAGE);
+        }
+    }
+
+    public static function failAsString(){
+        return self::ERROR_MESSAGE;
+    }
+
+
+}

+ 67 - 0
app/Helpers/UrlServiceHelper.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers;
+
+/*
+File:   UrlServiceHelper.php
+Date:   15.06.2020
+Author: Tomasz Bielecki (tomasz.bi@modulesgarden.com)
+Class UrlServiceHelper
+*/
+
+use ModulesGarden\ProxmoxAddon\App\Services\UrlService;
+
+
+/**
+ * Class UrlServiceHelper
+ * @package ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers
+ */
+class UrlServiceHelper
+{
+
+    /**
+     * @var \ModulesGarden\ProxmoxAddon\App\Services\UrlService
+     */
+    protected $urlService;
+
+    /**
+     * UrlServiceHelper constructor.
+     */
+    public function __construct()
+    {
+        $this->urlService = new UrlService();
+    }
+
+    /**
+     * @return string
+     */
+    public function getXTermConsoleUrl()
+    {
+        $id = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        return BuildUrl::isClientArea() ? $this->urlService->getUrl('console', 'xtermjs',['vm'=> $id]) : BuildUrl::getSelfUrl().'&mg-action=xtermjs&vm='.$id;
+    }
+
+    /**
+     * @return string
+     */
+    public function getNoVncConsoleUrl()
+    {
+        $id = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        return BuildUrl::isClientArea() ? $this->urlService->getUrl('console', 'novnc', ['vm'=> $id]) : BuildUrl::getSelfUrl().'&mg-action=novncs&vm='.$id;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getSpiceConsoleUrl()
+    {
+        $id = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        return $this->urlService->getUrl('console', 'spice',['vm'=> $id]);
+    }
+
+    public function home()
+    {
+        return $this->urlService->getUrl();
+    }
+
+}

+ 40 - 0
app/Hooks/AdminAreaFooterOutput.php

@@ -0,0 +1,40 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Hook\HookIntegrator;
+
+$hookManager->register(
+    function ($args)
+    {
+        $hookIntegrator = new HookIntegrator($args);
+
+        /**
+         * @var $toReturn is a HTML integration code (or null if no integration was made)
+         * you can add your code to this var before returning its content,
+         * do not overwrite this var!
+         */
+        $toReturn = $hookIntegrator->getHtmlCode();
+
+        if ($toReturn)
+        {
+            return $toReturn;
+        }
+    },
+    100
+);

+ 31 - 0
app/Hooks/AdminProductConfigFieldsSave.php

@@ -0,0 +1,31 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+use ModulesGarden\Servers\ProxmoxCloudVps as main;
+
+$hookManager->register(
+    function ($args)
+    {
+        $provider = new main\App\UI\Admin\Product\Providers\ProductProvider($args['pid']);
+        if (!$provider->isSupportedModule())
+        {
+            return;
+        }
+        $provider->update();
+    }, 1001);

+ 57 - 0
app/Hooks/ClientAreaPrimarySidebar.php

@@ -0,0 +1,57 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+
+$hookManager->register(
+    function (\WHMCS\View\Menu\Item $primarySidebar)
+    {
+        if(!\ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator::isInstalled()){
+            return;
+        }
+        /**
+         * @var  main\Core\Http\Request $request
+         */
+        $request = \ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl('request');
+        if (!$request->get('id'))
+        {
+            return;
+        }
+        $clientAreaSideBar = new \ModulesGarden\ProxmoxAddon\App\Services\Cloud\ClientAreaSidebarService($request->get("id"), $primarySidebar);
+        if (!$clientAreaSideBar->isActive() || !$clientAreaSideBar->isSupportedModule())
+        {
+            return;
+        }
+        if (!function_exists('ModuleBuildParams'))
+        {
+            require_once \ModulesGarden\Servers\ProxmoxCloudVps\Core\ModuleConstants::getFullPathWhmcs('includes') . DIRECTORY_SEPARATOR . "modulefunctions.php";
+        }
+        //Page Cancel
+        if ($request->get('action') == "cancel")
+        {
+            $clientAreaSideBar->informationReplaceUri();
+        } //Page Productdetails
+        if ($request->get('action') == "productdetails")
+        {
+            $clientAreaSideBar->informationReplaceUri();
+            $clientAreaSideBar->serviceDetailsOverview();
+            $clientAreaSideBar->build();
+        }
+
+    }, 943
+);

+ 31 - 0
app/Hooks/ProductDelete.php

@@ -0,0 +1,31 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+
+$hookManager->register(
+    function ($args)
+    {
+        $provider = new \ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Providers\ProductProvider($args['pid']);
+        if (!$provider->isSupportedModule())
+        {
+            return;
+        }
+        $provider->delete();
+    }
+);

+ 44 - 0
app/Hooks/ServiceDelete.php

@@ -0,0 +1,44 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+use ModulesGarden\ProxmoxAddon\App\Models\SnapshotJob;
+
+$hookManager->register(
+    function ($vars)
+    {
+
+        if (!$vars['serviceid'])
+        {
+            return;
+        }
+        $serviceid = $vars['serviceid'];
+        try
+        {
+            \ModulesGarden\ProxmoxAddon\App\Models\Job::ofHostingId($serviceid)->delete();
+            \ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress::ofHostingId($serviceid)->delete();
+            \ModulesGarden\ProxmoxAddon\App\Models\User::ofHostingId($serviceid)->delete();
+            \ModulesGarden\ProxmoxAddon\App\Models\IpAddress::ofHostingId($serviceid)->update(["hosting_id" => "0"]);
+            //snapshot jobs
+            SnapshotJob::ofHostingId($serviceid)->delete();
+        }
+        catch (\Exception $ex)
+        {
+        }
+    }
+);

+ 62 - 0
app/Http/Actions/AdminServicesTabFields.php

@@ -0,0 +1,62 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions;
+
+use ModulesGarden\ProxmoxAddon\App\Configuration\Addon\Update\AddonUpgradeService;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\CustomField;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Admin\Home;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\Validator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+
+class AdminServicesTabFields extends AddonController
+{
+    use WhmcsParams;
+    use ProductService;
+    use ApiService;
+
+    /**
+     * @var AddonUpgradeService
+     */
+    private $addonUpgradeService;
+
+    public function execute($params = null)
+    {
+        $action = $this->getRequestValue('mg-action') ? $this->request->get('mg-action') : 'index';
+
+        if ($params['status'] != "Active" || ! $this->getWhmcsCustomField(CustomField::AUTHENTICATION))
+        {
+            return [];
+        }
+        try {
+            ProxmoxAddonValidator::isInstalledOrFail();
+            $this->addonUpgradeService = new AddonUpgradeService();
+            $this->addonUpgradeService->run();
+            return [Home::class, $action];
+        } catch (\Exception $ex) {
+
+            return ["Error" => "<span style='color: red'>" . $ex->getMessage() . "</span>"];
+        }
+
+    }
+}

+ 83 - 0
app/Http/Actions/ChangePackage.php

@@ -0,0 +1,83 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions;
+
+use ModulesGarden\ProxmoxAddon\App\Models\ModuleSettings;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\HostingService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\ProxmoxAddon\App\Services\Utility;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+
+
+class ChangePackage extends AddonController
+{
+    use ApiService;
+    use UserService;
+    use ProductService;
+    use WhmcsParams;
+    use HostingService;
+
+
+    /**
+     * @param null $params
+     * @return bool|string
+     * @todo Resources validation
+     */
+    public function execute($params = null)
+    {
+        try {
+            if(!ProxmoxAddonValidator::isInstalled()){
+                return ProxmoxAddonValidator::failAsString();
+            }
+            (new AppParams())->initFromWhmcsParams();
+            $this->networkService = new NetworkService();
+            //Bandwith limit
+            $this->saveUsageLimit();
+            //Assing ip
+            if (!Utility::isIpManagerProxmoxCloudIntegration())
+            {
+                list($ip4, $ip6) = $this->networkService->getIpAddressesRequest();
+                $this->networkService->addIp($ip4, $ip6, $this->getDefaultNodeIfSet());
+            }
+            return "success";
+        }catch (\Exception $ex)
+        {
+            if (ModuleSettings::isDebug())
+            {
+                logModuleCall(
+                    'ProxmoxCloudVps',
+                    __CLASS__,
+                    [],
+                    null,
+                    $ex->getMessage() . " " . $ex->getTraceAsString()
+                );
+            }
+            return $ex->getMessage();
+        }
+
+    }
+
+}

+ 75 - 0
app/Http/Actions/ChangeUserRole.php

@@ -0,0 +1,75 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions;
+
+use ModulesGarden\ProxmoxAddon\App\Models\ModuleSettings;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\ProxmoxAddon\App\Services\CloudService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\Validator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+
+class ChangeUserRole extends AddonController
+{
+
+    use WhmcsParams;
+    use ProductService;
+    use UserService;
+    use ApiService;
+
+    public function execute($params = null)
+    {
+        if(!ProxmoxAddonValidator::isInstalled()){
+            return ProxmoxAddonValidator::failAsString();
+        }
+        try
+        {
+            (new AppParams())->initFromParams($params);
+            //Create User
+            if (!$this->isUser())
+            {
+                $this->userCreate();
+            }
+            $this->userUpdate();
+            $cloud = new CloudService();
+            $vms = $cloud->getVmids();
+            $this->userUpdatePermission($vms);
+            return "success";
+        }
+        catch (\Exception $ex)
+        {
+            if (ModuleSettings::isDebug())
+            {
+                logModuleCall(
+                    'ProxmoxCloudVps',
+                    __CLASS__,
+                    [],
+                    null,
+                    $ex->getMessage() . " " . $ex->getTraceAsString()
+                );
+            }
+            return $ex->getMessage();
+        }
+    }
+}

+ 53 - 0
app/Http/Actions/ConfigOptions.php

@@ -0,0 +1,53 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions;
+
+use ModulesGarden\ProxmoxAddon\App\Configuration\Addon\Update\AddonUpgradeService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Admin\Product;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController;
+
+class ConfigOptions extends AddonController
+{
+
+    /**
+     * @var AddonUpgradeService
+     */
+    private $addonUpgradeService;
+
+    public function execute($params = null)
+    {
+
+        if (($this->getRequestValue('action') === 'module-settings' || ($this->getRequestValue('loadData') && $this->getRequestValue('ajax') == '1')))
+        {
+            ProxmoxAddonValidator::isInstalledOrFail();
+            $this->addonUpgradeService = new AddonUpgradeService();
+            $this->addonUpgradeService->run();
+            return [Product::class, 'index'];
+        }
+        else
+        {
+            if ($this->getRequestValue('action') !== 'save')
+            {
+                return [];
+            }
+        }
+    }
+}

+ 101 - 0
app/Http/Actions/CreateAccount.php

@@ -0,0 +1,101 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions;
+
+use ModulesGarden\ProxmoxAddon\App\Configuration\Addon\Update\AddonUpgradeService;
+use ModulesGarden\ProxmoxAddon\App\Models\ModuleSettings;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\HostingService;
+use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\CustomField;
+use ModulesGarden\ProxmoxAddon\App\Services\Utility;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+
+class CreateAccount extends AddonController
+{
+    use WhmcsParams;
+    use ProductService;
+    use ApiService;
+    use UserService;
+    use HostingService;
+
+    /**
+     * @var AddonUpgradeService
+     */
+    private $addonUpgradeService;
+
+    public function execute($params = null)
+    {
+        if(!ProxmoxAddonValidator::isInstalled()){
+            return ProxmoxAddonValidator::failAsString();
+        }
+        try
+        {
+            (new AppParams())->initFromWhmcsParams();
+            $this->addonUpgradeService = new AddonUpgradeService();
+            $this->networkService = new NetworkService();
+            $this->addonUpgradeService->run();
+            if(!$this->configuration()->getTagFrom() || !$this->configuration()->getTagTo() && $this->configuration()->isPermissionVirtualNetwork()){
+                throw new \Exception("Product configuration validator error: VLAN TAG Range Number is empty.");
+            }
+            //Bandwith limit
+            $this->saveUsageLimit();
+            //Assing ip
+            if (!Utility::isIpManagerProxmoxCloudIntegration())
+            {
+                list($ip4, $ip6) = $this->networkService->getIpAddressesRequest();
+
+                $this->networkService->addIp($ip4, $ip6, $this->getDefaultNodeIfSet());
+            }
+            if( $this->isUser()){
+                return "success";
+            }
+            $this->userCreate();
+            $this->customFieldUpdate(CustomField::AUTHENTICATION, $this->configuration()->getRealm());
+            return "success";
+        }
+        catch (\Exception $ex)
+        {
+            if (ModuleSettings::isDebug())
+            {
+                logModuleCall(
+                    'ProxmoxCloudVps',
+                    __CLASS__,
+                    [],
+                    null,
+                    $ex->getMessage() . " " . $ex->getTraceAsString()
+                );
+            }
+            return $ex->getMessage();
+        }
+    }
+
+
+
+
+
+
+
+}

+ 37 - 0
app/Http/Actions/MetaData.php

@@ -0,0 +1,37 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController;
+
+class MetaData extends AddonController
+{
+    public function execute($params = null)
+    {
+        return [
+            'DisplayName'    => 'Proxmox Cloud VPS',
+            'RequiresServer' => true,
+            'DefaultNonSSLPort' => '8006', // Default Non-SSL Connection Port
+            'DefaultSSLPort' => '8006', // Default SSL Connection Port
+        ];
+
+    }
+
+}

+ 62 - 0
app/Http/Actions/ResetBandwidth.php

@@ -0,0 +1,62 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions;
+
+use ModulesGarden\ProxmoxAddon\App\Models\ModuleSettings;
+use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Hosting;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\Validator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+
+class ResetBandwidth extends AddonController
+{
+
+    use WhmcsParams;
+    use ProductService;
+
+    public function execute($params = null)
+    {
+        if(!ProxmoxAddonValidator::isInstalled()){
+            return ProxmoxAddonValidator::failAsString();
+        }
+        try
+        {
+            Hosting::where("id", $this->getWhmcsParamByKey('serviceid'))
+                   ->update(["bwusage" => 0]);
+            return "success";
+        }
+        catch (\Exception $ex)
+        {
+            if (ModuleSettings::isDebug())
+            {
+                logModuleCall(
+                    'ProxmoxCloudVps',
+                    __CLASS__,
+                    [],
+                    null,
+                    $ex->getMessage() . " " . $ex->getTraceAsString()
+                );
+            }
+            return $ex->getMessage();
+        }
+    }
+}

+ 100 - 0
app/Http/Actions/SuspendAccount.php

@@ -0,0 +1,100 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions;
+
+use MGProvision\Proxmox\v2\models\Kvm;
+use MGProvision\Proxmox\v2\models\User;
+use MGProvision\Proxmox\v2\VmFactory;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\ProxmoxAddon\App\Services\CloudService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+
+class SuspendAccount extends AddonController
+{
+    use ProductService;
+    use ApiService;
+    use UserService;
+    use WhmcsParams;
+
+    public function execute($params = null)
+    {
+        if(!ProxmoxAddonValidator::isInstalled()){
+            return ProxmoxAddonValidator::failAsString();
+        }
+        try
+        {
+            (new AppParams())->initFromParams($params);
+            $cloud = new CloudService();
+            //User suspend
+            $user        = $this->getUser();
+            $userService = new User("{$user->username}@{$user->realm}");
+            $userService->setApi($this->api());
+            $permissions = $userService->permissions();
+            //get vmids
+            $vmids = $cloud->getVmids();
+            foreach ($vmids as $vmid){
+                foreach ($permissions as $p)
+                {
+                    if ($p['path'] == "/vms/" . $vmid && $p['ugid'] == $userService->getUserid())
+                    {
+                        $userService->updatePermission($vmid, $p['roleid'], 1);
+                    }
+                }
+            }
+            //disable user
+            $userService->disable();
+            //VM suspend
+            $suspensionAction = $this->configuration()->getSuspensionAction();
+            foreach ($cloud->getVmModels() as $vmModel){
+                $vm = (new VmFactory())->fromVmModel($vmModel);
+                $vm->updateConfig(["onboot" => 0]);
+                if (!$vm->isRunning())
+                {
+                    continue;
+                }
+                if ($suspensionAction && method_exists($vm, $suspensionAction))
+                {
+                    $vm->{$suspensionAction}();
+                    continue;
+                }
+                if ($vm instanceof Kvm)
+                {
+                    $vm->suspend();
+                    continue;
+                }
+                if ($vm->isRunning())
+                {
+                    $vm->stop();
+                }
+            }
+            return "success";
+
+        }
+        catch (\Exception $ex)
+        {
+            return $ex->getMessage();
+        }
+    }
+}

+ 114 - 0
app/Http/Actions/TerminateAccount.php

@@ -0,0 +1,114 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions;
+
+
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Hosting;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\ProxmoxAddon\App\Services\CloudService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\HighAvailabilityClusterService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\HostingService;
+use ModulesGarden\ProxmoxAddon\Core\Models\ModuleSettings\Model as ModuleSettings;
+use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\CustomField;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+
+
+class TerminateAccount extends AddonController
+{
+    use WhmcsParams;
+    use ProductService;
+    use ApiService;
+    use UserService;
+    use HostingService;
+    /**
+     * @var HighAvailabilityClusterService
+     */
+    private $highAvailabilityClusterService;
+
+    public function __construct()
+    {
+        $this->highAvailabilityClusterService = new HighAvailabilityClusterService();
+    }
+
+    /**
+     * @param null $params
+     * @return string
+     * @todo delete vms
+     */
+    public function execute($params = null)
+    {
+        (new AppParams())->initFromParams($params);
+        if(!ProxmoxAddonValidator::isInstalled()){
+            return ProxmoxAddonValidator::failAsString();
+        }
+        try
+        {
+            if (!$this->getWhmcsParamByKey('serviceid'))
+            {
+                throw new \InvalidArgumentException("The Service Id cannot be empty");
+            }
+            $serviceId = $this->getWhmcsParamByKey('serviceid');
+
+            //User delete
+            if ($this->isUser())
+            {
+                $this->deleteUser();
+            }
+            //virtual networks
+            VirtualNetwork::ofHostingId($serviceId)->delete();
+            //vms
+            $cloudService = new CloudService();
+            $cloudService->destroy();
+            //Reset Custom Fields
+            if ($this->getWhmcsCustomField(CustomField::TAG))
+            {
+                $this->customFieldUpdate(CustomField::TAG, "");
+            }
+            $this->customFieldUpdate(CustomField::AUTHENTICATION, "");
+            //Cache
+            ModuleSettings::where('setting', "LIKE", "%{$serviceId}_cacheData%")->delete();
+            //ip addresses
+            Hosting::where("id", $this->getWhmcsParamByKey('serviceid'))
+                ->update(["dedicatedip" => "", "assignedips" => ""]);
+
+            return "success";
+        }
+        catch (\Exception $ex)
+        {
+            if (\ModulesGarden\ProxmoxAddon\App\Models\ModuleSettings::isDebug())
+            {
+                logModuleCall(
+                    'ProxmoxCloudVps',
+                    __CLASS__,
+                    [],
+                    null,
+                    $ex->getMessage() . " " . $ex->getTraceAsString()
+                );
+            }
+            return $ex->getMessage();
+        }
+    }
+}

+ 69 - 0
app/Http/Actions/TestConnection.php

@@ -0,0 +1,69 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions;
+
+use MGProvision\Proxmox\v2\Api;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController;
+
+class TestConnection extends AddonController
+{
+    public function execute($params = null)
+    {
+        try
+        {
+            if(isset($GLOBALS['disable_hook_loading']) && $GLOBALS['disable_hook_loading']){
+                throw new \Exception("Enabled hooks are required by the module. Please disable \$disable_hook_loading in cofiguration.php ");
+            }
+            ProxmoxAddonValidator::isInstalledOrFail();
+            if (!$params['serverip'] && !$params['serverhostname'])
+            {
+                throw new \Exception("Server Hostname or  IP Address  is empty.");
+            }
+            if ($params['serverip'])
+            {
+                if(is_numeric($params['serverport'])){
+                    $params['serverip'] .=":".$params['serverport'];
+                }
+                $api = new Api($params['serverip'], $params['serverusername'], $params['serveraccesshash'], $params['serverpassword']);
+                $api->debug();
+                $api->get("/nodes");
+            }
+            if ($params['serverhostname'])
+            {
+                if (preg_match("/[\/]/", $params['serverhostname']))
+                {
+                    throw new \Exception(sprintf("Server Hostname '%s' is invalid", $params['serverhostname']));
+                }
+                if(is_numeric($params['serverport'])){
+                    $params['serverhostname'] .=":".$params['serverport'];
+                }
+                $api = new Api($params['serverhostname'], $params['serverusername'], $params['serveraccesshash'], $params['serverpassword']);
+                $api->debug();
+                $api->get("/nodes");
+            }
+            return ['success' => true];
+        }
+        catch (\Exception $e)
+        {
+            return ['error' => $e->getMessage()];
+        }
+    }
+}

+ 100 - 0
app/Http/Actions/UnsuspendAccount.php

@@ -0,0 +1,100 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions;
+
+use MGProvision\Proxmox\v2\models\Kvm;
+use MGProvision\Proxmox\v2\models\User;
+use MGProvision\Proxmox\v2\VmFactory;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\ProxmoxAddon\App\Services\CloudService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+
+class UnsuspendAccount extends AddonController
+{
+    use ApiService;
+    use UserService;
+    use ProductService;
+    use WhmcsParams;
+
+    public function execute($params = null)
+    {
+        if(!ProxmoxAddonValidator::isInstalled()){
+            return ProxmoxAddonValidator::failAsString();
+        }
+        try
+        {
+            (new AppParams())->initFromParams($params);
+            $cloud = new CloudService();
+            //User Unsuspend
+            $user        = $this->getUser();
+            $userService = new User("{$user->username}@{$user->realm}");
+            $userService->setApi($this->api());
+            if ($userService->configuration()['enable'] == "0")
+            {
+                $userService->enable();
+            }
+            //VM Permission
+            $permissions = $userService->permissions();
+            foreach ($cloud->getVmModels() as $vmModel){
+                $vmid        = $vmModel->vmid;
+                $vm = (new VmFactory())->fromVmModel($vmModel);
+                foreach ($permissions as $p)
+                {
+                    if ($p['path'] == "/vms/" . $vmid && $p['ugid'] == $userService->getUserid())
+                    {
+                        $userService->updatePermission($vmid, $p['roleid'], 1);
+                    }
+                }
+                $role = $this->configuration()->getUserRole() ? $this->configuration()->getUserRole() : 'PVEVMUser';
+                $userService->updatePermission($vmid, $role);
+                if ($this->configuration()->isOnboot())
+                {
+                    $vm->updateConfig(["onboot" => 1]);
+                }
+                $status = $vm->status();
+                if ($vm instanceof Kvm && $status['qmpstatus'] == "paused")
+                {
+                    $vm->resume();
+                    continue;
+                }
+                if ($status['status'] == "running")
+                {
+                    continue;
+                }
+                else
+                {
+                    $vm->start();
+                }
+            }
+
+
+            return "success";
+        }
+        catch (\Exception $ex)
+        {
+            return $ex->getMessage();
+        }
+    }
+}

+ 49 - 0
app/Http/Admin/Home.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Admin;
+
+use MGProvision\Proxmox\v2\Api;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\AccountResources\AccountResourcesContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\User\Pages\UserDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Pages\IpAddressDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\AccountSummary;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Pages\VmsDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Http\AbstractController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Traits\OutputBuffer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+
+/**
+ * Example admin home page controler
+ * @author Sławomir Miśkowicz <slawomir@modulesgarden.com>
+ */
+class Home extends AbstractController
+{
+    use WhmcsParams;
+    use ProductService;
+    use ApiService;
+    use OutputBuffer;
+    use UserService;
+    public function index()
+    {
+        $view = Helper\viewIntegrationAddon();
+        $view->initCustomAssetFiles();
+        (new AppParams())->initFromWhmcsParams();
+        //Resurces
+        $view->addElement(AccountResourcesContainer::class);
+        //VMs
+        $view->addElement(VmsDataTable::class);
+        //IPs
+        $view->addElement(IpAddressDataTable::class);
+        //User
+        $view->addElement(UserDataTable::class);
+        return $view;
+
+    }
+
+}

+ 52 - 0
app/Http/Admin/Product.php

@@ -0,0 +1,52 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Admin;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Forms\MainForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Pages\CustomOptionsWidget;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Pages\MainContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\RequestObjectHandler;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\Packages\WhmcsService\UI\ConfigurableOption\OptionsWidget;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\viewIntegrationAddon;
+
+
+class Product
+{
+    use RequestObjectHandler;
+    use WhmcsParams;
+    use ProductService;
+
+    public function index()
+    {
+
+        $productId = $this->getRequestValue("id");
+        $product   = \ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Product::where("id", $productId)->firstOrFail();
+        sl("whmcsParams")->setParams($product->getParams());
+
+        return viewIntegrationAddon()
+            ->addElement(MainForm::class)
+            ->addElement(new  OptionsWidget());
+
+    }
+
+}

+ 63 - 0
app/Http/Client/BaseClientController.php

@@ -0,0 +1,63 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Client;
+
+
+use MGProvision\Proxmox\v2\VmFactory;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CloneQemuJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateLxcJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateQemuJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\LoadBalancer\UpgradeVmJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\MigrateVmJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Reinstall\CreateVmJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\RestoreVm;
+use ModulesGarden\ProxmoxAddon\App\Models\Job;
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Factory\VmModelFactory;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\VmBuild;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\view;
+
+
+trait BaseClientController
+{
+    public function isVmCreated(   VmModel $vmModel)
+    {
+        $jobs = [
+            CloneQemuJob::class,
+            CreateQemuJob::class,
+            CreateLxcJob::class,
+            MigrateVmJob::class,
+            RestoreVm::class,
+            \ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Reinstall\RestoreVm::class,
+            UpgradeVmJob::class,
+            CreateVmJob::class
+        ];
+        if (!$vmModel->vmid || $vmModel->vmid == 0 ){
+            return false;
+        }
+        if(Job::waiting()->ofHostingId($this->getWhmcsParamByKey("serviceid"))->ofJobs($jobs)->ofCustomId($vmModel->id)->count() > 0){
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * @return \ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\View|object|null
+     * @todo
+     */
+    public function onVpsBuild()
+    {
+        return view()->addElement(VmBuild::class);
+    }
+
+    protected function initVm(){
+        $vmModel =  (new VmModelFactory)->fromRequest();
+        \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->setVmModel($vmModel);
+        if($vmModel->vmid==0){
+            return;
+        }
+        \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->setVm((new VmFactory())->fromVmModel($vmModel));
+    }
+}

+ 143 - 0
app/Http/Client/Console.php

@@ -0,0 +1,143 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Client;
+
+use MGProvision\Proxmox\v2\Api;
+use ModulesGarden\ProxmoxAddon\App\Models\ModuleSettings;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\ProxmoxAddon\App\Services\Utility;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\DetailsContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Http\AbstractClientController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+
+class Console extends AbstractClientController
+{
+
+    use WhmcsParams;
+    use UserService;
+    use ApiService;
+    use ProductService;
+    use BaseClientController;
+
+
+    /**
+     * Console constructor.
+     */
+    public function __construct()
+    {
+        $this->initVm();;
+        (new AppParams())->initFromWhmcsParams();
+    }
+
+    public function novnc()
+    {
+        $this->acl()->novnc();
+        $this->console(['novnc' => 1]);
+    }
+
+    public function xtermjs()
+    {
+        $this->acl()->xtermjs();
+        $this->console(['xtermjs' => 1]);
+    }
+
+    private function console($request = [])
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $serverHost = $this->getWhmcsParamByKey('serverip') ? $this->getWhmcsParamByKey('serverip') : $this->getWhmcsParamByKey('serverhostname');
+        //Host
+        $consoleHost = $this->getWhmcsParamByKey('serverhostname') ? $this->getWhmcsParamByKey('serverhostname') : $this->getWhmcsParamByKey('serverip');
+        if ($this->configuration()->getConsoleHost())
+        {
+            $consoleHost = $this->configuration()->getConsoleHost();
+        }
+        //Port
+        $consolePort = 8006;
+        if(is_numeric($this->getWhmcsParamByKey('serverport'))){
+            $consolePort = $this->getWhmcsParamByKey('serverport');
+        }
+        if (preg_match('/\:/', $consoleHost))
+        {
+            $ex          = explode(":", $consoleHost);
+            $consoleHost = $ex['0'];
+            $consolePort = $ex['1'];
+        }
+        try
+        {
+            //User
+            $vpsUser = $this->getUser();
+            if (empty($vpsUser->username))
+            {
+                throw new \Exception('User does not have permissions to access noVNC console');
+            }
+            //Load Users API
+            if(!preg_match('/\:/', $serverHost) && $this->getWhmcsParamByKey('serverport') ){
+                $serverHost .=":".$this->getWhmcsParamByKey('serverport');
+            }
+            $api = new Api($serverHost, $vpsUser->username, $vpsUser->realm, $vpsUser->getPassword());
+            $api->debug(ModuleSettings::isDebug());
+            //User Authorization
+            $ticket                         = $api->getLoginTicket();
+            $request['token']               = $ticket['ticket'];
+            $request['CSRFPreventionToken'] = $ticket['CSRFPreventionToken'];
+            $request['console']             = $vm->getVirtualization();
+            /* @deprecated $vars['virtualization'] since version 2.6.0 */
+            $request['virtualization'] = $vm->getVirtualization();
+            $request['node']           = $vm->getNode();
+            $request['vmid']           = $vm->getVmid();
+        }
+        catch (\Exception $ex)
+        {
+
+            $request['error'] = $ex->getMessage();
+        }
+        $response = new RedirectResponse("https://{$consoleHost}:{$consolePort}/novnc/mgnovnc.html?" . http_build_query($request));
+        $response->send();
+    }
+
+    public function spice()
+    {
+        $this->acl()->spice();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $this->api();
+        $proxy       = $vm->spiceproxy();
+        $consoleHost = $this->getWhmcsParamByKey('serverhostname') ? $this->getWhmcsParamByKey('serverhostname') : $this->getWhmcsParamByKey('serverip');
+        if ($this->configuration()->getConsoleHost())
+        {
+            $consoleHost = $this->configuration()->getConsoleHost();
+        }
+        if ($consoleHost)
+        {
+            $ex             = explode(":", $proxy['proxy']);
+            $port           = end($ex);
+            $proxy['proxy'] = "http://{$consoleHost}:{$port}";
+        }
+        $content = "[virt-viewer]\r\n";
+        foreach ($proxy as $k => $v)
+        {
+            $content .= "{$k}={$v}\r\n";
+        }
+        //Response
+        $response = new StreamedResponse();
+        $response->setStatusCode(200);
+        $response->headers->set('Cache-Control', 'public');
+        $response->headers->set('Content-Type', 'application/x-virt-viewer');
+        $response->headers->set('Content-Transfer-Encoding', 'Binary');
+        $response->setCallback(function () use ($content)
+        {
+            echo $content;
+        });
+        $fileName = Utility::generatePassword(8, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+        $fileName .= ".vv";
+        $response->headers->set(
+            'Content-Disposition', "attachment; filename=\"{$fileName}\""
+        );
+        $response->send();
+        exit();
+    }
+}

+ 52 - 0
app/Http/Client/CustomTemplate.php

@@ -0,0 +1,52 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Client;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Pages\CustomTemplateDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\AccountSummary;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\DetailsContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\ErrorContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Pages\VirtualNetworkDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Pages\VmsDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Http\AbstractClientController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class CustomTemplate extends AbstractClientController
+{
+
+    use WhmcsParams;
+    use ProductService;
+    use BaseClientController;
+    use UserService;
+
+    public function index()
+    {
+        if ($this->getWhmcsParamByKey('status') != 'Active')
+        {
+            return;
+        }
+        if (!ProxmoxAddonValidator::isInstalled())
+        {
+            ProxmoxAddonValidator::isInstalledOrFail();
+        }
+        if (!$this->isUser())
+        {
+            return Helper\view()->addElement(ErrorContainer::class);
+        }
+        (new AppParams())->initFromWhmcsParams();
+        $this->acl()->customTemplate();
+        sl("sidebar")->getSidebar("Service Details Overview")->getChild("customTemplate")->setActive(true);
+        $view = Helper\view();
+        $view->addElement(CustomTemplateDataTable::class);
+
+        return $view;
+    }
+
+
+}

+ 57 - 0
app/Http/Client/Home.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Client;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\AccountSummary;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\DetailsContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\ErrorContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Pages\VirtualNetworkDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Pages\VmsDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Http\AbstractClientController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+
+class Home extends AbstractClientController
+{
+
+    use WhmcsParams;
+    use ProductService;
+    use BaseClientController;
+    use UserService;
+
+    public function index()
+    {
+        if ($this->getWhmcsParamByKey('status') != 'Active')
+        {
+            return;
+        }
+
+        if (!ProxmoxAddonValidator::isInstalled())
+        {
+            ProxmoxAddonValidator::isInstalledOrFail();
+        }
+
+        if (!$this->isUser())
+        {
+            return Helper\view()->addElement(ErrorContainer::class);
+        }
+
+        (new AppParams())->initFromWhmcsParams();
+
+        $view = Helper\view();
+        $view->addElement((new AccountSummary())->initGraphs())
+            ->addElement(VmsDataTable::class);
+
+        if ($this->configuration()->isPermissionVirtualNetwork())
+        {
+            $view->addElement(VirtualNetworkDataTable::class);
+        }
+        return $view;
+    }
+
+
+}

+ 72 - 0
app/Http/Client/SshKey.php

@@ -0,0 +1,72 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Client;
+
+use ModulesGarden\ProxmoxAddon\App\Models\KeyPair;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\DetailsContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Http\AbstractClientController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+
+
+class SshKey extends AbstractClientController
+{
+
+    use WhmcsParams;
+    use ProductService;
+    use BaseClientController;
+    use UserService;
+
+
+    public function sshPublicKeyDownload()
+    {
+        $response = new StreamedResponse();
+        $response->setStatusCode(200);
+        $response->headers->set('Content-Type', 'application/x-pem-file; charset=utf-8');
+        $response->headers->set('Content-Transfer-Encoding', 'Binary');
+        $response->setCallback(function ()
+        {
+            /**
+             * @var $keyPair KeyPair
+             */
+            $keyPair = KeyPair::ofHostingId($this->getWhmcsParamByKey("serviceid"))
+                ->ofVmId($this->getRequestValue('vm'))
+                ->firstOrFail();
+            echo $keyPair->getPublic();
+        });
+        $response->headers->set(
+            'Content-Disposition', 'attachment; filename="id_rsa.pub"'
+        );
+        $response->send();
+    }
+
+    public function sshPrivateKeyDownload()
+    {
+        $response = new StreamedResponse();
+        $response->setStatusCode(200);
+        $response->headers->set('Content-Type', 'application/x-pem-file; charset=utf-8');
+        $response->headers->set('Content-Transfer-Encoding', 'Binary');
+        $response->setCallback(function ()
+        {
+            /**
+             * @var $keyPair KeyPair
+             */
+            $keyPair = KeyPair::ofHostingId($this->getWhmcsParamByKey("serviceid"))
+                ->ofVmId($this->getRequestValue('vm'))
+                ->firstOrFail();
+            echo $keyPair->getPrivate();
+            //delete private key
+            if ($this->configuration()->isSshDeletePrivateKey())
+            {
+                $keyPair->setPrivate(null);
+                $keyPair->save();
+            }
+        });
+        $response->headers->set(
+            'Content-Disposition', 'attachment; filename="id_rsa"'
+        );
+        $response->send();
+    }
+}

+ 87 - 0
app/Http/Client/Vm.php

@@ -0,0 +1,87 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Client;
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\ProxmoxAddonValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages\ServiceCpuGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages\VmSmallGraphs;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\AccountSummary;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\AccountSummaryBars;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\ServiceActions;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\ServiceDetails;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vm\Pages\VmTabs;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Forms\VmCreateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Forms\VmUpdateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Http\AbstractClientController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\view;
+
+class Vm extends AbstractClientController
+{
+    use WhmcsParams;
+    use ProductService;
+    use BaseClientController;
+    use ApiService;
+
+    /**
+     * details
+     */
+    public function index()
+    {
+        if ($this->getWhmcsParamByKey('status') != 'Active')
+        {
+            return;
+        }
+        $this->initVm();
+        (new AppParams())->initFromWhmcsParams();
+        $this->api();
+        if (!ProxmoxAddonValidator::isInstalled())
+        {
+            ProxmoxAddonValidator::isInstalledOrFail();
+        }
+        else
+        {
+            if (!$this->isVmCreated(\ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()))
+            {
+                return $this->onVpsBuild();
+            }
+        }
+        $view = view();
+        $view->initCustomAssetFiles();
+        $view->addElement(ServiceDetails::class);
+        $view->addElement(ServiceActions::class);
+        $view->addElement(VmTabs::class);
+
+        return $view;
+    }
+
+    public function create()
+    {
+        sl("sidebar")->getSidebar("virtualMachinesProxmoxCloudVps")->getChild("vmcreate")->setActive(true);
+        (new AppParams())->initFromWhmcsParams();
+        $view = view();
+        $view->initCustomAssetFiles();
+        /**
+         * @deprecated
+         *     $view->addElement(\ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\AccountSummary::class);
+         */
+
+        return $view->addElement(VmCreateForm::class);
+    }
+
+    public function update()
+    {
+//        sl("sidebar")->getSidebar("virtualMachinesProxmoxCloudVps")->getChild("vmupdate")->setActive(true);
+        $this->initVm();
+        (new AppParams())->initFromWhmcsParams();
+        $this->api();
+        return view()->addElement(VmUpdateForm::class);
+    }
+
+}

+ 50 - 0
app/UI/AccountSummary/Providers/AccountSummaryProvider.php

@@ -0,0 +1,50 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\AccountSummary\Providers;
+
+
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\di;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+
+class AccountSummaryProvider
+{
+    public function read()
+    {
+        $resourceManager = new ResourceManager();
+
+        $this->data['bars']    = [
+            [
+                'name'  => di('lang')->abtr('memory'),
+                'value' => $resourceManager->memory()->getPercent(),
+                'used'  => $resourceManager->memory()->getUsed(),
+                'max'   => $resourceManager->memory()->getTotal(),
+                'unit'  => di('lang')->abtr('MB'),
+            ],
+            [
+                'name'  => di('lang')->abtr('vcpu'),
+                'value' => $resourceManager->vcpus()->getPercent(),
+                'used'  => $resourceManager->vcpus()->getUsed(),
+                'max'   => $resourceManager->vcpus()->getTotal(),
+                'unit'  => di('lang')->abtr('cores'),
+            ],
+            [
+                'name'  => di('lang')->abtr('disk'),
+                'value' => $resourceManager->disk()->getPercent(),
+                'used'  => $resourceManager->disk()->getUsed(),
+                'max'   => $resourceManager->disk()->getTotal(),
+                'unit'  => di('lang')->abtr('GB'),
+            ],
+            [
+                'name'  => di('lang')->abtr('networks'),
+                'value' => $resourceManager->virtualNetworks()->getPercent(),
+                'used'  => $resourceManager->virtualNetworks()->getUsed(),
+                'max'   => $resourceManager->virtualNetworks()->getTotal(),
+                'unit'  => ''
+            ]
+        ];
+
+        return $this->data['bars'];
+    }
+}

+ 22 - 0
app/UI/Admin/AccountResources/AccountResourcesContainer.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\AccountResources;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\AccountSummary\Providers\AccountSummaryProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Builder\BaseContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class AccountResourcesContainer extends BaseContainer implements AdminArea, ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('accountResourcesContainer');
+        $provider = new AccountSummaryProvider();
+        $this->customTplVars['bars'] = $provider->read();
+    }
+
+}

+ 89 - 0
app/UI/Admin/IpSet/Pages/IpSetDataTable.php

@@ -0,0 +1,89 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\IpSet\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+
+class IpSetDataTable extends DataTable implements AdminArea
+{
+    use ProductService;
+    use ApiService;
+
+    protected $id = 'ipSetDataTable';
+    protected $title = 'ipSetDataTable';
+    protected $searchable = false;
+    protected $tableLength = "100";
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('name')))
+            ->addColumn((new Column('comment')))
+            ->addColumn((new Column('ipCidr')));
+    }
+
+    public function replaceFieldIpCidr($key, $row)
+    {
+        return $row[$key] ? $row[$key] : '-';
+    }
+
+    protected function loadData()
+    {
+        $data = [];
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        foreach ($vm->getIpSet() as $ipSet)
+        {
+            $cidr = [];
+            foreach ($ipSet->getIpCidr() as $ipCidr)
+            {
+                $cidr[] = $ipCidr->getCidr();
+            }
+            $data[] = [
+                "name"    => $ipSet->getName(),
+                "comment" => $ipSet->getComment(),
+                "ipCidr"  => implode(", ", $cidr)
+            ];
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+
+    public function initContent()
+    {
+
+    }
+
+    public function isViewFooter()
+    {
+        return false;
+    }
+
+    public function isViewTopBody()
+    {
+        return false;
+    }
+
+}

+ 34 - 0
app/UI/Admin/Product/Buttons/VirtualizationChangButton.php

@@ -0,0 +1,34 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Buttons;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Modals\VirtualizationChangeModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+
+class VirtualizationChangButton extends ButtonCreate implements AdminArea
+{
+    protected $title = null;
+    protected $name = 'virtualizationChangButton';
+
+    public function initContent()
+    {
+        $this->htmlAttributes['style'] = "display: none;";
+        $this->htmlAttributes['id']    = "virtualizationChangButton";
+        $this->initLoadModalAction(new VirtualizationChangeModal());
+    }
+
+    public function loadDataToForm()
+    {
+
+    }
+
+    public function getSections()
+    {
+
+    }
+
+
+}

+ 137 - 0
app/UI/Admin/Product/Forms/MainForm.php

@@ -0,0 +1,137 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Buttons\VirtualizationChangButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Providers\ProductProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\AdminNotificationSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\BackupSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\ClientNotificationSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\ConsoleSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\CpuPrioritySection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\FirewallOptionSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\FirewallSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\HighAvailabilityClusterSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\LoadBalancerSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Lxc;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\MainSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\MiscellaneousSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\UserSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\MainContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\FormIntegration;
+
+class MainForm extends FormIntegration implements AdminArea
+{
+
+    public function initContent()
+    {
+       /**
+         *
+         */
+        $this->initIds('mainForm');
+        $this->setProvider(new ProductProvider($this->getRequestValue('id')));
+        $this->addSection(new VirtualizationChangButton());
+        $this->dataProvider->initData();
+        /**
+         *
+         */
+        $isQemu = !$this->dataProvider->getValueById('customconfigoption[virtualization]') || $this->dataProvider->getValueById('customconfigoption[virtualization]') == "qemu";
+        /**
+         * Main Section
+         */
+        $section = new MainSection();
+        $section->setMainContainer($this->mainContainer);
+        $this->addSection($section);
+
+        if ($isQemu)
+        {
+            // KVM
+            $this->addSection((new Qemu\DefaultConfigurationSection())->enableToggler())
+                ->addSection((new Qemu\ServerSection())->enableToggler())
+                ->addSection((new Qemu\NetworkSection())->enableToggler())
+                ->addSection((new Qemu\DiskSection())->enableToggler())
+                ->addSection((new Qemu\DiskSpeedSection())->enableTogglerAndHide())
+                ->addSection((new Qemu\AdditonalDisk())->enableToggler())
+                ->addSection((new Qemu\AdditonalDiskSpeedSection())->enableToggler())
+                ->addSection((new BackupSection())->enableToggler())
+                ->addSection((new Qemu\BootSection())->enableTogglerAndHide())
+                ->addSection((new FirewallSection())->enableTogglerAndHide())
+                ->addSection((new FirewallOptionSection())->enableTogglerAndHide())
+                ->addSection((new Qemu\CloudInitSection())->enableTogglerAndHide())
+                ->addSection((new Qemu\GuestAgentSection())->enableTogglerAndHide())
+                ->addSection((new UserSection())->enableTogglerAndHide())
+                ->addSection((new MiscellaneousSection())->enableTogglerAndHide())
+                ->addSection((new LoadBalancerSection())->enableTogglerAndHide())
+                ->addSection((new Qemu\ConfigurationSection())->enableTogglerAndHide())
+                ->addSection((new Qemu\AdvancedSection())->enableTogglerAndHide())
+                ->addSection((new HighAvailabilityClusterSection())->enableTogglerAndHide())
+                ->addSection((new ConsoleSection())->enableTogglerAndHide())
+                ->addSection((new Qemu\ClientAreaSection())->enableToggler())
+                ->addSection((new Qemu\ConfigurableOptionUnitsSection())->enableToggler());
+        }
+        else
+        {
+            //LXC
+            $this->addSection((new Lxc\DefaultConfigurationSection())->enableToggler())
+                ->addSection((new Lxc\ServerSection())->enableToggler())
+                ->addSection((new Lxc\MountPointSection())->enableToggler())
+                ->addSection((new BackupSection())->enableToggler())
+                ->addSection((new Lxc\NetworkSection())->enableToggler())
+                ->addSection((new FirewallSection())->enableTogglerAndHide())
+                ->addSection((new FirewallOptionSection())->enableTogglerAndHide())
+                ->addSection((new UserSection())->enableTogglerAndHide())
+                ->addSection((new MiscellaneousSection())->enableTogglerAndHide())
+                ->addSection((new LoadBalancerSection())->enableTogglerAndHide())
+                ->addSection((new Lxc\ConfigurationSection())->enableTogglerAndHide())
+                ->addSection((new HighAvailabilityClusterSection())->enableTogglerAndHide())
+                ->addSection((new ConsoleSection())->enableTogglerAndHide())
+                ->addSection((new Lxc\ClientAreaSection())->enableToggler())
+                ->addSection((new Lxc\ConfigurableOptionUnitsSection())->enableToggler());
+        }
+        $this->addSection((new CpuPrioritySection())->enableToggler());
+        $this->loadDataToForm();
+    }
+
+    public function getSwitcherFields()
+    {
+        $this->setMainContainer(new MainContainer());
+        $this->runInitContentProcess();
+        $fieldNames = [];
+        foreach ($this->getSections() as $section)
+        {
+            foreach ($section->getSections() as $s)
+            {
+                foreach ($s->getFields() as $field)
+                {
+                    if (!$field instanceof Switcher)
+                    {
+                        continue;
+                    }
+                    $name         = str_replace(["customconfigoption[", "]"], ["", ""], $field->getName());
+                    $fieldNames[] = $name;
+                }
+            }
+        }
+        return array_unique($fieldNames);
+    }
+}

+ 34 - 0
app/UI/Admin/Product/Forms/VirtualizationChangeForm.php

@@ -0,0 +1,34 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+
+
+class VirtualizationChangeForm extends BaseForm implements AdminArea
+{
+    public function initContent()
+    {
+        $this->initIds('virtualizationChangeForm');
+        $this->setConfirmMessage('confirmVirtualizationChange');
+    }
+
+}

+ 53 - 0
app/UI/Admin/Product/Modals/VirtualizationChangeModal.php

@@ -0,0 +1,53 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Forms\VirtualizationChangeForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ModalActionButtons\BaseAcceptButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ModalActionButtons\BaseCancelButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmSuccess;
+
+class VirtualizationChangeModal extends ModalConfirmSuccess implements AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('virtualizationChangeModal');
+        $this->addForm(new VirtualizationChangeForm());
+    }
+
+
+    protected function initActionButtons()
+    {
+        if (!empty($this->actionButtons))
+        {
+            return $this;
+        }
+        $acceptButton = new BaseAcceptButton;
+        $acceptButton->deleteHtmlAttribute('@click');
+        $acceptButton->addClass('virtualizationChangeConfirmButton');
+        $this->addActionButton($acceptButton);
+        $this->addActionButton(new BaseCancelButton);
+
+        return $this;
+    }
+
+}

+ 482 - 0
app/UI/Admin/Product/Providers/ProductProvider.php

@@ -0,0 +1,482 @@
+<?php
+/**********************************************************************
+ * ProxmoxVPS developed. (26.03.19)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ **********************************************************************/
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Providers;
+
+use MGProvision\Proxmox\v2\models\Node;
+use MGProvision\Proxmox\v2\repository\ClusterResourcesRepository;
+use MGProvision\Proxmox\v2\repository\FileRepository;
+use MGProvision\Proxmox\v2\repository\NodeRepository;
+use MGProvision\Proxmox\v2\repository\StorageRepository;
+use ModulesGarden\ProxmoxAddon\App\Models\CloudInitScript;
+use ModulesGarden\ProxmoxAddon\App\Models\IpAddress;
+use ModulesGarden\ProxmoxAddon\App\Models\ProductConfiguration;
+use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Hosting;
+use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Product;
+use ModulesGarden\ProxmoxAddon\App\Repositories\Cloud\ProductConfigurationRepository;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Enum\JobPeriod;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Forms\MainForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\FileReader\Reader\Json;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Models\Whmcs\EmailTemplate;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ModuleConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class ProductProvider extends BaseDataProvider implements AdminArea
+{
+    use ApiService;
+    use ProductService;
+
+    private $productId;
+
+    /**
+     * @var ProductConfigurationRepository
+     */
+    protected $configuration;
+    /**
+     * @var Node
+     */
+    private $node;
+
+    /**
+     * ProductConfigurationProvider constructor.
+     * @param $productId
+     */
+    public function __construct($productId)
+    {
+        if (!is_numeric($productId)) {
+            throw new \InvalidArgumentException("The product id must be definded.");
+        }
+        $this->configuration = new ProductConfigurationRepository($productId);
+        $this->productId = $productId;
+    }
+
+    public function isSupportedModule()
+    {
+        return Product::where("id", $this->configuration->getProductId())
+                ->where("servertype", "ProxmoxCloudVps")->count() == 1;
+    }
+
+    public function read()
+    {
+        foreach ($this->configuration->all() as $key => $value) {
+            if ($key == "serverSockets") {
+
+
+            }
+            //multiselect
+            if (is_array($value)) {
+                $this->data[sprintf("customconfigoption[%s][]", $key)] = $value;
+                continue;
+            }
+
+            if (is_null($value)) {
+                $value = "";
+            }
+            $this->data[sprintf("customconfigoption[%s]", $key)] = $value;
+        }
+        $this->initApi();
+        $this->defaultRead();
+        if (!$this->configuration->getVirtualization() || $this->configuration->isQemu()) {
+            //kvm
+            $this->qemuRead();
+        } else {
+            //lxc
+            $this->lxcRead();
+        }
+    }
+
+    private function initApi()
+    {
+        $lang = sl("lang");
+        $product = Product::where("id", $this->productId)->firstOrFail();
+        sl("whmcsParams")->setParams($product->getParams());
+    }
+
+    private function defaultRead()
+    {
+        $lang = sl("lang");
+        //Virtualization
+        $this->availableValues["customconfigoption[virtualization]"] = ["qemu" => $lang->tr("KVM"), "lxc" => $lang->tr("LXC")];
+        if ($this->getWhmcsParamByKey('packageid') && Hosting::ofProductId($this->getWhmcsParamByKey('packageid'))->activeAndSuspended()->count()) {
+            if ($this->configuration->isQemu()) {
+                unset($this->availableValues["customconfigoption[virtualization]"]["lxc"]);
+            } else {
+                unset($this->availableValues["customconfigoption[virtualization]"]["qemu"]);
+            }
+        }
+        //Default Node
+        $this->availableValues["customconfigoption[defaultNode]"] = ["serverNode" => $lang->tr('Server-Node'), "autoNode" => $lang->tr('Auto-Node')];
+        $nodeRepository = new NodeRepository();
+        $nodeRepository->setApi($this->api());
+        $nodeRepository->findOnline(true);
+        foreach ($nodeRepository->fetch() as $node) {
+            $this->availableValues["customconfigoption[defaultNode]"][$node->getNode()] = $node->getNode();
+            //locations
+            $this->availableValues["customconfigoption[locations][]"][$node->getNode()] = $node->getNode();
+        }
+        //realm
+        foreach ($this->api()->get("/access/domains") as $d) {
+            if (!$d['realm']) {
+                continue;
+            }
+            $this->availableValues["customconfigoption[realm]"][$d['realm']] = $lang->tr($d['comment']);
+        }
+        //userRole
+        foreach ($this->api()->get("/access/roles") as $r) {
+            if (!$r['roleid']) {
+                continue;
+            }
+            $this->availableValues["customconfigoption[userRole]"][$r['roleid']] = $lang->tr($r['roleid']);
+        }
+        //welcomeEmailTemplateId
+        $this->availableValues["customconfigoption[welcomeEmailTemplateId]"][0] = "";
+        foreach (EmailTemplate::where('type', "product")->pluck("name", "id")->all() as $key => $value) {
+            $this->availableValues["customconfigoption[welcomeEmailTemplateId]"][$key] = $value;
+        }
+        //reinstallEmailTemplateId
+        $this->availableValues["customconfigoption[reinstallEmailTemplateId]"][0] = "";
+        foreach (EmailTemplate::where('type', "product")->pluck("name", "id")->all() as $key => $value) {
+            $this->availableValues["customconfigoption[reinstallEmailTemplateId]"][$key] = $value;
+        }
+        //upgradeNotificationTemplateId
+        $this->availableValues["customconfigoption[serviceCreationFailedTemplateId]"][0] = "";
+        foreach (EmailTemplate::where('type', "admin")->where("custom", 1)->pluck("name", "id")->all() as $key => $value) {
+            $this->availableValues["customconfigoption[serviceCreationFailedTemplateId]"][$key] = $value;
+        }
+        //upgradeNotificationTemplateId
+        $this->availableValues["customconfigoption[upgradeNotificationTemplateId]"] = $this->availableValues["customconfigoption[serviceCreationFailedTemplateId]"];
+        //loadBalancerOnUpgrade
+        $this->availableValues["customconfigoption[loadBalancerOnUpgrade]"] = ['0' => $lang->tr('None'), "block" => $lang->tr("Block"), "migrate" => $lang->tr("Migrate")];
+        //backupStorage
+        if (in_array($this->configuration->getDefaultNode(), $this->availableValues["customconfigoption[defaultNode]"])) {
+            $this->node = new Node($this->configuration->getDefaultNode());
+        } else {//"Auto-Node" or 'Server-Node' or empty
+
+            $servePrivateIP = $this->getServerPrivateIpAddress();
+            $serverIp = $servePrivateIP ? $servePrivateIP : $this->getWhmcsParamByKey('serverip');
+            $this->node = $nodeRepository->findWithHostOrIp($this->getWhmcsParamByKey('serverhostname'), $serverIp);
+        }
+        $this->node->setApi($this->api());
+        $storageRepository = new StorageRepository();
+        $storageRepository->findByNodes([$this->node->getNode()])
+            ->findEnabed();
+        foreach ($storageRepository->fetch() as $entity) {
+            if (!in_array("backup", $entity->getContentAsArray())) {
+                continue;
+            }
+            $this->availableValues["customconfigoption[backupStorage]"] [$entity->getStorage()] = $lang->tr($entity->getStorage());
+        }
+        //clusterState
+        $this->availableValues["customconfigoption[clusterState]"] = ['' => "", 'started' => $lang->tr('Started'), 'stopped' => $lang->tr('Stopped'), 'enabled' => $lang->tr('Enabled'), 'disabled' => $lang->tr('Disabled'), 'ignored' => $lang->tr('Ignored')];
+        //firewallInterfaces
+        $this->availableValues["customconfigoption[firewallInterfaces][]"] = ["venet" => $lang->tr("venet"), "eth" => $lang->tr("eth\d+")];
+        //clusterGroup
+        $this->availableValues["customconfigoption[clusterGroup]"] = ['' => ""];
+        foreach ($this->api()->get('/cluster/ha/groups') as $g) {
+            $this->availableValues["customconfigoption[clusterGroup]"][$g['group']] = ucfirst($g['group']);
+        }
+        //suspensionAction
+        $this->availableValues["customconfigoption[suspensionAction]"] = ['0' => $lang->tr('Default'), "stop" => $lang->tr('Stop VM'), 'shutdown' => $lang->tr('Shutdown VM')];
+        if ($this->configuration()->isQemu()) {
+            $this->availableValues["customconfigoption[suspensionAction]"]["suspend"] = $lang->tr("Pause VM");
+            $this->availableValues["customconfigoption[suspensionAction]"]["hibernate"] = $lang->tr("Hibernate VM");
+        }
+        //tag
+        $this->availableValues["customconfigoption[tags][]"];
+        foreach (IpAddress::select("tag")->whereNotNull("tag")->where("tag", ">", o)->groupBy("tag")->pluck("tag")->all() as $tag) {
+            $this->availableValues["customconfigoption[tags][]"][$tag] = $tag;
+        }
+        //pool
+        $this->availableValues["customconfigoption[pool]"] = [""];
+        foreach ($this->api()->get('/pools') as $pool) {
+            $this->availableValues["customconfigoption[pool]"][$pool['poolid']] = $lang->tr($pool['poolid']);
+        }
+        //permissionFirewalOptions
+        $this->availableValues["customconfigoption[permissionFirewalOptions][]"] = [
+            "enable" => $lang->abtr("Enable/Disable Firewall"),
+            "dhcp" => $lang->abtr("DHCP"),
+            "radv" => $lang->abtr("Allow Router Advertisement"),
+            "ndp" => $lang->abtr("NDP"),
+            "macfilter" => $lang->abtr("MAC Filter"),
+            "ipfilter" => $lang->abtr("IP Filter"),
+        ];
+        //buttonSyle
+        $this->availableValues["customconfigoption[buttonSyle]"] = ["tiles" => $lang->tr('Tiles'), 'buttons' => $lang->tr('Buttons'),];
+        //detailsView
+        $this->availableValues["customconfigoption[detailsView]"] = ["standard" => $lang->tr('Standard'),
+            'combined' => $lang->tr('Combined'),];
+
+    }
+
+    /**
+     * KVM
+     */
+    private function qemuRead()
+    {
+        $lang = sl("lang");
+        //ostype
+        $ostype = new Json('ostype.json', ModuleConstants::getFullPathWhmcs('modules', 'addons', 'proxmoxAddon', 'storage', 'app'));
+        foreach ($ostype->get() as $k => $ostype) {
+            $this->availableValues["customconfigoption[ostype]"][$k] = $lang->abtr('ostype', $ostype);
+            $this->availableValues["customconfigoption[permissionOstype][]"][$k] = $lang->abtr($ostype);
+        }
+        //hotplug
+        $this->availableValues["customconfigoption[hotplug][]"] = ["disk" => $lang->tr('disk'), "network" => $lang->tr('network'), "usb" => $lang->tr('usb'), "cpu" => $lang->tr('cpu'), "memory" => $lang->tr('memory')];
+        //keyboard
+        $this->availableValues["customconfigoption[keyboard]"] = ['', 'pt' => $lang->tr('pt'), "tr" => $lang->tr('tr'), 'ja' => $lang->tr('ja'), 'es' => $lang->tr('es'), 'no' => $lang->tr('no'), 'is' => $lang->tr('is'), 'fr-ca' => $lang->tr('fr-ca'), 'fr' => $lang->tr('fr'), 'pt-br' => $lang->tr('pt-br'), 'da' => $lang->tr('da'), 'fr-ch' => $lang->tr('fr-ch'), 'sl' => $lang->tr('sl'), 'de-ch' => $lang->tr('de-ch'), 'en-gb' => $lang->tr('en-gb'), 'it' => $lang->tr('it'), 'en-us' => $lang->tr('en-us'), 'fr-be' => $lang->tr('fr-be'), 'hu' => $lang->tr('hu'), 'pl' => $lang->tr('pl'), 'nl' => $lang->tr('nl'), 'mk' => $lang->tr('mk'), 'fi' => $lang->tr('fi'), 'lt' => $lang->tr('lt'), 'sv' => $lang->tr('sv'), 'de' => $lang->tr('de')];
+        //vga
+        $jsonData = new Json('vga.json', ModuleConstants::getFullPathWhmcs('modules', 'addons', 'proxmoxAddon', 'storage', 'app'));
+        foreach ($jsonData->get() as $k => $name) {
+            $this->availableValues["customconfigoption[vga]"][$k] = $lang->tr($name);
+        }
+        //cloneMode
+        $this->availableValues["customconfigoption[cloneMode]"] = ['1' => $lang->tr('Full Clone'), "0" => $lang->tr("Linked Clone")];
+        //diskStorage images (Disk Images)
+        $storageRepository = new StorageRepository();
+        $storageRepository->findByNodes([$this->node->getNode()])
+            ->findEnabed();
+        foreach ($storageRepository->fetch() as $entity) {
+            if (!in_array("images", $entity->getContentAsArray())) {
+                continue;
+            }
+            $this->availableValues["customconfigoption[diskStorage]"] [$entity->getStorage()] = $lang->tr($entity->getStorage());
+            $this->availableValues["customconfigoption[additionalDiskStorage]"] [$entity->getStorage()] = $lang->tr($entity->getStorage());
+        }
+        //diskType
+        $this->availableValues["customconfigoption[diskType]"] = ["ide" => $lang->abtr('ide'), "sata" => $lang->abtr('sata'), "virtio" => $lang->abtr('virtio'), "scsi" => $lang->abtr('scsi')];
+        //diskFormat
+        $this->availableValues["customconfigoption[diskFormat]"] = ['raw' => $lang->abtr('raw'), 'qcow2' => $lang->abtr('qcow2'), 'vmdk' => $lang->abtr('vmdk')];
+        //diskCache
+        $this->availableValues["customconfigoption[diskCache]"] = ['none' => $lang->tr('Default (No Cache)'), 'writethrough' => $lang->tr('Write Through'), 'writeback' => $lang->tr('Write Back'), 'unsafe' => $lang->tr('Write Back (Unsafe)'), 'directsync' => $lang->tr('Direct Sync')];
+        //scsihw
+        $this->availableValues["customconfigoption[scsihw]"] = [
+            '0' => $lang->abtr('Default (LSI 53C895A)'),
+            "lsi" => $lang->abtr('LSI 53C895A'),
+            "lsi53c810" => $lang->abtr('LSI 53C810'),
+            'virtio-scsi-pci' => $lang->abtr('VirtIO SCSI'),
+            "virtio-scsi-single" => $lang->abtr('VirtIO SCSI single'),
+            'megasas' => $lang->abtr('MegaRAID SAS 8708EM2'),
+            "pvscsi" => $lang->abtr('VMware PVSCSI'),
+        ];
+        //additionalDiskStorage
+        $this->availableValues["customconfigoption[additionalDiskStorage]"] = $this->availableValues["customconfigoption[diskStorage]"];
+        //additionalDiskType
+        $this->availableValues["customconfigoption[additionalDiskType][]"] = $this->availableValues["customconfigoption[diskType]"];
+        //additionalDiskFormat
+        $this->availableValues["customconfigoption[additionalDiskFormat][]"] = $this->availableValues["customconfigoption[diskFormat]"];
+        if ($this->configuration->getAdditionalDiskStorage() && preg_match("/lvm/", $this->configuration->getAdditionalDiskStorage())) {
+            $this->disabledList["customconfigoption[additionalDiskFormat][]"] = ['qcow2', 'vmdk'];
+        }
+        //additionalDiskCache
+        $this->availableValues["customconfigoption[additionalDiskCache]"] = $this->availableValues["customconfigoption[diskCache]"];
+        //networkModel
+        $this->availableValues["customconfigoption[networkModel]"] = ['e1000' => $lang->tr('e1000'), 'i82551' => $lang->tr('i82551'), 'i82557b' => $lang->tr('i82557b'), 'i82559er' => $lang->tr('i82559er'), 'ne2k_isa' => $lang->tr('ne2k_isa'), 'ne2k_pci' => $lang->tr('ne2k_pci'), 'pcnet' => $lang->tr('pcnet'), 'rtl8139' => $lang->tr('rtl8139'), 'virtio' => $lang->tr('virtio'), 'vmxnet3' => $lang->tr('vmxnet3')];
+        //bridge
+        foreach ($this->api()->get("/nodes/{$this->node->getNode()}/network") as $network) {
+            if (!in_array($network['type'], ['bridge', 'OVSBridge'])) {
+                continue;
+            }
+            $this->availableValues["customconfigoption[bridge]"] [$network['iface']] = $lang->tr($network['iface']);
+        }
+        ksort($this->availableValues["customconfigoption[bridge]"]);
+        //privateBridge
+        $this->availableValues["customconfigoption[privateBridge]"] = ['0' => ""] + (array)$this->availableValues["customconfigoption[bridge]"];
+        //networkPrivateModel
+        $this->availableValues["customconfigoption[networkPrivateModel]"] = $this->availableValues["customconfigoption[networkModel]"];
+        //bootDevice1
+        $this->availableValues["customconfigoption[bootDevice1]"] = ['', 'c' => $lang->tr('Hard Disk'), 'd' => $lang->tr('CD-ROM'), 'n' => $lang->tr('Network')];
+        //bootDevice2
+        $this->availableValues["customconfigoption[bootDevice2]"] = $this->availableValues["customconfigoption[bootDevice1]"];
+        //bootDevice3
+        $this->availableValues["customconfigoption[bootDevice3]"] = $this->availableValues["customconfigoption[bootDevice1]"];
+        //permissionOsTemplates
+        $clusterResourcesRepository = new ClusterResourcesRepository();
+        $clusterResourcesRepository->setApi($this->api());
+        $clusterResourcesRepository->findKvmTemplate();
+        foreach ($clusterResourcesRepository->fetch() as $resurce) {
+            if (preg_match('/^custom[0-9]*/', $resurce->getName())) {
+                continue;
+            }
+            $this->availableValues["customconfigoption[permissionOsTemplates][]"][$resurce->getName()] = $lang->abtr('template', $resurce->getName());
+        }
+        //osTemplate
+        $this->availableValues["customconfigoption[osTemplate]"] = ['0' => ""] + (array)$this->availableValues["customconfigoption[permissionOsTemplates][]"];
+        //permissionIsoImage
+        $fileRepository = new FileRepository();
+        $fileRepository->setApi($this->api());
+        $fileRepository->findIso();
+        $fileRepository->findByNode($this->node);
+        $fileRepository->findByStorages($storageRepository->fetchAsArray());
+        foreach ($fileRepository->fetch() as $file) {
+            $this->availableValues["customconfigoption[permissionIsoImages][]"][$file->getVolid()] = $lang->tr($file->getFriendlyName());
+            $this->availableValues["customconfigoption[permissionSecondaryIsoImages][]"][$file->getVolid()] = $lang->tr($file->getFriendlyName());
+        }
+        //isoImage
+        $this->availableValues["customconfigoption[isoImage]"] = ["none" => $lang->tr("None")] + (array)$this->availableValues["customconfigoption[permissionIsoImages][]"];
+
+        //memoryUnit
+        $this->availableValues["customconfigoption[memoryUnit]"] = ['mb' => $lang->tr("MB"), "gb" => $lang->tr("GB")];
+        //storageUnit
+        $this->availableValues["customconfigoption[storageUnit]"] = ['mb' => $lang->tr("MB"), "gb" => $lang->tr("GB"), "tb" => $lang->tr("TB")];
+        //cdromType
+        $this->availableValues["customconfigoption[cdromType]"] = $this->availableValues["customconfigoption[diskType]"];
+        //bios
+        $this->availableValues["customconfigoption[bios]"] = [
+            '0' => "",
+            'seabios' => $lang->tr('SeaBIOS'),
+            'ovmf' => $lang->tr('OVMF (UEFI)')
+        ];
+        //cloudInitScript
+        $this->availableValues["customconfigoption[cloudInitScript][]"] = CloudInitScript::pluck('name', 'id')->toArray();
+        //machine
+        $jsonData = new Json('machine.json', ModuleConstants::getFullPathWhmcs('modules', 'addons', 'proxmoxAddon', 'storage', 'app'));
+        foreach ($jsonData->get() as $k => $name) {
+            $this->availableValues["customconfigoption[machine]"][$k] = $lang->tr($name);
+        }
+        //cpu
+        $jsonData = new Json('cpu.json', ModuleConstants::getFullPathWhmcs('modules', 'addons', 'proxmoxAddon', 'storage', 'app'));
+        foreach ($jsonData->get() as $k => $name) {
+            $this->availableValues["customconfigoption[cpu]"][$k] = $lang->tr($name);
+        }
+
+    }
+
+    /**
+     * LXC
+     */
+    private function lxcRead()
+    {
+        $lang = sl("lang");
+        //storage
+        $storageRepository = new StorageRepository();
+        $storageRepository->findByNodes([$this->node->getNode()])
+            ->findEnabed();
+        foreach ($storageRepository->fetch() as $storage) {
+            if (!in_array("rootdir", $storage->getContentAsArray())) {
+                continue;
+            }
+            $this->availableValues["customconfigoption[storage]"][$storage->getStorage()] = $lang->tr($storage->getStorage());
+        }
+        //arch
+        $this->availableValues["customconfigoption[arch]"] = ['0' => "", 'amd64' => $lang->tr("AMD64"), $lang->tr("i386") => $lang->tr("i386")];
+        //cmode
+        $this->availableValues["customconfigoption[cmode]"] = ['0' => "", 'shell' => $lang->tr("shell"), "console" => $lang->tr("console"), "tty" => $lang->tr("tty")];
+        //ostype
+        $this->availableValues["customconfigoption[ostype]"] = ['0' => "", 'debian' => $lang->tr("Debian"), "ubuntu" => $lang->tr("Ubuntu"), "centos" => $lang->tr("centos"), "archlinux" => $lang->tr("Archlinux")];
+        //osTemplate
+        $fileRepository = new FileRepository();
+        $fileRepository->setApi($this->api());
+        $fileRepository->findLxcTemplates();
+        $fileRepository->findByNode($this->node);
+        $fileRepository->findByStorages($storageRepository->fetchAsArray());
+        foreach ($fileRepository->fetch() as $file) {
+            $this->availableValues["customconfigoption[osTemplate]"][$file->getVolid()] = $lang->tr($file->getFriendlyName());
+        }
+        //memoryUnit
+        $this->availableValues["customconfigoption[memoryUnit]"] = ['mb' => $lang->tr("MB"), "gb" => $lang->tr("GB")];
+        //storageUnit
+        $this->availableValues["customconfigoption[storageUnit]"] = ['mb' => $lang->tr("MB"), "gb" => $lang->tr("GB"), "tb" => $lang->tr("TB")];
+        //persimonOsTemplates
+        $this->availableValues["customconfigoption[permissionOsTemplates][]"] = $this->availableValues["customconfigoption[osTemplate]"];
+        //mountPointStorage
+        foreach ($storageRepository->fetch() as $entity) {
+            if (!in_array("rootdir", $entity->getContentAsArray())) {
+                continue;
+            }
+            $this->availableValues["customconfigoption[mountPointStorage]"][$entity->getStorage()] = $lang->tr($entity->getStorage());
+        }
+        //mountPointAcl
+        $this->availableValues["customconfigoption[mountPointAcl]"] = ["default" => $lang->tr('Default'), "1" => $lang->tr("On"), "0" => $lang->tr("Off")];
+        //ipv4NetworkMode
+        $this->availableValues["customconfigoption[ipv4NetworkMode]"] = ["static" => $lang->tr('Static'), "dhcp" => $lang->tr("DHCP")];
+        //ipv6NetworkMode
+        $this->availableValues["customconfigoption[ipv6NetworkMode]"] = ["static" => $lang->tr('Static'), "dhcp" => $lang->tr("DHCP"), "slaac" => $lang->tr("SLAAC")];
+        //swapUnit
+        $this->availableValues["customconfigoption[swapUnit]"] = ['mb' => $lang->tr("MB"), $lang->tr("gb") => $lang->tr("GB"), "tb" => $lang->tr("TB")];
+        //bridge
+        foreach ($this->api()->get("/nodes/{$this->node->getNode()}/network") as $network) {
+            if (!in_array($network['type'], ['bridge', 'OVSBridge'])) {
+                continue;
+            }
+            $this->availableValues["customconfigoption[bridge]"] [$network['iface']] = $lang->tr($network['iface']);
+        }
+        ksort($this->availableValues["customconfigoption[bridge]"]);
+        //privateBridge
+        $this->availableValues["customconfigoption[privateBridge]"] = ['0' => ""] + (array)$this->availableValues["customconfigoption[bridge]"];
+    }
+
+    public function update()
+    {
+        $this->loadRequestObj();
+        if (empty($this->request->get('customconfigoption'))) {
+            return;
+        }
+        try {
+            $form = new MainForm();
+            $switcherFields = $form->getSwitcherFields();
+            $values = $this->request->get('customconfigoption');
+            if (!$values['locations']) {
+                $values['locations'] = [];
+            }
+            foreach ($values as $k => $v) {
+                if (in_array($k, $switcherFields)) {
+                    unset($switcherFields[array_search($k, $switcherFields)]);
+                }
+            }
+            foreach ($switcherFields as $switch) {
+                $values[$switch] = "off";
+            }
+        } catch (\Exception $ex) {
+            //login to proxmox host failed
+        }
+        //delete
+        $this->configuration->flush();
+        sleep(1);
+        //save
+        $this->configuration->fillAndSave($values);
+
+    }
+
+    public function delete()
+    {
+        $this->configuration->flush();
+    }
+
+    public function replicate($replicateProductId)
+    {
+        $_SESSION['ProxmoxCloudVps'] = null;
+        if (ProductConfiguration::ofProductId($this->productId)->count()) {
+            return;
+        }
+        /**
+         * @var $entity ProductConfiguration
+         */
+        foreach (ProductConfiguration::ofProductId($replicateProductId)->get() as $entity) {
+            $newEntity = new ProductConfiguration();
+            $newEntity->setting = $entity->setting;
+            $newEntity->value = $entity->value;
+            $newEntity->product_id = $this->productId;
+            $newEntity->save();
+        }
+    }
+}

+ 52 - 0
app/UI/Admin/Product/Sections/BackupSection.php

@@ -0,0 +1,52 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class BackupSection extends BoxSection implements AdminArea
+{
+    protected $id = 'backupSection';
+    protected $name = 'backupSection';
+    protected $title = 'backupSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //Storage
+        $field = new Select('customconfigoption[backupStorage]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Backups Routing
+        $field = new Switcher('customconfigoption[backupRouting]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->rightSection->addField($field);
+        //Store The Backup For X Days
+        $field = new Text('customconfigoption[backupStoreDays]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+    }
+
+}

+ 43 - 0
app/UI/Admin/Product/Sections/ConfigurableOptionUnitSection.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class ConfigurableOptionUnitSection extends BoxSection implements AdminArea
+{
+    protected $id = 'configurableOptionUnitSection';
+    protected $name = 'configurableOptionUnitSection';
+    protected $title = 'configurableOptionUnitSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSectionsdf');
+        $this->rightSection = new HalfPageSection('rightSectionsdf');
+
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //One User Per VPS
+        $field = new Switcher('customconfigoption[oneUserPerVps]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->leftSection->addField($field);
+    }
+
+}

+ 42 - 0
app/UI/Admin/Product/Sections/ConsoleSection.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class ConsoleSection extends BoxSection implements AdminArea
+{
+    protected $id = 'consoleSection';
+    protected $name = 'consoleSection';
+    protected $title = 'consoleSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //Additional IP Address For VNC Console
+        $field = new Text('customconfigoption[consoleHost]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+
+    }
+
+}

+ 73 - 0
app/UI/Admin/Product/Sections/CpuPrioritySection.php

@@ -0,0 +1,73 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+class CpuPrioritySection extends TwiceColumnSection implements AdminArea
+{
+
+    protected $id = 'cpuPrioritySection';
+    protected $name = 'cpuPrioritySection';
+    protected $title = 'cpuPrioritySection';
+
+
+    public function initFields()
+    {
+        //1: very low-> CPU Units 256, CPU Limits 0.2
+        $field = new Text('customconfigoption[cpuunitsPriority1]');
+        $field->setDefaultValue(256);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //CPU Limits
+        $field = new Text('customconfigoption[cpulimitPriority1]');
+        $field->setDefaultValue(0.2);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //2: Low -> CPU Units 512, CPU Limits 0.4
+        $field = new Text('customconfigoption[cpuunitsPriority2]');
+        $field->setDefaultValue(512);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //CPU Limits
+        $field = new Text('customconfigoption[cpulimitPriority2]');
+        $field->setDefaultValue(0.4);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //3: Normal -> CPU Units 712, CPU Limits 0.6
+        $field = new Text('customconfigoption[cpuunitsPriority3]');
+        $field->setDefaultValue(712);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //CPU Limits
+        $field = new Text('customconfigoption[cpulimitPriority3]');
+        $field->setDefaultValue(0.6);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //4: High -> CPU Units 1024, CPU Limits 0.8
+        $field = new Text('customconfigoption[cpuunitsPriority4]');
+        $field->setDefaultValue(1024);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //CPU Limits
+        $field = new Text('customconfigoption[cpulimitPriority4]');
+        $field->setDefaultValue(0.8);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //5: Medium -> CPU Units 1280, CPU Limits 1
+        $field = new Text('customconfigoption[cpuunitsPriority5]');
+        $field->setDefaultValue(1280);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //CPU Limits
+        $field = new Text('customconfigoption[cpulimitPriority5]');
+        $field->setDefaultValue(1);
+        $field->setDescription('tip');
+        $this->addField($field);
+
+    }
+
+}

+ 69 - 0
app/UI/Admin/Product/Sections/FirewallOptionSection.php

@@ -0,0 +1,69 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class FirewallOptionSection extends BoxSection implements AdminArea
+{
+//    protected $id = 'clientNotificationSection';
+//    protected $name = 'clientNotificationSection';
+//    protected $title = 'clientNotificationSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->initIds('firewallOptionSection');
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //enable
+        $field = new Switcher("customconfigoption[firewalOptionEnable]");
+        $this->addField($field);
+        //dhcp
+        $field = new Switcher("customconfigoption[firewalOptionDhcp]");
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //ndp
+        $field = new Switcher("customconfigoption[firewalOptionNdp]");
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //radv
+        $field = new Switcher("customconfigoption[firewalOptionRadv]");
+        $this->addField($field);
+        //macfilter
+        $field = new Switcher("customconfigoption[firewalOptionMacfilter]");
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //ipfilter
+        $field = new Switcher("customconfigoption[firewalOptionIpfilter]");
+        $this->addField($field);
+    }
+
+    public function addField($field){
+        $total = count($this->leftSection->getFields()) + count($this->rightSection->getFields());
+        if($total % 2 == 0){
+            $this->leftSection->addField($field);
+        }else{
+            $this->rightSection->addField($field);
+        }
+        return $this;
+    }
+
+}

+ 57 - 0
app/UI/Admin/Product/Sections/FirewallSection.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class FirewallSection extends BoxSection implements AdminArea
+{
+    protected $id = 'firewallSection';
+    protected $name = 'firewallSection';
+    protected $title = 'firewallSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        /**
+         * @deprecated
+        //Interfaces
+        $field = new Select('customconfigoption[firewallInterfaces][]');
+        $field->setDescription('tip');
+        $field->enableMultiple();
+        $this->leftSection->addField($field);
+         */
+        //Firewall Rules Limit
+        $field = new Text('customconfigoption[firewallMaxRules]');
+        $field->setDefaultValue(10);
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //IPSet IP Filter
+        $field = new Switcher('customconfigoption[ipsetIpFilter]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+    }
+
+}

+ 54 - 0
app/UI/Admin/Product/Sections/HighAvailabilityClusterSection.php

@@ -0,0 +1,54 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class HighAvailabilityClusterSection extends BoxSection implements AdminArea
+{
+    protected $id = 'highAvailabilityClusterSection';
+    protected $name = 'highAvailabilityClusterSection';
+    protected $title = 'highAvailabilityClusterSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //State
+        $field = new Select('customconfigoption[clusterState]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Group
+        $field = new Select('customconfigoption[clusterGroup]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Max. Restart
+        $field = new Text('customconfigoption[clusterMaxRestart]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Max. Relocate
+        $field = new Text('customconfigoption[clusterMaxRelocate]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+    }
+
+}

+ 55 - 0
app/UI/Admin/Product/Sections/LoadBalancerSection.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class LoadBalancerSection extends BoxSection implements AdminArea
+{
+    protected $id = 'loadBalancerSection';
+    protected $name = 'loadBalancerSection';
+    protected $title = 'loadBalancerSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //Enable
+        $field = new Switcher('customconfigoption[loadBalancer]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //On Upgrade
+        $field = new Select('customconfigoption[loadBalancerOnUpgrade]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Shutdown VM on Upgrade
+        $field = new Switcher('customconfigoption[loadBalancerShutdownOnUpgrade]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Stop VM If Shutdown Fails
+        $field = new Switcher('customconfigoption[loadBalancerStopOnUpgrade]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+    }
+
+}

+ 171 - 0
app/UI/Admin/Product/Sections/Lxc/ClientAreaSection.php

@@ -0,0 +1,171 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Lxc;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\TwiceColumnSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+
+class ClientAreaSection extends TwiceColumnSection implements AdminArea
+{
+    protected $id = 'clientAreaSection';
+    protected $name = 'clientAreaSection';
+    protected $title = 'clientAreaSection';
+
+
+    protected function initFields()
+    {
+        //Start
+        $field = new Switcher('customconfigoption[permissionStart]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Reboot
+        $field = new Switcher('customconfigoption[permissionReboot]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Stop
+        $field = new Switcher('customconfigoption[permissionStop]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Shutdown
+        $field = new Switcher('customconfigoption[permissionShutdown]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //noVNC Console
+        $field = new Switcher('customconfigoption[permissionNovnc]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //SPICE Console
+        $field = new Switcher('customconfigoption[permissionSpice]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //xterm.js Console
+        $field = new Switcher('customconfigoption[permissionXtermjs]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Reinstallation
+        $field = new Switcher('customconfigoption[permissionReinstall]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //OS Templates
+        $field = new Select('customconfigoption[permissionOsTemplates][]');
+        $field->setDescription('tip');
+        $field->enableMultiple();
+        $this->addField($field);
+        //MRTG Graphics
+        $field = new Switcher('customconfigoption[permissionGraph]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Backup
+        $field = new Switcher('customconfigoption[permissionBackup]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Scheduled Backup Jobs
+        $field = new Switcher('customconfigoption[permissionBackupJob]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Task History
+        $field = new Switcher('customconfigoption[permissionTaskHistory]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Network
+        $field = new Switcher('customconfigoption[permissionNetwork]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Snapshots
+        $field = new Switcher('customconfigoption[permissionSnapshot]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Firewall
+        $field = new Switcher('customconfigoption[permissionFirewall]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Firewall Options
+        $field = new Switcher('customconfigoption[permissionFirewallOption]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Disks Management
+        $field = new Switcher('customconfigoption[permissionDisk]');
+        $field->setDefaultValue("on");
+        $field->setDescription('tip');
+        $this->addField($field);
+        //permissionfirewalOptions
+        $field = new Select("customconfigoption[permissionFirewalOptions][]");
+        $field->enableMultiple();
+        $field->setDescription('description');
+        $this->addField($field);
+        //permissionCpuLimit
+        $field = new Switcher('customconfigoption[permissionCpuLimit]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //permissionIpv4
+        $field = new Switcher('customconfigoption[permissionIpv4]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //permissionIpv6
+        $field = new Switcher('customconfigoption[permissionIpv6]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //virtualNetwork
+        $field = new Switcher('customconfigoption[permissionVirtualNetwork]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Locations
+        $field = new Select('customconfigoption[locations][]');
+        $field->setDescription('tip');
+        $field->enableMultiple();
+        $this->addField($field);
+        //cores
+        $field = new Switcher('customconfigoption[permissionCores]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Service Password
+        $field = new Switcher('customconfigoption[permissionPassword]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Service Nameservers
+        $field = new Switcher('customconfigoption[permissionNameservers]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //DNS Domain
+        $field = new Switcher('customconfigoption[permissionSearchdomain]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //permissionCpuunits
+        $field = new Switcher('customconfigoption[permissionCpuunits]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //swap
+        $field = new Switcher('customconfigoption[permissionSwap]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+    }
+
+
+
+}

+ 52 - 0
app/UI/Admin/Product/Sections/Lxc/ConfigurableOptionUnitsSection.php

@@ -0,0 +1,52 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Lxc;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class ConfigurableOptionUnitsSection extends BoxSection implements AdminArea
+{
+    protected $id = 'configurableOptionUnitsSection';
+    protected $name = 'configurableOptionUnitsSection';
+    protected $title = 'configurableOptionUnitsSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //Memory- MB/GB
+        $field = new Select('customconfigoption[memoryUnit]');
+        $field->setDefaultValue("mb");
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Disk Size - MB/GB/TB
+        $field = new Select('customconfigoption[storageUnit]');
+        $field->setDefaultValue("gb");
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //SWAP For the VM - MB/GB
+        $field = new Select('customconfigoption[swapUnit]');
+        $field->setDefaultValue("mb");
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+    }
+
+}

+ 103 - 0
app/UI/Admin/Product/Sections/Lxc/ConfigurationSection.php

@@ -0,0 +1,103 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Lxc;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\TwiceColumnSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+class ConfigurationSection extends TwiceColumnSection implements AdminArea
+{
+    protected $id = 'lxcConfigurationSection';
+    protected $name = 'lxcConfigurationSection';
+    protected $title = 'lxcConfigurationSection';
+
+
+    protected function initFields()
+    {
+        //Storage
+        $field = new Select('customconfigoption[storage]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //OS Architecture Type
+        $field = new Select('customconfigoption[arch]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Console Type
+        $field = new Select('customconfigoption[cmode]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Console
+        $field = new Switcher('customconfigoption[console]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //OS Type
+        $field = new Select('customconfigoption[ostype]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Start At Boot
+        $field = new Switcher('customconfigoption[onboot]');
+        $this->addField($field);
+        //Add The VM To The Specific Pool
+        $field = new  Select('customconfigoption[pool]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Protection
+        $field = new Switcher('customconfigoption[protection]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Startup
+        $field = new Text('customconfigoption[startup]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Amount of tty For The VM
+        $field = new Text('customconfigoption[tty]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Unprivileged
+        $field = new Switcher('customconfigoption[unprivileged]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //SSH Key Pairs
+        $field = new Switcher('customconfigoption[sshKeyPairs]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Delete Private Key
+        $field = new Switcher('customconfigoption[sshDeletePrivateKey]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Start after created
+        $field = new Switcher('customconfigoption[start]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //featureKeyctl
+        $field = new Switcher('customconfigoption[featureKeyctl]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //featureNesting
+        $field = new Switcher('customconfigoption[featureNesting]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //featureNfs
+        $field = new Switcher('customconfigoption[featureNfs]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //featureCifs
+        $field = new Switcher('customconfigoption[featureCifs]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //featureFuse
+        $field = new Switcher('customconfigoption[featureFuse]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //featureMknod
+        $field = new Switcher('customconfigoption[featureMknod]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+
+    }
+
+}

+ 91 - 0
app/UI/Admin/Product/Sections/Lxc/DefaultConfigurationSection.php

@@ -0,0 +1,91 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Lxc;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\TwiceColumnSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+class DefaultConfigurationSection extends TwiceColumnSection implements AdminArea
+{
+    protected $id = 'defaultConfigurationSection';
+    protected $name = 'defaultConfigurationSection';
+    protected $title = 'defaultConfigurationSection';
+
+
+    protected function initFields()
+    {
+        //CPU Limit
+        $field = new Text('customconfigoption[cpulimit]');
+        $field->setDefaultValue(10);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Cores
+        $field = new Text('customconfigoption[cores]');
+        $field->setDescription('tip');
+        $field->setDefaultValue(10);
+        $this->addField($field);
+        //SWAP For the VM in MB
+        $field = new Text('customconfigoption[swap]');
+        $field->setDescription('tip');
+        $field->setDefaultValue(3000);
+        $this->addField($field);
+        //CPU Weight For The VM
+        $field = new Text('customconfigoption[cpuunits]');
+        $field->setDefaultValue(10240);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Memory
+        $field = new Text('customconfigoption[memory]');
+        $field->setDescription('tip');
+        $field->setDefaultValue(3000);
+        $this->addField($field);
+        //Disk Size
+        $field = new Text('customconfigoption[storageSize]');
+        $field->setDescription('tip');
+        $field->setDefaultValue(300);
+        $this->addField($field);
+        //Network Rate Limit
+        $field = new Text('customconfigoption[rate]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Minimum Network Rate Limit
+        $field = new Text('customconfigoption[minimumRate]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Amount of IPv4 Addresses
+        $field = new Text('customconfigoption[ipv4]');
+        $field->setDefaultValue(10);
+        $field->setDescription('tip');
+        $field->setDefaultValue(10);
+        $this->addField($field);
+        //Amount of IPv6 Addresses
+        $field = new Text('customconfigoption[ipv6]');
+        $field->setDefaultValue(0);
+        $field->setDescription('tip');
+        $field->setDefaultValue(0);
+        $this->addField($field);
+        //Backups Size Limit
+        $field = new Text('customconfigoption[backupMaxSize]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Backup Files Limit
+        $field = new Text('customconfigoption[backupMaxFiles]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Bandwidth Limit
+        $field = new Text('customconfigoption[bandwidth]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Snapshots Limit
+        $field = new Text('customconfigoption[snapshotMaxFiles]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //virtualNetworks
+        $field = new Text('customconfigoption[virtualNetworks]');
+        $field->setDescription('tip');
+        $field->setDefaultValue(1);
+        $this->addField($field);
+    }
+
+}

+ 67 - 0
app/UI/Admin/Product/Sections/Lxc/MountPointSection.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Lxc;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class MountPointSection extends BoxSection implements AdminArea
+{
+    protected $id = 'mountPointSection';
+    protected $name = 'mountPointSection';
+    protected $title = 'mountPointSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection = new HalfPageSection('leftSection');
+
+        $this->rightSection = new HalfPageSection('rightSection');
+
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //Storage
+        $field = new Select('customconfigoption[mountPointStorage]');
+        $field->setDefaultValue('local-lvm');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //ACLs
+        $field = new Select('customconfigoption[mountPointAcl]');
+        $field->setDefaultValue("default");
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Read-Only
+        $field = new Switcher('customconfigoption[mountPointRo]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Enable Quota
+        $field = new Switcher('customconfigoption[mountPointQuota]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Skip Replication
+        $field = new Switcher('customconfigoption[mountPointReplicate]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //permissionMountPointBackup
+        $field = new Switcher('customconfigoption[permissionMountPointBackup]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->rightSection->addField($field);
+    }
+
+}

+ 78 - 0
app/UI/Admin/Product/Sections/Lxc/NetworkSection.php

@@ -0,0 +1,78 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Lxc;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Utility;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class NetworkSection extends BoxSection implements AdminArea
+{
+    protected $id = 'networkSection';
+    protected $name = 'networkSection';
+    protected $title = 'networkSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //IPv4 Network Mode
+        $field = new Select('customconfigoption[ipv4NetworkMode]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //IPv6 Network Mode
+        $field = new Select('customconfigoption[ipv6NetworkMode]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('static');
+        $this->rightSection->addField($field);
+        //Bridge
+        $field = new Select('customconfigoption[bridge]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Private Bridge
+        $field = new Select('customconfigoption[privateBridge]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Firewall
+        $field = new Switcher('customconfigoption[networkFirewall]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //VLAN TAG Range From
+        $field = new Text('customconfigoption[tagFrom]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //VLAN TAG Range To
+        $field = new Text('customconfigoption[tagTo]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Tag
+        $field = new Select('customconfigoption[tags][]');
+        $field->enableMultiple();
+        $field->setDescription('tip');
+        if(Utility::isIpManagerProxmoxVPSIntegration()){
+            $field->setDescription('ip_manager_integration_tag');
+        }
+        $this->rightSection->addField($field);
+
+    }
+
+}

+ 60 - 0
app/UI/Admin/Product/Sections/Lxc/ServerSection.php

@@ -0,0 +1,60 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Lxc;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\TwiceColumnSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+class ServerSection extends TwiceColumnSection implements AdminArea
+{
+    protected $id = 'serverSection';
+    protected $name = 'serverSection';
+    protected $title = 'serverSection';
+
+    protected function initFields()
+    {
+        //CPU Cores
+        $field = new Text('customconfigoption[serverCores]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('1-20');
+        $this->addField($field);
+        //CPU Limit
+        $field = new Text('customconfigoption[serverCpulimit]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('0.1-1');
+        $this->addField($field);
+        //CPU Units
+        $field = new Text('customconfigoption[serverCpuunit]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('1024-500000');
+        $this->addField($field);
+        //Memory
+        $field = new Text('customconfigoption[serverMemory]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('512-4096');
+        $this->addField($field);
+        //SWAP
+        $field = new Text('customconfigoption[serverSwap]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('512-9048');
+        $this->addField($field);
+        //Disk Space
+        $field = new Text('customconfigoption[serverDiskSize]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('8-100');
+        $this->addField($field);
+        //IPv4
+        $field = new Text('customconfigoption[serverIpv4]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('1-10');
+        $this->addField($field);
+        //IPv6
+        $field = new Text('customconfigoption[serverIpv6]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('0-10');
+        $this->addField($field);
+    }
+}

+ 44 - 0
app/UI/Admin/Product/Sections/MainSection.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Lang\Lang;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class MainSection extends TwiceColumnSection implements AdminArea
+{
+    protected $id = 'mainSection';
+    protected $name = 'mainSection';
+    protected $title = 'mainSection';
+
+
+    protected function initFields()
+    {
+        /**
+         * @var Lang $lang
+         */
+        $lang = sl("lang");
+        //Virtualization
+        $field = new Select('customconfigoption[virtualization]');
+        $field->setDefaultValue('qemu');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Default Node
+        $field = new Select('customconfigoption[defaultNode]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Check Available Resources
+        $field = new Switcher('customconfigoption[checkResources]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //resetUsageFirstDayOfMonth
+        $field = new Switcher('customconfigoption[resetUsageFirstDayOfMonth]');
+        $field->setDescription('tip');
+        $this->addField($field);
+    }
+
+}

+ 66 - 0
app/UI/Admin/Product/Sections/MiscellaneousSection.php

@@ -0,0 +1,66 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class MiscellaneousSection extends BoxSection implements AdminArea
+{
+    protected $id = 'miscellaneousSection';
+    protected $name = 'miscellaneousSection';
+    protected $title = 'miscellaneousSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+
+    }
+
+    private function initFields()
+    {
+        //Backup VM Before Reinstallation
+        $field = new Switcher('customconfigoption[backupVmBeforeReinstall]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Reboot VM After Changing Package
+        $field = new Switcher('customconfigoption[rebootVmAfterUpgrade');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Bandwidth Overage
+        $field = new Switcher('customconfigoption[suspendOnBandwidthOverage]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Suspension Action
+        $field = new Select('customconfigoption[suspensionAction]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //buttons
+        $field = new Select('customconfigoption[buttonSyle]');
+        $field->setDefaultValue('tiles');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Details View
+        $field = new Select('customconfigoption[detailsView]');
+        $field->setDefaultValue('standard');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+    }
+
+}

+ 85 - 0
app/UI/Admin/Product/Sections/Qemu/AdditonalDisk.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class AdditonalDisk extends BoxSection implements AdminArea
+{
+    protected $id = 'additonalDisk';
+    protected $name = 'additonalDisk';
+    protected $title = 'additonalDisk';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //Disks Storage
+        $field = new Select('customconfigoption[additionalDiskStorage]');
+        $field->setDefaultValue('local-lvm');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Disks Type
+        $field = new Select('customconfigoption[additionalDiskType][]');
+        $field->setDescription('tip');
+        $field->enableMultiple();
+        $field->setDefaultValue(["ide"]);
+        $this->rightSection->addField($field);
+        //Disk Format
+        $field = new Select('customconfigoption[additionalDiskFormat][]');
+        $field->enableMultiple();
+        $field->setDefaultValue(["raw"]);
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Disk Skip Replication
+        $field = new Switcher('customconfigoption[additionalDiskReplicate]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Disk Cache
+        $field = new Select('customconfigoption[additionalDiskCache]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Disk Discard
+        $field = new Switcher('customconfigoption[additionalDiskDiscard]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Disk IO Thread
+        $field = new Switcher('customconfigoption[additionalDiskIoThread]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Allow Backups On Additional Disks
+        $field = new Switcher('customconfigoption[permissionAdditionalDiskBackup]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Limits
+        $field = new Switcher('customconfigoption[additionalDiskSpeed]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //ssd
+        $field = new Switcher('customconfigoption[additionalDiskSsd]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+
+
+    }
+
+}

+ 63 - 0
app/UI/Admin/Product/Sections/Qemu/AdditonalDiskSpeedSection.php

@@ -0,0 +1,63 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class AdditonalDiskSpeedSection extends BoxSection implements AdminArea
+{
+    protected $id = 'additonalDiskSpeedSection';
+    protected $name = 'additonalDiskSpeedSection';
+    protected $title = 'additonalDiskSpeedSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection = new HalfPageSection('leftSection');
+
+        $this->rightSection = new HalfPageSection('rightSection');
+
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //Read Limit (MB/s)
+        $field = new Text('customconfigoption[additionalDiskMbps_rd]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Write Limit (MB/s)
+        $field = new  Text('customconfigoption[additionalDiskMbps_wr]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Read Limit (ops/s)
+        $field = new  Text('customconfigoption[additionalDiskIops_rd]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Read Max Burst (ops)
+        $field = new  Text('customconfigoption[additionalDiskIops_rd_max]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Write Limit (ops/s)
+        $field = new  Text('customconfigoption[additionalDiskIops_wr]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Write Max Burst (ops)
+        $field = new  Text('customconfigoption[additionalDiskIops_wr_max]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+    }
+
+}

+ 92 - 0
app/UI/Admin/Product/Sections/Qemu/AdvancedSection.php

@@ -0,0 +1,92 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class AdvancedSection extends BoxSection implements AdminArea
+{
+    protected $id = 'advancedSection';
+    protected $name = 'advancedSection';
+    protected $title = 'advancedSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //Minimum RAM For The VM
+        $field = new Text('customconfigoption[balloon]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Memory Shares
+        $field = new Text('customconfigoption[shares]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Arguments-
+        $field = new Textarea('customconfigoption[args]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Local Time For Real Time Clock
+        $field = new Switcher('customconfigoption[localtime]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Maximum Tolerated Downtime
+        $field = new Text('customconfigoption[migrate_downtime]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Maximum Speed For Migrations [MB/s]
+        $field = new Text('customconfigoption[migrate_speed]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Hardware Watchdog Device
+        $field = new Text('customconfigoption[watchdog]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Initial Date Of The Real Time Clock
+        $field = new Text('customconfigoption[startdate]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Startup
+        $field = new Text('customconfigoption[startup]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Time Drift Fix
+        $field = new Switcher('customconfigoption[tdf]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //bwlimit
+        $field = new Text('customconfigoption[bwlimit]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //bios
+        $field = new Select('customconfigoption[bios]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //machine
+        $field = new Select('customconfigoption[machine]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+    }
+
+}

+ 54 - 0
app/UI/Admin/Product/Sections/Qemu/BootSection.php

@@ -0,0 +1,54 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class BootSection extends BoxSection implements AdminArea
+{
+    protected $id = 'bootSection';
+    protected $name = 'bootSection';
+    protected $title = 'bootSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //Boot Device 1
+        $field = new Select('customconfigoption[bootDevice1]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Boot Device 2
+        $field = new Select('customconfigoption[bootDevice2]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Boot Device 3
+        $field = new Select('customconfigoption[bootDevice3]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Boot Disk
+        $field = new Text('customconfigoption[bootdisk]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+    }
+
+}

+ 226 - 0
app/UI/Admin/Product/Sections/Qemu/ClientAreaSection.php

@@ -0,0 +1,226 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\TwiceColumnSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+
+class ClientAreaSection extends TwiceColumnSection implements AdminArea
+{
+    protected $id = 'clientAreaSection';
+    protected $name = 'clientAreaSection';
+    protected $title = 'clientAreaSection';
+
+    protected function initFields()
+    {
+        //Start
+        $field = new Switcher('customconfigoption[permissionStart]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Reboot
+        $field = new Switcher('customconfigoption[permissionReboot]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Stop
+        $field = new Switcher('customconfigoption[permissionStop]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Shutdown
+        $field = new Switcher('customconfigoption[permissionShutdown]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //noVNC Console
+        $field = new Switcher('customconfigoption[permissionNovnc]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //SPICE Console
+        $field = new Switcher('customconfigoption[permissionSpice]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //xterm.js Console
+        $field = new Switcher('customconfigoption[permissionXtermjs]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Reinstallation
+        $field = new Switcher('customconfigoption[permissionReinstall]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //KVM Templates
+        $field = new Switcher('customconfigoption[permissionOsTemplate]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //OS Templates
+        $field = new Select('customconfigoption[permissionOsTemplates][]');
+        $field->setDescription('tip');
+        $field->enableMultiple();
+        $this->addField($field);
+        //ISO Images
+        $field = new Switcher('customconfigoption[permissionIsoImage]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //ISO Images
+        $field = new Select('customconfigoption[permissionIsoImages][]');
+        $field->setDescription('tip');
+        $field->enableMultiple();
+        $this->addField($field);
+        //Secondary ISO Images
+        $field = new Select('customconfigoption[permissionSecondaryIsoImages][]');
+        $field->setDescription('tip');
+        $field->enableMultiple();
+        $this->addField($field);
+        //MRTG Graphics
+        $field = new Switcher('customconfigoption[permissionGraph]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Backup
+        $field = new Switcher('customconfigoption[permissionBackup]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Scheduled Backup Jobs
+        $field = new Switcher('customconfigoption[permissionBackupJob]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Task History
+        $field = new Switcher('customconfigoption[permissionTaskHistory]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Network
+        $field = new Switcher('customconfigoption[permissionNetwork]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Snapshots
+        $field = new Switcher('customconfigoption[permissionSnapshot]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Firewall
+        $field = new Switcher('customconfigoption[permissionFirewall]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Firewall Options
+        $field = new Switcher('customconfigoption[permissionFirewallOption]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Disks Management
+        $field = new Switcher('customconfigoption[permissionDisk]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //sshkeys
+        $field = new Switcher('customconfigoption[permissionSshkeys]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //permissionfirewalOptions
+        $field = new Select("customconfigoption[permissionFirewalOptions][]");
+        $field->enableMultiple();
+        $field->setDescription('description');
+        $this->addField($field);
+        //customTemplates
+        $field = new Switcher('customconfigoption[permissionCustomTemplates]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //permissionVcpus
+        $field = new Switcher('customconfigoption[permissionVcpus]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //permissionSockets
+        $field = new Switcher('customconfigoption[permissionSockets]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //cores
+        $field = new Switcher('customconfigoption[permissionCores]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //permissionUpgrade
+        $field = new Switcher('customconfigoption[permissionUpgrade]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //permissionCpuLimit
+        $field = new Switcher('customconfigoption[permissionCpuLimit]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //permissionIpv4
+        $field = new Switcher('customconfigoption[permissionIpv4]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //permissionIpv6
+        $field = new Switcher('customconfigoption[permissionIpv6]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //virtualNetwork
+        $field = new Switcher('customconfigoption[permissionVirtualNetwork]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //OsTypes
+        $field = new Select('customconfigoption[permissionOstype][]');
+        $field->enableMultiple();
+        $field->setDescription('tip');
+        $field->setDefaultValue("l26");
+        $this->addField($field);
+        //Locations
+        $field = new Select('customconfigoption[locations][]');
+        $field->setDescription('tip');
+        $field->enableMultiple();
+        $this->addField($field);
+        //Service Username
+        $field = new Switcher('customconfigoption[permissionUsername]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Service Password
+        $field = new Switcher('customconfigoption[permissionPassword]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Service Nameservers
+        $field = new Switcher('customconfigoption[permissionNameservers]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //DNS Domain
+        $field = new Switcher('customconfigoption[permissionSearchdomain]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //permissionCpuunits
+        $field = new Switcher('customconfigoption[permissionCpuunits]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //calculate Sockets And Cores
+        $field = new Switcher('customconfigoption[calculateSocketsAndCores]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //cloudInitScript
+        $field = new Select('customconfigoption[cloudInitScript][]');
+        $field->enableMultiple();
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+    }
+    
+}

+ 37 - 0
app/UI/Admin/Product/Sections/Qemu/CloudInitSection.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\TwiceColumnSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+
+class CloudInitSection extends TwiceColumnSection implements AdminArea
+{
+    protected $id = 'cloudInitSection';
+    protected $name = 'cloudInitSection';
+    protected $title = 'cloudInitSection';
+    private $sectionFields=[];
+
+
+    protected function initFields()
+    {
+        //Enable Cloud-Init
+        $field = new Switcher('customconfigoption[cloudInit]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //Default User
+        $field = new Text('customconfigoption[ciuser]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //cicustom
+        $field = new Textarea('customconfigoption[cicustom]');
+        $field->setDescription('tip');
+        $this->addField($field);
+
+    }
+
+}

+ 47 - 0
app/UI/Admin/Product/Sections/Qemu/ConfigurableOptionUnitsSection.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class ConfigurableOptionUnitsSection extends BoxSection implements AdminArea
+{
+    protected $id = 'configurableOptionUnitsSection';
+    protected $name = 'configurableOptionUnitsSection';
+    protected $title = 'configurableOptionUnitsSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //Memory- MB/GB
+        $field = new Select('customconfigoption[memoryUnit]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("mb");
+        $this->leftSection->addField($field);
+        //Disk Size - MB/GB/TB
+        $field = new Select('customconfigoption[storageUnit]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("gb");
+        $this->rightSection->addField($field);
+    }
+
+}

+ 176 - 0
app/UI/Admin/Product/Sections/Qemu/ConfigurationSection.php

@@ -0,0 +1,176 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class ConfigurationSection extends BoxSection implements AdminArea
+{
+    protected $id = 'configurationSection';
+    protected $name = 'configurationSection';
+    protected $title = 'configurationSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection = new HalfPageSection('leftSection');
+
+        $this->rightSection = new HalfPageSection('rightSection');
+
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //OS Type	- default 2.6/3.x
+        $field = new Select('customconfigoption[ostype]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("l26");
+        $this->leftSection->addField($field);
+        //ACPI - switch, default off
+        $field = new Switcher('customconfigoption[acpi]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("off");
+        $this->rightSection->addField($field);
+        //Automatic Restart After Crash
+        $field = new Switcher('customconfigoption[autostart]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //cdrom
+        $field = new Text('customconfigoption[cdrom]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //CD/DVD-ROM Type
+        $field = new Select('customconfigoption[cdromType]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //PCID
+        $field = new Switcher('customconfigoption[pcid]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Numa
+        $field = new Switcher('customconfigoption[numa]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //SPEC-CTRL
+        $field = new Switcher('customconfigoption[spec-ctrl]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Startup Freeze CPU
+        $field = new Switcher('customconfigoption[freeze]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Hotplug
+        $field = new Select('customconfigoption[hotplug][]');
+        $field->setDescription('tip');
+        $field->enableMultiple();
+        $this->rightSection->addField($field);
+        //Keyboard
+        $field = new Select('customconfigoption[keyboard]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //KVM Hardware Virtualization
+        $field = new Switcher('customconfigoption[kvm]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->rightSection->addField($field);
+        //Start At Boot
+        $field = new Switcher('customconfigoption[onboot]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Add The VM To The Specific Pool
+        $field = new Select('customconfigoption[pool]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Allow Reboot
+        $field = new Switcher('customconfigoption[reboot]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //USB Tablet Device
+        $field = new Switcher('customconfigoption[tablet]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //VGA Type
+        $field = new Select('customconfigoption[vga]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Search For Templates In All Nodes
+        $field = new Switcher('customconfigoption[osTemplatesInAllNodes]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->leftSection->addField($field);
+        //Clone Mode
+        $field = new Select('customconfigoption[cloneMode]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("full");
+        $this->rightSection->addField($field);
+        //Start after created
+        $field = new Switcher('customconfigoption[start]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->leftSection->addField($field);
+        //Clone On The Same Storage As Source
+        $field = new Switcher('customconfigoption[cloneOnTheSameStorage]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //md-clear
+        $field = new Switcher('customconfigoption[md-clear]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //ssbd
+        $field = new Switcher('customconfigoption[ssbd]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //ibpb
+        $field = new Switcher('customconfigoption[ibpb]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //virt-ssbd
+        $field = new Switcher('customconfigoption[virt-ssbd]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //amd-ssbd
+        $field = new Switcher('customconfigoption[amd-ssbd]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //amd-no-ssb
+        $field = new Switcher('customconfigoption[amd-no-ssb]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //pdpe1gb
+        $field = new Switcher('customconfigoption[pdpe1gb]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //hv-tlbflush
+        $field = new Switcher('customconfigoption[hv-tlbflush]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //hv-evmcs
+        $field = new Switcher('customconfigoption[hv-evmcs]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //aes
+        $field = new Switcher('customconfigoption[aes]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //vgaMemory
+        $field = new Text('customconfigoption[vgaMemory]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+    }
+
+}

+ 89 - 0
app/UI/Admin/Product/Sections/Qemu/DefaultConfigurationSection.php

@@ -0,0 +1,89 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\TwiceColumnSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+class DefaultConfigurationSection extends TwiceColumnSection implements AdminArea
+{
+    protected $id = 'defaultConfigurationSection';
+    protected $name = 'defaultConfigurationSection';
+    protected $title = 'defaultConfigurationSection';
+
+    protected function initFields()
+    {
+        //cpu
+        $field = new Select('customconfigoption[cpu]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('kvm64');
+        $this->addField($field);
+        //Number of CPU Sockets
+        $field = new Text('customconfigoption[sockets]');
+        $field->setDescription('tip');
+        $field->setDefaultValue(10);
+        $this->addField($field);
+        //Number of Cores Per Socket
+        $field = new Text('customconfigoption[cores]');
+        $field->setDefaultValue(10);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //VCPUs
+        $field = new Text('customconfigoption[vcpus]');
+        $field->setDefaultValue(10);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Limit of CPU
+        $field = new Text('customconfigoption[cpulimit]');
+        $field->setDefaultValue(10);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //CPU Weight For The VM
+        $field = new Text('customconfigoption[cpuunits]');
+        $field->setDefaultValue(10240);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //RAM For The VM
+        $field = new Text('customconfigoption[memory]');
+        $field->setDefaultValue(3000);
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Disk Space
+        $field = new Text('customconfigoption[storageSize]');
+        $field->setDescription('tip');
+        $field->setDefaultValue(300);
+        $this->addField($field);
+        //Amount of IPv4 Addresses
+        $field = new Text('customconfigoption[ipv4]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Amount of IPv6 Addresses
+        $field = new Text('customconfigoption[ipv6]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Backups Size Limit
+        $field = new Text('customconfigoption[backupMaxSize]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Backup Files Limit
+        $field = new Text('customconfigoption[backupMaxFiles]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Bandwidth Limit
+        $field = new Text('customconfigoption[bandwidth]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Snapshots Limit
+        $field = new Text('customconfigoption[snapshotMaxFiles]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Private Network Limit
+        $field = new Text('customconfigoption[virtualNetworks]');
+        $field->setDescription('tip');
+        $field->setDefaultValue(1);
+        $this->addField($field);
+    }
+
+}

+ 79 - 0
app/UI/Admin/Product/Sections/Qemu/DiskSection.php

@@ -0,0 +1,79 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class DiskSection extends BoxSection implements AdminArea
+{
+    protected $id = 'diskSection';
+    protected $name = 'diskSection';
+    protected $title = 'diskSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //Storage
+        $field = new Select('customconfigoption[diskStorage]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('local-lvm');
+        $this->leftSection->addField($field);
+        //Disk Type
+        $field = new Select('customconfigoption[diskType]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Disk Format
+        $field = new Select('customconfigoption[diskFormat]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Cache
+        $field = new Select('customconfigoption[diskCache]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //SCSI Controller Model
+        $field = new Select('customconfigoption[scsihw]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Discard
+        $field = new Switcher('customconfigoption[discard]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Skip Replication
+        $field = new Switcher('customconfigoption[replicate]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //IO Thread
+        $field = new Switcher('customconfigoption[ioThread]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Limits
+        $field = new Switcher('customconfigoption[diskSpeed]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //ssd
+        $field = new Switcher('customconfigoption[ssd]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+    }
+
+}

+ 61 - 0
app/UI/Admin/Product/Sections/Qemu/DiskSpeedSection.php

@@ -0,0 +1,61 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class DiskSpeedSection extends BoxSection implements AdminArea
+{
+    protected $id = 'diskSpeedSection';
+    protected $name = 'diskSpeedSection';
+    protected $title = 'diskSpeedSection';
+    /**
+     * @var HalfPageSection
+     */
+    private $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    private $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    private function initFields()
+    {
+        //Read Limit (MB/s)
+        $field = new Text('customconfigoption[mbps_rd]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Write Limit (MB/s)
+        $field = new  Text('customconfigoption[mbps_wr]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Read Limit (ops/s)
+        $field = new  Text('customconfigoption[iops_rd]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Read Max Burst (ops)
+        $field = new  Text('customconfigoption[iops_rd_max]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Write Limit (ops/s)
+        $field = new  Text('customconfigoption[iops_wr]');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //Write Max Burst (ops)
+        $field = new  Text('customconfigoption[iops_wr_max]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+    }
+
+}

+ 34 - 0
app/UI/Admin/Product/Sections/Qemu/GuestAgentSection.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\TwiceColumnSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+
+class GuestAgentSection extends TwiceColumnSection implements AdminArea
+{
+    protected $id = 'guestAgentSection';
+    protected $name = 'guestAgentSection';
+    protected $title = 'guestAgentSection';
+    private $sectionFields=[];
+
+
+    protected function initFields()
+    {
+        //Guest Agent [on/off]
+        $field = new Switcher('customconfigoption[agent]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Service Password
+        $field = new Switcher('customconfigoption[agentPassword]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Configure Network
+        $field = new Switcher('customconfigoption[agentConfigureNetwork]');
+        $field->setDescription('tip');
+        $this->addField($field);
+    }
+
+
+}

+ 76 - 0
app/UI/Admin/Product/Sections/Qemu/NetworkSection.php

@@ -0,0 +1,76 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Utility;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\TwiceColumnSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+class NetworkSection extends TwiceColumnSection implements AdminArea
+{
+    protected $id = 'networkSection';
+    protected $name = 'networkSection';
+    protected $title = 'networkSection';
+
+
+    protected function initFields()
+    {
+        //Network Model
+        $field = new Select('customconfigoption[networkModel]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Bridge
+        $field = new Select('customconfigoption[bridge]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Network Rate Limit [MB/s]
+        $field = new Text('customconfigoption[rate]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Minimum Network Rate Limit [MB/s]
+        $field = new Text('customconfigoption[minimumRate]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Private Bridge
+        $field = new Select('customconfigoption[privateBridge]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Private Network Model
+        $field = new Select('customconfigoption[networkPrivateModel]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Disable Additional NIC Creation
+        $field = new Switcher('customconfigoption[oneNetworkDevice]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Firewall
+        $field = new Switcher('customconfigoption[networkFirewall]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Multiqueue
+        $field = new Text('customconfigoption[queues]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //VLAN TAG Range From
+        $field = new Text('customconfigoption[tagFrom]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //VLAN TAG Range To
+        $field = new Text('customconfigoption[tagTo]');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //Tag
+        $field = new Select('customconfigoption[tags][]');
+        $field->enableMultiple();
+        $field->setDescription('tip');
+        if(Utility::isIpManagerProxmoxVPSIntegration()){
+            $field->setDescription('ip_manager_integration_tag');
+        }
+        $this->addField($field);
+
+    }
+
+}

+ 65 - 0
app/UI/Admin/Product/Sections/Qemu/ServerSection.php

@@ -0,0 +1,65 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qemu;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\TwiceColumnSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+class ServerSection extends TwiceColumnSection implements AdminArea
+{
+    protected $id = 'serverSection';
+    protected $name = 'serverSection';
+    protected $title = 'serverSection';
+
+    protected function initFields()
+    {
+        //Sockets
+        $field = new Text('customconfigoption[serverSockets]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('1-20');
+        $this->addField($field);
+        //CPU Cores
+        $field = new Text('customconfigoption[serverCores]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('1-20');
+        $this->addField($field);
+        //VCPUs
+        $field = new Text('customconfigoption[serverVcpus]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('1-20');
+        $this->addField($field);
+        //CPU Limit
+        $field = new Text('customconfigoption[serverCpulimit]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('0.1-1');
+        $this->addField($field);
+        //CPU Units
+        $field = new Text('customconfigoption[serverCpuunit]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('1024-500000');
+        $this->addField($field);
+        //Memory
+        $field = new Text('customconfigoption[serverMemory]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('512-4096');
+        $this->addField($field);
+        //Disk Space
+        $field = new Text('customconfigoption[serverDiskSize]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('8-100');
+        $this->addField($field);
+        //IPv4
+        $field = new Text('customconfigoption[serverIpv4]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('1-10');
+        $this->addField($field);
+        //IPv6
+        $field = new Text('customconfigoption[serverIpv6]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('0-10');
+        $this->addField($field);
+    }
+}

+ 46 - 0
app/UI/Admin/Product/Sections/TwiceColumnSection.php

@@ -0,0 +1,46 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class TwiceColumnSection extends BoxSection
+{
+
+    /**
+     * @var HalfPageSection
+     */
+    protected $leftSection;
+    /**
+     * @var HalfPageSection
+     */
+    protected $rightSection;
+
+    public function initContent()
+    {
+        $this->leftSection  = new HalfPageSection('leftSection');
+        $this->rightSection = new HalfPageSection('rightSection');
+
+        $this->addSection($this->leftSection)
+            ->addSection($this->rightSection);
+        $this->initFields();
+    }
+
+    protected function initFields()
+    {
+
+    }
+
+    public function addField($field){
+        $total = count($this->leftSection->getFields()) + count($this->rightSection->getFields());
+        if($total % 2 == 0){
+            $this->leftSection->addField($field);
+        }else{
+            $this->rightSection->addField($field);
+        }
+        return $this;
+    }
+}

+ 40 - 0
app/UI/Admin/Product/Sections/UserSection.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+
+class UserSection extends TwiceColumnSection implements AdminArea
+{
+    protected $id = 'userSection';
+    protected $name = 'userSection';
+    protected $title = 'userSection';
+
+    protected function initFields()
+    {
+        //Username Prefix
+        $field = new Text('customconfigoption[userPrefix]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('ProxmoxCloudVps_{$serviceid}');
+        $this->addField($field);
+        //Realm
+        $field = new Select('customconfigoption[realm]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('pve');
+        $this->addField($field);
+        //Comment
+        $field = new Textarea('customconfigoption[userComment]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('User from module ProxmoxCloudVps for WHMCS');
+        $this->addField($field);
+        //Role
+        $field = new Select('customconfigoption[userRole]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('PVEVMUser');
+        $this->addField($field);
+    }
+
+}

+ 97 - 0
app/UI/Admin/QemuGuestAgent/Pages/NetworkInterfacesDataTable.php

@@ -0,0 +1,97 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\QemuGuestAgent\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+
+class NetworkInterfacesDataTable extends DataTable implements AdminArea
+{
+    use ProductService;
+    use ApiService;
+
+
+    protected $id = 'networkInterfacesDataTable';
+    protected $title = 'networkInterfacesDataTable';
+    protected $searchable = false;
+    protected $tableLength = "100";
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('name'))->setTitle("interfaceName"))
+            ->addColumn((new Column('hardwareAddress')))
+            ->addColumn((new Column('ipAddresses')));
+    }
+
+
+    public function replaceFieldHardwareAddress($key, $row)
+    {
+
+        if($row[$key]){
+            return $row[$key];
+        }
+        return '-';
+    }
+
+
+    protected function loadData()
+    {
+        $data  = [];
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $agent = $vm->agent();
+        foreach ($agent->networkGetInterfaces()['result'] as $net)
+        {
+            $ips = [];
+            foreach ($net['ip-addresses'] as $ipAddress)
+            {
+                $ips[] = "{$ipAddress['ip-address']} / {$ipAddress['prefix']}";
+            }
+            $data[] = [
+                "name"            => $net['name'],
+                "hardwareAddress" => $net['hardware-address'],
+                "ipAddresses"     => implode("<br/>", $ips)
+            ];
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+
+    public function initContent()
+    {
+
+    }
+
+    public function isViewFooter()
+    {
+        return false;
+    }
+
+    public function isViewTopBody()
+    {
+        return false;
+    }
+
+}

+ 24 - 0
app/UI/Admin/Templates/accountResources/accountResourcesContainer.tpl

@@ -0,0 +1,24 @@
+<div class="lu-widget">
+    <div class="lu-widget__header">
+        <div class="lu-widget__top lu-top">
+            <div class="lu-top__title">
+                <span>{$MGLANG->tr('availableResources')}</span>
+            </div>
+        </div>
+    </div>
+    <div class="lu-widget__body">
+        <div class="lu-widget__content">
+            {foreach from=$customTplVars.bars item=bar}
+                <div class="lu-progress lu-progress--h lu-progress--s lu-progress__label">
+                    <div class="lu-progress__label">
+                        {$bar.name} ({$bar.used}/{$bar.max}{if $bar.unit} {$bar.unit}{/if})
+                    </div>
+                    <div class="lu-progress__bar progress-bar-danger">
+                        <div class="lu-progress__fill" style="width: {$bar.value}%"></div>
+                    </div>
+                </div>
+            {/foreach}
+        </div>
+    </div>
+</div>
+

+ 25 - 0
app/UI/Admin/Templates/assets/css/integration.css

@@ -0,0 +1,25 @@
+#contentarea > div > h1 {
+    display: block !important;
+}
+
+#contentarea {
+    margin: 10px;
+    padding: 15px;
+    min-height: 600px;
+    background-color: #fff;
+    border: 4px solid #e2e7e9;
+    -moz-border-radius: 10px;
+    -webkit-border-radius: 10px;
+    -o-border-radius: 10px;
+    border-radius: 10px;
+    overflow: auto;
+}
+
+.mg-integration-container .lu-app {
+    height: 0px;
+    visibility: hidden;
+}
+
+#layers .lu-app {
+    background-color: #efefef;
+}

+ 134 - 0
app/UI/Admin/Templates/assets/css/module_styles.css

@@ -0,0 +1,134 @@
+#layers  .lu-widget--toggle .lu-widget__header {
+    cursor: pointer !important;
+}
+
+#layers .lu-app .progress-bar[aria-valuenow="0"] {
+    min-width: 30px;
+    color: #777;
+    background-color: transparent;
+    background-image: none;
+    box-shadow: none;
+}
+
+.pm-resource-usege {
+    clear: both;
+    width: 40% !important;
+    margin-bottom: 2px !important;
+}
+
+
+/*background: #2368AD; tło #e9ebf0*/
+
+input[type=range] {
+    height: 25px;
+    -webkit-appearance: none;
+    margin: 10px 0;
+    width: 100%;
+}
+input[type=range]:focus {
+    outline: none;
+}
+input[type=range]::-webkit-slider-runnable-track {
+    width: 100%;
+    height: 5px;
+    cursor: pointer;
+    animate: 0.2s;
+    box-shadow: 0px 0px 0px #E9EBF0;
+    background: #2368AD;
+    border-radius: 1px;
+    border: 0px solid #E9EBF0;
+}
+input[type=range]::-webkit-slider-thumb {
+    box-shadow: 0px 0px 0px #000000;
+    border: 1px solid #174370;
+    height: 18px;
+    width: 18px;
+    border-radius: 25px;
+    background: #2368AD;
+    cursor: pointer;
+    -webkit-appearance: none;
+    margin-top: -7px;
+}
+input[type=range]:focus::-webkit-slider-runnable-track {
+    background: #2368AD;
+}
+input[type=range]::-moz-range-track {
+    width: 100%;
+    height: 5px;
+    cursor: pointer;
+    animate: 0.2s;
+    box-shadow: 0px 0px 0px #E9EBF0;
+    background: #2368AD;
+    border-radius: 1px;
+    border: 0px solid #E9EBF0;
+}
+input[type=range]::-moz-range-thumb {
+    box-shadow: 0px 0px 0px #000000;
+    border: 1px solid #174370;
+    height: 18px;
+    width: 18px;
+    border-radius: 25px;
+    background: #2368AD;
+    cursor: pointer;
+}
+input[type=range]::-ms-track {
+    width: 100%;
+    height: 5px;
+    cursor: pointer;
+    animate: 0.2s;
+    background: transparent;
+    border-color: transparent;
+    color: transparent;
+}
+input[type=range]::-ms-fill-lower {
+    background: #2368AD;
+    border: 0px solid #E9EBF0;
+    border-radius: 2px;
+    box-shadow: 0px 0px 0px #E9EBF0;
+}
+input[type=range]::-ms-fill-upper {
+    background: #2368AD;
+    border: 0px solid #E9EBF0;
+    border-radius: 2px;
+    box-shadow: 0px 0px 0px #E9EBF0;
+}
+input[type=range]::-ms-thumb {
+    margin-top: 1px;
+    box-shadow: 0px 0px 0px #000000;
+    border: 1px solid #174370;
+    height: 18px;
+    width: 18px;
+    border-radius: 25px;
+    background: #2368AD;
+    cursor: pointer;
+}
+input[type=range]:focus::-ms-fill-lower {
+    background: #2368AD;
+}
+input[type=range]:focus::-ms-fill-upper {
+    background: #2368AD;
+}
+
+.lu-range-output{
+    display: block;
+    width:100%;
+    text-align:center;
+    padding-top: 0px !important;
+    position: absolute;
+    top: 5px;
+}
+
+#layers .lu-progress--h .lu-progress__label{
+    flex-basis: 23%!important;
+}
+
+.vm-actions .lu-widget__content{
+    justify-content: center;
+    display: flex!important;
+    flex-wrap: wrap;
+    padding-bottom: 10px!important;
+}
+
+.vm-actions .lu-btn{
+    width: 23%;
+}

BIN
app/UI/Admin/Templates/assets/img/buttons/backup.png


BIN
app/UI/Admin/Templates/assets/img/buttons/backupJob.png


BIN
app/UI/Admin/Templates/assets/img/buttons/disk.png


BIN
app/UI/Admin/Templates/assets/img/buttons/firewall.png


BIN
app/UI/Admin/Templates/assets/img/buttons/firewallOption.png


BIN
app/UI/Admin/Templates/assets/img/buttons/graph.png


BIN
app/UI/Admin/Templates/assets/img/buttons/network.png


BIN
app/UI/Admin/Templates/assets/img/buttons/novnc.png


BIN
app/UI/Admin/Templates/assets/img/buttons/rebootButton.png


BIN
app/UI/Admin/Templates/assets/img/buttons/reinstall.png


BIN
app/UI/Admin/Templates/assets/img/buttons/shutdownButton.png


BIN
app/UI/Admin/Templates/assets/img/buttons/snapshot.png


BIN
app/UI/Admin/Templates/assets/img/buttons/spice.png


BIN
app/UI/Admin/Templates/assets/img/buttons/startButton.png


BIN
app/UI/Admin/Templates/assets/img/buttons/stopButton.png


BIN
app/UI/Admin/Templates/assets/img/buttons/taskHistory.png


BIN
app/UI/Admin/Templates/assets/img/buttons/vnc.png


BIN
app/UI/Admin/Templates/assets/img/buttons/xtermjs.png


+ 37 - 0
app/UI/Admin/Templates/assets/js/home/index.js

@@ -0,0 +1,37 @@
+function mgBytesToSize(bytes) {
+    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
+    if (bytes <= 1) {
+        if (bytes !== 0) {
+            var bytes = Number(bytes).toFixed(1);
+        }
+        return bytes + ' Byte';
+    }
+    var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1000)));
+    return Math.round(bytes / Math.pow(1000, i), 2) + ' ' + sizes[i];
+}
+
+function mgTooltipCpu(tooltipItem, data) {
+    var used = Number(tooltipItem.yLabel).toFixed(2);
+    return used + "%";
+}
+
+function mgTooltipServerLoad(tooltipItem, data) {
+    var used = Number(tooltipItem.yLabel).toFixed(2);
+    return used;
+}
+
+function mgTooltipCallbackForMemory(tooltipItem, data) {
+    return mgBytesToSize(tooltipItem.yLabel) + "/s";
+}
+
+function mgTooltipCallbackForNet(tooltipItem, data) {
+    return mgBytesToSize(tooltipItem.yLabel) + "/s";
+}
+
+function mgTooltipCallbackForDisk(tooltipItem, data) {
+    return mgBytesToSize(tooltipItem.yLabel) + "/s";
+}
+
+function mgLocationReload(data) {
+    window.location.reload();
+}

+ 45 - 0
app/UI/Admin/Templates/assets/js/hooks/server.js

@@ -0,0 +1,45 @@
+var ProxmoxCloudVps_td1;
+var ProxmoxCloudVps_td2;
+var ProxmoxCloudVps_accesshash;
+var ProxmoxCloudVps_selectAdded = false;
+
+function ProxmoxCloudVps_addSelect(){
+
+    var accessTd = $(  "#inputServerType").closest("tbody").find(" tr:eq(3)").find(" td:eq(0)");
+    ProxmoxCloudVps_td1 = accessTd.html();
+    accessTd.html("Authentication");
+
+    var accessInput = $(  "#inputServerType").closest("tbody").find(" tr:eq(3)").find(" td:eq(1)");
+    ProxmoxCloudVps_td2 = accessInput.html();
+    accessInput.html("<select name=\"accesshash\"><option value=\"pam\">Linux PAM standard authentication</option><option value=\"pve\">Proxmox VE authentication server</option><option value=\"PVEAPIToken\" hidden>API Tokens</option></select>");
+    ProxmoxCloudVps_accesshash ? $("select[name='accesshash']").val(ProxmoxCloudVps_accesshash): $("select[name='accesshash']").val("pam")
+    ProxmoxCloudVps_selectAdded = true;
+
+}
+
+function ProxmoxCloudVps_removeSelect(){
+    $( "#inputServerType").closest("tbody").find(" tr:eq(3)").find(" td:eq(0)").html(ProxmoxCloudVps_td1);
+    $(  "#inputServerType").closest("tbody").find(" tr:eq(3)").find(" td:eq(1)").html(ProxmoxCloudVps_td2);
+    ProxmoxCloudVps_selectAdded = false
+}
+
+$(document).ready(function(){
+
+    var pc_ServerType =  $( "#inputServerType").val();
+
+    ProxmoxCloudVps_accesshash = $( "textarea[name='accesshash']").val();
+    if(pc_ServerType=="ProxmoxCloudVps" || pc_ServerType=="ProxmoxCloudVps"){
+        ProxmoxCloudVps_addSelect();
+    }
+
+    $( "#inputServerType").change(function(){
+        pc_ServerType = $( this).val();
+
+        if(ProxmoxCloudVps_selectAdded==true &&  pc_ServerType!="ProxmoxCloudVps" && pc_ServerType!="ProxmoxCloudVps"   ){
+            ProxmoxCloudVps_removeSelect();
+        }else if(!ProxmoxCloudVps_selectAdded && pc_ServerType=="ProxmoxCloudVps" || pc_ServerType=="ProxmoxCloudVps"  ){
+            ProxmoxCloudVps_addSelect();
+        }
+
+    });
+});

+ 51 - 0
app/UI/Admin/Templates/assets/js/product/index.js

@@ -0,0 +1,51 @@
+//replace url wrapper
+var mgUrlParser = {
+    oldMgUrlParser: mgUrlParser,
+
+    getCurrentUrl: function () {
+        var url = this.oldMgUrlParser.getCurrentUrl();
+        return url.replace("action=edit", "action=module-settings").replace("&success=true", "");
+    }
+};
+//change virtualization
+$(document).on("click", ".virtualizationChangeConfirmButton", function (event) {
+    event.preventDefault();
+    $("form[name=packagefrm]").submit();
+});
+$(document).on("change", "select[name='customconfigoption[virtualization]']", function () {
+    document.getElementById("virtualizationChangButton").click();
+});
+//default node
+$(document).on("change", "select[name='customconfigoption[defaultNode]']", function () {
+    $("form[name=packagefrm]").submit();
+});
+// Disk Speed
+$(document).on("change", "input[name='customconfigoption[diskSpeed]']", function (e) {
+    var show = $(this).is(":checked");
+    $("input[name='customconfigoption[mbps_rd]']").closest(".lu-widget").toggle(show);
+});
+if ($("input[name='customconfigoption[diskSpeed]']").size()) {
+    $("input[name='customconfigoption[diskSpeed]']").trigger('change');
+}
+//Additional Disk Speed
+$(document).on("change", "input[name='customconfigoption[additionalDiskSpeed]']", function (e) {
+    var show = $(this).is(":checked");
+    $("input[name='customconfigoption[additionalDiskMbps_rd]']").closest(".lu-widget").toggle(show);
+});
+if ($("input[name='customconfigoption[additionalDiskSpeed]']").size()) {
+    $("input[name='customconfigoption[additionalDiskSpeed]']").trigger('change');
+}
+//Storage LVM
+$(document).on("change", "select[name='customconfigoption[diskStorage]']",function(e){
+    var storage = $(this).val();
+    if(storage.match(/lvm/)){
+        $("select[name='customconfigoption[diskFormat]']").val("raw");
+        $("select[name='customconfigoption[diskFormat]'] option").attr("disabled",true);
+        $("select[name='customconfigoption[diskFormat]'] option[value=raw]").attr("disabled",false);
+    }else{
+        $("select[name='customconfigoption[diskFormat]'] option").attr("disabled",false);
+    }
+});
+if ($("input[name='customconfigoption[diskStorage]']").size()) {
+    $("input[name='customconfigoption[diskStorage]']").trigger('change');
+}

+ 113 - 0
app/UI/Admin/User/Pages/UserDataTable.php

@@ -0,0 +1,113 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\User\Pages;
+
+use MGProvision\Proxmox\v2\models\User;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class UserDataTable extends DataTable implements AdminArea
+{
+
+    use ProductService;
+    use UserService;
+    use ApiService;
+
+    protected $id = 'userDataTable';
+    protected $title = 'userDataTable';
+    protected $searchable = false;
+    protected $tableLength = "100";
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('username')))
+            ->addColumn((new Column('realm')))
+            ->addColumn((new Column('password')))
+            ->addColumn((new Column('enable')))
+            ->addColumn((new Column('expire')))
+            ->addColumn((new Column('name')))
+            ->addColumn((new Column('comment')));
+    }
+
+    public function replaceFieldExpire($key, $row)
+    {
+        if ($row[$key] == 0)
+        {
+            return sl("lang")->tr("Never");
+        }
+        return $row[$key];
+    }
+
+    public function replaceFieldEnable($key, $row)
+    {
+        if ($row[$key])
+        {
+            return '<span class="lu-label lu-label--success lu-label--status">' . sl('lang')->tr("Yes") . '</span>';
+        }
+        return '<span class="lu-label lu-label--danger lu-label--status">' . sl('lang')->tr("No") . '</span>';
+    }
+
+    protected function loadData()
+    {
+        $data = [];
+        if ($this->isUser())
+        {
+            $user        = $this->getUser();
+            $userService = new User("{$user->username}@{$user->realm}");
+            $userService->setApi($this->api());
+            $configuration = $userService->configuration();
+            $data[]        = [
+                'username' => $user->username,
+                'password' => $user->getPassword(),
+                'realm'    => $user->realm,
+                'enable'   => $configuration['enable'],
+                'expire'   => $configuration['expire'],
+                'name'     => $configuration['firstname'] . " " . $configuration['lastname'],
+                'comment'  => $configuration['comment'],
+            ];
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+
+    public function initContent()
+    {
+
+    }
+
+    public function isViewFooter()
+    {
+        return false;
+    }
+
+    public function isViewTopBody()
+    {
+        return false;
+    }
+
+}

+ 35 - 0
app/UI/Backup/Buttons/CreateButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Modals\CreateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+
+class CreateButton extends ButtonCreate implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createButton');
+        $this->initLoadModalAction(new CreateModal());
+    }
+
+}

+ 36 - 0
app/UI/Backup/Buttons/DeleteButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class DeleteButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteButton');
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteModal());
+    }
+
+}

+ 36 - 0
app/UI/Backup/Buttons/DeleteMassButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Modals\DeleteMassModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonMassAction;
+
+class DeleteMassButton extends ButtonMassAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteMassButton');
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteMassModal());
+    }
+
+}

+ 36 - 0
app/UI/Backup/Buttons/RestoreButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Modals\RestoreModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class RestoreButton extends ButtonDataTableModalAction implements ClientArea
+{
+    protected $icon = 'lu-zmdi lu-zmdi-time-restore-setting';
+
+    public function initContent()
+    {
+        $this->initIds('restoreButton ');
+        $this->initLoadModalAction(new RestoreModal());
+    }
+
+}

+ 84 - 0
app/UI/Backup/Forms/CreateForm.php

@@ -0,0 +1,84 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Providers\BackupProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+
+class CreateForm extends BaseForm implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('createBackupForm');
+        $this->setFormType('create');
+        $this->setProvider(new BackupProvider());
+        $backupFilesLimit = $this->configuration()->getBackupMaxFiles();
+        if ($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) && $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) != "-1")
+        {
+            $backupFilesLimit = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
+        }
+        if($backupFilesLimit == "-1"){
+            $backupFilesLimit = null;
+        }
+        if ($this->configuration()->isBackupRouting() && $backupFilesLimit)
+        {
+            sl("lang")->addReplacementConstant("backupFilesLimit" , $backupFilesLimit);
+            $this->setInternalAlertMessage( sl("lang")->tr('Your routing backup limit is :backupFilesLimit:. When you exceed this limit, the last backup will be replaced with a new one.'));
+            $this->setInternalAlertMessageRaw(true);
+        }
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+
+    private function initFields()
+    {
+        //compress
+        $field = new Select('compress');
+        $field->setAvailableValues([
+            "0"    => sl("lang")->tr("None"),
+            "lzo"  => sl("lang")->tr("LZO (fast)"),
+            "gzip" => sl("lang")->tr("GZIP (good)"),
+            "zstd" => sl("lang")->abtr("ZSTD (fast and good)")
+        ]);
+        $field->setDefaultValue('zstd');
+        $this->addField($field);
+        //mode
+        $field = new Select('mode');
+        $field->setAvailableValues([
+            "snapshot" => sl("lang")->tr("Snapshot"),
+            "suspend"  => sl("lang")->tr("Suspend"),
+            "stop"     => sl("lang")->tr("Stop")
+        ]);
+        $this->addField($field);
+    }
+}

+ 52 - 0
app/UI/Backup/Forms/DeleteForm.php

@@ -0,0 +1,52 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Providers\BackupProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class DeleteForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteBackupForm');
+        $this->setFormType('delete');
+        $this->setProvider(new BackupProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDelete');
+        $this->addField(new Hidden("volid"));
+        $this->addField(new Hidden("date"));
+        $this->addField(new Hidden("hour"));
+    }
+
+}

+ 48 - 0
app/UI/Backup/Forms/DeleteMassForm.php

@@ -0,0 +1,48 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Providers\BackupProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+
+
+class DeleteMassForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteMassBackupForm');
+        $this->setFormType('deleteMass');
+        $this->setProvider(new BackupProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['deleteMass'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDeleteMass');
+    }
+
+}

+ 51 - 0
app/UI/Backup/Forms/RestoreForm.php

@@ -0,0 +1,51 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Providers\BackupProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class RestoreForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('restoreBackupForm');
+        $this->setFormType('restore');
+        $this->setProvider(new BackupProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['restore'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmRestore');
+        $this->addField(new Hidden("volid"));
+        $this->addField(new Hidden("date"));
+        $this->addField(new Hidden("hour"));
+    }
+}

+ 35 - 0
app/UI/Backup/Modals/CreateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Forms\CreateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class CreateModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createBackupModal');
+        $this->addForm(new CreateForm());
+    }
+
+}

+ 35 - 0
app/UI/Backup/Modals/DeleteMassModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Forms\DeleteMassForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteMassModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteBackupMassModal');
+        $this->addForm(new DeleteMassForm());
+    }
+
+}

+ 35 - 0
app/UI/Backup/Modals/DeleteModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteBackupModal');
+        $this->addForm(new DeleteForm());
+    }
+
+}

+ 35 - 0
app/UI/Backup/Modals/RestoreModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Forms\RestoreForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmSuccess;
+
+class RestoreModal extends ModalConfirmSuccess implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('restoreBackupModal');
+        $this->addForm(new RestoreForm());
+    }
+
+}

+ 100 - 0
app/UI/Backup/Pages/BackupDataTable.php

@@ -0,0 +1,100 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Pages;
+
+use MGProvision\Proxmox\v2\repository\FileRepository;
+use ModulesGarden\ProxmoxAddon\App\Libs\Format;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Buttons\CreateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Buttons\RestoreButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+
+class BackupDataTable extends DataTable implements ClientArea
+{
+    use ProductService, ApiService;
+
+    protected $id   = 'backupDataTable';
+    protected $name = 'backupDataTableName';
+    protected $title = 'backupDataTableTitle';
+
+    public function isRawTitle()
+    {
+        return false;
+    }
+
+    public function initContent()
+    {
+        //Create
+        $createButton = new CreateButton();
+        $createButton->addClass("pmCreateBackupButton");
+        if (!$this->resourceGuard()->hasBackupLimit())
+        {
+            $createButton->addClass("hidden");
+        }
+        $this->unsetShowTitle();
+        if ($this->configuration()->isPermissionBackup())
+        {
+            $this->addButton($createButton);
+        }
+
+        //Restore
+        $this->addActionButton(new RestoreButton());
+        //Delete
+        $this->addActionButton(new DeleteButton());
+        //Delete Mass
+        $this->addMassActionButton(new DeleteMassButton());
+    }
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('date'))->setSearchable(true, "date")->setOrderable('DESC'))
+            ->addColumn((new Column('format'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('size'))->setSearchable(true)->setOrderable());
+    }
+
+    protected function loadData()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $backupRepository = new FileRepository();
+        $backupRepository->setApi($this->api());
+        $backupRepository->findBackup($vm)
+            ->findByStorages([$this->configuration()->getBackupStorage()]);
+        $data = [];
+        foreach ($backupRepository->fetch() as $file)
+        {
+            $row         = $file->getAttributes();
+            $row['size'] = Format::convertBytes($row['size']);
+            $row['date'] = $row['date'] . " " . $row['hour'];
+            $data[]      = array_merge(['id' => base64_encode(json_encode($row))], $row);
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setDefaultSorting("date", 'DESC');
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+
+}

+ 119 - 0
app/UI/Backup/Providers/BackupProvider.php

@@ -0,0 +1,119 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Providers;
+
+use MGProvision\Proxmox\v2\models\File;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\RestoreVm;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
+
+class BackupProvider extends BaseDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function read()
+    {
+        if ($this->actionElementId)
+        {
+            $this->data = json_decode(base64_decode($this->actionElementId), true);
+        }
+    }
+
+    public function create()
+    {
+        $this->acl()->backup();
+        $this->resourceGuard()->backupLimit();
+        $storage  = $this->configuration()->getBackupStorage();
+        $routing  = $this->configuration()->isBackupRouting() ? 1 : 0;
+        $maxFiles       =  $this->configuration()->getBackupMaxFiles();
+        if($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) &&  $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)!="-1"){
+            $maxFiles       = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
+        }else if($this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)=="-1"){
+            $maxFiles       = null;
+        }
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vm ->backup($storage, $routing, $maxFiles, $this->formData['compress'], $this->formData['mode']);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The backup creation is in progress')
+            ->addData('createButtonStatus', $this->configuration()->isPermissionBackup() && $this->resourceGuard()->hasBackupLimit())
+            ->setCallBackFunction('pmToggleBackupButton');
+    }
+
+    public function restore()
+    {
+        $id = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        queue(RestoreVm::class, ['volid' => $this->formData['volid']], null, 'hosting', $this->getWhmcsParamByKey('serviceid'), $id);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The virtual machine restore is in progress');
+    }
+
+    public function update()
+    {
+
+    }
+
+    public function delete()
+    {
+        $this->acl()->backup();
+        $node = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->node;
+        $storage    = $this->configuration()->getBackupStorage();
+        $volid      = $this->formData['volid'];
+        $backupFile = new File();
+        $backupFile->setApi($this->api());
+        $backupFile->setPath("/nodes/{$node}/storage/{$storage}/content/{$volid}");
+        $backupFile->delete();
+
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The backup has been deleted successfully')
+            ->addData('createButtonStatus', $this->configuration()->isPermissionBackup() && $this->resourceGuard()->hasBackupLimit())
+            ->setCallBackFunction('pmToggleBackupButton');
+    }
+
+    public function deleteMass()
+    {
+        $this->acl()->backup();
+        $node = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->node;
+        $storage    = $this->configuration()->getBackupStorage();
+        $backupFile = new File();
+        $backupFile->setApi($this->api());
+        foreach ($this->request->get('massActions') as $id)
+        {
+            $data  = json_decode(base64_decode($id), true);
+            $volid = $data['volid'];
+            $backupFile->setPath("/nodes/{$node}/storage/{$storage}/content/{$volid}");
+            $backupFile->delete();
+        }
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The backups have been deleted successfully')
+            ->addData('createButtonStatus', $this->configuration()->isPermissionBackup() && $this->resourceGuard()->hasBackupLimit())
+            ->setCallBackFunction('pmToggleBackupButton');
+    }
+
+}

+ 35 - 0
app/UI/BackupJob/Buttons/CreateButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Modals\CreateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+
+class CreateButton extends ButtonCreate implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createButton');
+        $this->initLoadModalAction(new CreateModal());
+    }
+
+}

+ 36 - 0
app/UI/BackupJob/Buttons/DeleteButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class DeleteButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteButton');
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteModal());
+    }
+
+}

+ 85 - 0
app/UI/BackupJob/Buttons/MailtoSwitchButton.php

@@ -0,0 +1,85 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Buttons;
+
+use MGProvision\Proxmox\v2\models\BackupSchedule;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\DataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonSwitchAjax;
+
+class MailtoSwitchButton extends ButtonSwitchAjax implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+    protected $switchColumn = 'mailto';
+    protected $id = 'mailtoSwitchButton';
+    protected $name = 'mailtoSwitchButton';
+    protected $refreshActionIds = 'backupJobDataTable';
+
+    public function returnAjaxData()
+    {
+        try
+        {
+
+            $data           = json_decode(base64_decode($this->getRequestValue('actionElementId')), true);
+            $storage        = $this->configuration()->getBackupStorage() ? $this->configuration()->getBackupStorage() : "local";
+            $routing        = 1;
+            $maxFiles       =  $this->configuration()->getBackupMaxFiles();
+            if($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) &&  $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)!="-1"){
+                $maxFiles       = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
+            }else if($this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)=="-1"){
+                $maxFiles       = null;
+            }
+            $backupSchedule = new BackupSchedule();
+            $backupSchedule->setApi($this->api());
+            $vmid = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->vmid;
+            $backupSchedule->setAttributes([
+                "id"        => $data['backupScheduleId'],
+                "vmid"      => $vmid,
+                "storage"   => $storage,
+                "remove"    => $routing,
+                "maxfiles"  => $maxFiles,
+                "starttime" => $data['starttime'],
+                "dow"       => $data['dow'],
+                "mode"      => $data['mode'],
+                "compress"  => $data['compress'],
+                "mailto"    => $this->getRequestValue("value") == "on" ? $this->getWhmcsParamByKey('clientsdetails')['email'] : null,
+            ]);
+            $backupSchedule->update();
+        }
+        catch (\Exception $exc)
+        {
+            return (new DataJsonResponse())->setStatusError()->setMessage($exc->getMessage())->setCallBackFunction($this->callBackFunction)->addRefreshTargetId($this->refreshActionIds);
+        }
+        return (new DataJsonResponse())->setMessageAndTranslate('changesSaved')
+                                       ->setCallBackFunction('pmOnBackupJobChanged');
+    }
+
+    /**
+     *
+     */
+    protected function afterInitContent()
+    {
+        //Why?
+    }
+}

+ 35 - 0
app/UI/BackupJob/Buttons/UpdateButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Modals\UpdateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class UpdateButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateButton');
+        $this->initLoadModalAction(new UpdateModal());
+    }
+
+}

+ 120 - 0
app/UI/BackupJob/Forms/CreateForm.php

@@ -0,0 +1,120 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Providers\BackupJobProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Providers\FirewallOptionProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\StartTimeValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Helpers\AlertTypesConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+
+class CreateForm extends BaseForm implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('createForm');
+        $this->setFormType('create');
+        $this->setProvider(new BackupJobProvider());
+        $backupFilesLimit = $this->configuration()->getBackupMaxFiles();
+        if ($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) &&
+            $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) != "-1")
+        {
+            $backupFilesLimit = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
+        }
+
+        if ($backupFilesLimit == "-1")
+        {
+            $backupFilesLimit = null;
+        }
+
+        if ($this->configuration()->isBackupRouting() && $backupFilesLimit)
+        {
+            sl("lang")->addReplacementConstant("backupFilesLimit", $backupFilesLimit);
+            $this->setInternalAlertMessage(sl("lang")->tr('Your routing backup limit is :backupFilesLimit:. When you exceed this limit, the last backup will be replaced with a new one.'));
+            $this->setInternalAlertMessageRaw(true);
+            $this->setInternalAlertMessageType(AlertTypesConstants::INFO);
+        }
+
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+
+    private function initFields()
+    {
+        //starttime
+        $field = new Text('starttime');
+        $field->setPlaceholder("00:00");
+        $field->addValidator(new StartTimeValidator());
+        $this->addField($field);
+        //dow
+        $field = new Select('dow');
+        $field->enableMultiple();
+        $field->setAvailableValues([
+            "mon" => sl("lang")->tr("mon"),
+            "tue" => sl("lang")->tr("tue"),
+            "wed" => sl("lang")->tr("wed"),
+            "thu" => sl("lang")->tr("thu"),
+            "fri" => sl("lang")->tr("fri"),
+            "sat" => sl("lang")->tr("sat"),
+            "sun" => sl("lang")->tr("sun")
+        ]);
+        $field->notEmpty();
+        $this->addField($field);
+        //compress
+        $field = new Select('compress');
+        $field->setAvailableValues([
+            "0"    => sl("lang")->tr("0"),
+            "lzo"  => sl("lang")->tr("lzo"),
+            "gzip" => sl("lang")->tr("gzip"),
+            "zstd" => sl("lang")->tr("zstd")
+        ]);
+        $field->setDefaultValue('zstd');
+        $field->notEmpty();
+        $this->addField($field);
+        //mode
+        $field = new Select('mode');
+        $field->setAvailableValues([
+            "snapshot" => sl("lang")->tr("snapshot"),
+            "suspend"  => sl("lang")->tr("suspend"),
+            "stop"     => sl("lang")->tr("stop")
+        ]);
+        $field->notEmpty();
+        $this->addField($field);
+        //mailto
+        $field = new Switcher("mailto");
+        $this->addField($field);
+
+    }
+}

+ 51 - 0
app/UI/BackupJob/Forms/DeleteForm.php

@@ -0,0 +1,51 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Providers\BackupJobProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class DeleteForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteForm');
+        $this->setFormType('delete');
+        $this->setProvider(new BackupJobProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDelete');
+        $this->addField(new Hidden("backupScheduleId"));
+        $this->addField(new Hidden("displayId"));
+    }
+
+}

+ 124 - 0
app/UI/BackupJob/Forms/UpdateForm.php

@@ -0,0 +1,124 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Providers\BackupJobProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\StartTimeValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Helpers\AlertTypesConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+
+class UpdateForm extends BaseForm implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('updateForm');
+        $this->setFormType('update');
+        $this->setProvider(new BackupJobProvider());
+        $backupFilesLimit = $this->configuration()->getBackupMaxFiles();
+        if ($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) &&
+            $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) != "-1")
+        {
+            $backupFilesLimit = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
+        }else if($this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) == "-1"){
+            $backupFilesLimit = null;
+        }
+        if ($this->configuration()->isBackupRouting() && $backupFilesLimit)
+        {
+            sl("lang")->addReplacementConstant("backupFilesLimit" , $backupFilesLimit);
+            $this->setInternalAlertMessage( sl("lang")->tr('Your routing backup limit is :backupFilesLimit:. When you exceed this limit, the last backup will be replaced with a new one.'));
+            $this->setInternalAlertMessageRaw(true);
+            $this->setInternalAlertMessageType(AlertTypesConstants::INFO);
+        }
+        else
+        {
+            $this->setInternalAlertMessage('confirmUpdate');
+            $this->setInternalAlertMessageType(AlertTypesConstants::INFO);
+        }
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['update'];
+    }
+
+    private function initFields()
+    {
+        //backupScheduleId
+        $this->addField(new Hidden("backupScheduleId"));
+        //displayId
+        $this->addField(new Hidden("displayId"));
+        //starttime
+        $field = new Text('starttime');
+        $field->setPlaceholder("00:00");
+        $field->addValidator(new StartTimeValidator());
+        $this->addField($field);
+        //dow
+        $field = new Select('dow');
+        $field->enableMultiple();
+        $field->setAvailableValues([
+            "mon" => sl("lang")->tr("mon"),
+            "tue" => sl("lang")->tr("tue"),
+            "wed" => sl("lang")->tr("wed"),
+            "thu" => sl("lang")->tr("thu"),
+            "fri" => sl("lang")->tr("fri"),
+            "sat" => sl("lang")->tr("sat"),
+            "sun" => sl("lang")->tr("sun")
+        ]);
+        $field->notEmpty();
+        $this->addField($field);
+        //compress
+        $field = new Select('compress');
+        $field->setAvailableValues([
+            "0"    => sl("lang")->tr("0"),
+            "lzo"  => sl("lang")->tr("lzo"),
+            "gzip" => sl("lang")->tr("gzip"),
+            "zstd" => sl("lang")->tr("zstd")
+        ]);
+        $field->setDefaultValue('zstd');
+        $field->notEmpty();
+        $this->addField($field);
+        //mode
+        $field = new Select('mode');
+        $field->setAvailableValues([
+            "snapshot" => sl("lang")->tr("snapshot"),
+            "suspend"  => sl("lang")->tr("suspend"),
+            "stop"     => sl("lang")->tr("stop")
+        ]);
+        $field->notEmpty();
+        $this->addField($field);
+        //mailto
+        $field = new Switcher("mailto");
+        $this->addField($field);
+
+    }
+}

+ 35 - 0
app/UI/BackupJob/Modals/CreateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Forms\CreateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class CreateModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createBackupJobModal');
+        $this->addForm(new CreateForm());
+    }
+
+}

+ 35 - 0
app/UI/BackupJob/Modals/DeleteModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteBackupJobModal');
+        $this->addForm(new DeleteForm());
+    }
+
+}

+ 35 - 0
app/UI/BackupJob/Modals/UpdateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Forms\UpdateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class UpdateModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateBackupJobModal');
+        $this->addForm(new UpdateForm());
+    }
+
+}

+ 125 - 0
app/UI/BackupJob/Pages/BackupJobDataTable.php

@@ -0,0 +1,125 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Pages;
+
+use MGProvision\Proxmox\v2\repository\BackupScheduleRepository;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Buttons\CreateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Buttons\MailtoSwitchButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Buttons\RestoreButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Buttons\UpdateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class BackupJobDataTable extends DataTable implements ClientArea
+{
+    use ProductService, ApiService;
+
+    protected $id = 'backupJobDataTable';
+    protected $title = 'backupJobDataTable';
+
+    public function initContent()
+    {
+        //Create
+        $this->unsetShowTitle();
+        $createButton = new CreateButton();
+        $createButton->addClass("pmCreateBackupButton");
+        if (!$this->resourceGuard()->hasBackupJobLimit())
+        {
+            $createButton->addClass("hidden");
+        }
+        $this->addButton($createButton );
+        //Update
+        $this->addActionButton(new UpdateButton());
+        //Delete
+        $this->addActionButton(new DeleteButton());
+    }
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('displayId'))->setSearchable(true, "int")->setOrderable('DESC'))
+            ->addColumn((new Column('starttime'))->setSearchable(true, "date")->setOrderable())
+            ->addColumn((new Column('dow'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('compress'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('mode'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('mailto')));
+    }
+
+
+    public function replaceFieldDow($key, $row)
+    {
+        $down = explode(",", $row['dow']);
+        $days = [];
+        foreach ($down as $day)
+        {
+            $days[] = sl('lang')->tr($day);
+        }
+        return implode(", ", $days);
+    }
+
+    public function replaceFieldCompress($key, $row)
+    {
+        return sl('lang')->tr($row['compress']);
+    }
+
+    public function replaceFieldMode($key, $row)
+    {
+        return sl('lang')->tr($row['mode']);
+    }
+
+    public function customColumnHtmlMailto()
+    {
+        return (new MailtoSwitchButton())->getHtml();
+    }
+
+    public function replaceFieldMailto($key, $row)
+    {
+        return $row['mailto'] ? "on" : "off";
+
+    }
+
+    protected function loadData()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $scheduleRepository = new BackupScheduleRepository();
+        $scheduleRepository->setApi($this->api());
+        $scheduleRepository->findByVm($vm);
+        $data = [];
+        foreach ($scheduleRepository->fetch() as $job)
+        {
+            $row                     = $job->getAttributes();
+            $row['backupScheduleId'] = $row['id'];
+            unset($row['id'], $row['days']);
+            $data[] = array_merge(['id' => base64_encode(json_encode($row))], $row);
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setDefaultSorting("displayId", 'DESC');
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+
+}

+ 133 - 0
app/UI/BackupJob/Providers/BackupJobProvider.php

@@ -0,0 +1,133 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Providers;
+
+use MGProvision\Proxmox\v2\models\BackupSchedule;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+class BackupJobProvider extends BaseDataProvider implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+
+    public function read()
+    {
+        if ($this->actionElementId)
+        {
+            $this->data = json_decode(base64_decode($this->actionElementId), true);
+            //down
+            $dow               = $this->data['dow'];
+            $this->data['dow'] = explode(",", $dow);
+            //mailto
+            $mailto               = $this->data['mailto'];
+            $this->data['mailto'] = $mailto ? "on" : "off";
+        }
+    }
+
+    public function create()
+    {
+        $this->acl()->backupJob();
+        $this->resourceGuard()->backupJobLimit();
+        $storage        = $this->configuration()->getBackupStorage();
+        $routing        = $this->configuration()->isBackupRouting() ? 1 : 0;
+        $maxFiles       =  $this->configuration()->getBackupMaxFiles();
+
+        if($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) &&  $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)!="-1"){
+            $maxFiles       = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
+        }else if($this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)=="-1"){
+            $maxFiles       = null;
+        }
+        $backupSchedule = new BackupSchedule();
+        $backupSchedule->setApi($this->api());
+        $vmid = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->vmid;
+        $backupSchedule->setAttributes([
+            "vmid"      => $vmid,
+            "storage"   => $storage,
+            "remove"    => $routing,
+            "maxfiles"  => $maxFiles,
+            "starttime" => $this->formData['starttime'],
+            "dow"       => implode(",", $this->formData['dow']),
+            "mode"      => $this->formData['mode'],
+            "compress"  => $this->formData['compress'],
+            "mailto"    => $this->formData['mailto'] == "on" ? $this->getWhmcsParamByKey('clientsdetails')['email'] : null,
+        ]);
+        $backupSchedule->create();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The backup job has been created successfully')
+            ->setRefreshTargetIds(['backupJobDataTable'])
+            ->addData('createButtonStatus', $this->resourceGuard()->hasBackupJobLimit())
+            ->setCallBackFunction('pmToggleBackupButton');
+    }
+
+    public function update()
+    {
+        $this->acl()->backupJob();
+        $storage        = $this->configuration()->getBackupStorage();
+        $routing        = $this->configuration()->isBackupRouting() ? 1 : 0;
+        $maxFiles       =  $this->configuration()->getBackupMaxFiles();
+        if($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) &&  $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)!="-1"){
+            $maxFiles       = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
+        }else if($this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)=="-1"){
+            $maxFiles       = null;
+        }
+        $backupSchedule = new BackupSchedule();
+        $backupSchedule->setApi($this->api());
+        $vmid = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->vmid;
+        $backupSchedule->setAttributes([
+            "id"        => $this->formData['backupScheduleId'],
+            "vmid"      => $vmid,
+            "storage"   => $storage,
+            "remove"    => $routing,
+            "maxfiles"  => $maxFiles,
+            "starttime" => $this->formData['starttime'],
+            "dow"       => implode(",", $this->formData['dow']),
+            "mode"      => $this->formData['mode'],
+            "compress"  => $this->formData['compress'],
+            "mailto"    => $this->formData['mailto'] == "on" ? $this->getWhmcsParamByKey('clientsdetails')['email'] : null,
+        ]);
+        $backupSchedule->update();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The backup job has been updated successfully');
+    }
+
+    public function delete()
+    {
+        $this->acl()->backupJob();
+        $backupSchedule = new BackupSchedule();
+        $backupSchedule->setApi($this->api());
+        $backupSchedule->setId($this->formData['backupScheduleId']);
+        $backupSchedule->delete();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The backup job has been deleted successfully')
+            ->setRefreshTargetIds(['backupJobDataTable'])
+            ->addData('createButtonStatus', 1)
+            ->setCallBackFunction('pmToggleBackupButton');
+    }
+
+
+}

+ 21 - 0
app/UI/Client/Templates/assets/css/integration.css

@@ -0,0 +1,21 @@
+#contentarea > div > h1 {
+    display: block !important;
+}
+
+#contentarea {
+    margin: 10px;
+    padding: 15px;
+    min-height: 600px;
+    background-color: #fff;
+    border: 4px solid #e2e7e9;
+    -moz-border-radius: 10px;
+    -webkit-border-radius: 10px;
+    -o-border-radius: 10px;
+    border-radius: 10px;
+    overflow: auto;
+}
+
+.mg-integration-container .lu-app {
+    height: 0px;
+    visibility: hidden;
+}

+ 157 - 0
app/UI/Client/Templates/assets/css/module_styles.css

@@ -0,0 +1,157 @@
+#layers .lu-app .progress-bar[aria-valuenow="0"] {
+    min-width: 30px;
+    color: #777;
+    background-color: transparent;
+    background-image: none;
+    box-shadow: none;
+}
+
+.pm-resource-usege {
+    clear: both;
+    width: 40% !important;
+    margin-bottom: 2px !important;
+}
+
+
+/*background: #2368AD; tło #e9ebf0*/
+
+input[type=range] {
+    height: 25px;
+    -webkit-appearance: none;
+    margin: 10px 0;
+    width: 100%;
+}
+input[type=range]:focus {
+    outline: none;
+}
+input[type=range]::-webkit-slider-runnable-track {
+    width: 100%;
+    height: 5px;
+    cursor: pointer;
+    animate: 0.2s;
+    box-shadow: 0px 0px 0px #E9EBF0;
+    background: #2368AD;
+    border-radius: 1px;
+    border: 0px solid #E9EBF0;
+}
+input[type=range]::-webkit-slider-thumb {
+    box-shadow: 0px 0px 0px #000000;
+    border: 1px solid #174370;
+    height: 18px;
+    width: 18px;
+    border-radius: 25px;
+    background: #2368AD;
+    cursor: pointer;
+    -webkit-appearance: none;
+    margin-top: -7px;
+}
+input[type=range]:focus::-webkit-slider-runnable-track {
+    background: #2368AD;
+}
+input[type=range]::-moz-range-track {
+    width: 100%;
+    height: 5px;
+    cursor: pointer;
+    animate: 0.2s;
+    box-shadow: 0px 0px 0px #E9EBF0;
+    background: #2368AD;
+    border-radius: 1px;
+    border: 0px solid #E9EBF0;
+}
+input[type=range]::-moz-range-thumb {
+    box-shadow: 0px 0px 0px #000000;
+    border: 1px solid #174370;
+    height: 18px;
+    width: 18px;
+    border-radius: 25px;
+    background: #2368AD;
+    cursor: pointer;
+}
+input[type=range]::-ms-track {
+    width: 100%;
+    height: 5px;
+    cursor: pointer;
+    animate: 0.2s;
+    background: transparent;
+    border-color: transparent;
+    color: transparent;
+}
+input[type=range]::-ms-fill-lower {
+    background: #2368AD;
+    border: 0px solid #E9EBF0;
+    border-radius: 2px;
+    box-shadow: 0px 0px 0px #E9EBF0;
+}
+input[type=range]::-ms-fill-upper {
+    background: #2368AD;
+    border: 0px solid #E9EBF0;
+    border-radius: 2px;
+    box-shadow: 0px 0px 0px #E9EBF0;
+}
+input[type=range]::-ms-thumb {
+    margin-top: 1px;
+    box-shadow: 0px 0px 0px #000000;
+    border: 1px solid #174370;
+    height: 18px;
+    width: 18px;
+    border-radius: 25px;
+    background: #2368AD;
+    cursor: pointer;
+}
+input[type=range]:focus::-ms-fill-lower {
+    background: #2368AD;
+}
+input[type=range]:focus::-ms-fill-upper {
+    background: #2368AD;
+}
+
+.lu-range-output{
+    display: block;
+    width:100%;
+    text-align:center;
+    padding-top: 0px !important;
+    position: absolute;
+    top: 5px;
+}
+/*
+.lu-range-output {
+    position: absolute;
+    background-image: linear-gradient(#444444, #999999);
+    width: 40px;
+    height: 30px;
+    text-align: center;
+    color: white;
+    border-radius: 10px;
+    display: inline-block;
+    font: bold 15px/30px Georgia;
+    bottom: 60%;
+    left: 0;
+}*//*
+.lu-range-output:after {
+    content: "";
+    position: absolute;
+    width: 0;
+    height: 0;
+    border-top: 10px solid #999999;
+    border-left: 5px solid transparent;
+    border-right: 5px solid transparent;
+    top: 100%;
+    left: 50%;
+    margin-left: -5px;
+    margin-top: -1px;
+}*/
+
+#layers .lu-progress--h .lu-progress__label{
+    flex-basis: 23%!important;
+}
+
+.vm-actions .lu-widget__content{
+    justify-content: center;
+    display: flex!important;
+    flex-wrap: wrap;
+    padding-bottom: 10px!important;
+}
+
+.vm-actions .lu-btn{
+    width: 23%;
+}

BIN
app/UI/Client/Templates/assets/img/buttons/backup.png


BIN
app/UI/Client/Templates/assets/img/buttons/backupJob.png


BIN
app/UI/Client/Templates/assets/img/buttons/disk.png


BIN
app/UI/Client/Templates/assets/img/buttons/firewall.png


BIN
app/UI/Client/Templates/assets/img/buttons/firewallOption.png


BIN
app/UI/Client/Templates/assets/img/buttons/graph.png


BIN
app/UI/Client/Templates/assets/img/buttons/network.png


BIN
app/UI/Client/Templates/assets/img/buttons/novnc.png


BIN
app/UI/Client/Templates/assets/img/buttons/rebootButton.png


BIN
app/UI/Client/Templates/assets/img/buttons/reinstall.png


BIN
app/UI/Client/Templates/assets/img/buttons/shutdownButton.png


BIN
app/UI/Client/Templates/assets/img/buttons/snapshot.png


BIN
app/UI/Client/Templates/assets/img/buttons/spice.png


BIN
app/UI/Client/Templates/assets/img/buttons/sshKey.png


BIN
app/UI/Client/Templates/assets/img/buttons/startButton.png


BIN
app/UI/Client/Templates/assets/img/buttons/stopButton.png


BIN
app/UI/Client/Templates/assets/img/buttons/taskHistory.png


BIN
app/UI/Client/Templates/assets/img/buttons/vnc.png


BIN
app/UI/Client/Templates/assets/img/buttons/xtermjs.png


+ 54 - 0
app/UI/Client/Templates/assets/js/home/index.js

@@ -0,0 +1,54 @@
+function mgBytesToSize(bytes) {
+    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
+    if (bytes <= 1) {
+        if (bytes !== 0) {
+            var bytes = Number(bytes).toFixed(1);
+        }
+        return bytes + ' Byte';
+    }
+    var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1000)));
+    return Math.round(bytes / Math.pow(1000, i), 2) + ' ' + sizes[i];
+}
+
+function mgTooltipCpu(tooltipItem, data) {
+    var used = Number(tooltipItem.yLabel).toFixed(2);
+    return used + "%";
+}
+
+function mgTooltipServerLoad(tooltipItem, data) {
+    var used = Number(tooltipItem.yLabel).toFixed(2);
+    return used;
+}
+
+function mgTooltipCallbackForMemory(tooltipItem, data) {
+    return mgBytesToSize(tooltipItem.yLabel) + "/s";
+}
+
+function mgTooltipCallbackForNet(tooltipItem, data) {
+    return mgBytesToSize(tooltipItem.yLabel) + "/s";
+}
+
+function mgTooltipCallbackForDisk(tooltipItem, data) {
+    return mgBytesToSize(tooltipItem.yLabel) + "/s";
+}
+
+/*Virtual network*/
+function pmToggleVirtualNetworkButton (data) {
+    mgPageControler.vueLoader.refreshingState = ['virtualNetworkDataTable'];
+    mgPageControler.vueLoader.runRefreshActions();
+    let button = $(".pmCreateVirtualNetworkButton");
+    if(data.htmlData.createButtonStatus)
+    {
+        button.removeClass('hidden');
+    }
+    else
+    {
+        button.addClass('hidden');
+    }
+}
+
+/*VMs each 30 sec*/
+setInterval(function(){
+    mgPageControler.vueLoader.refreshingState = ['vmsDataTable'];
+    mgPageControler.vueLoader.runRefreshActions();
+}, 1000*30);

+ 190 - 0
app/UI/Client/Templates/assets/js/vm/create.js

@@ -0,0 +1,190 @@
+
+/*Create VM*/
+$(document).ready(function () {
+    //change os template
+    $("#osTemplate").change(function (e) {
+        console.log($(this).val() );
+        //show
+        if($(this).val() == "installationFromIso"){
+            if($("#isoImage").size()){
+                $("#isoImage").closest(".lu-form-group").show();
+            }
+            if($("#secondaryIsoImage").size()){
+                $("#secondaryIsoImage").closest(".lu-form-group").show();
+            }
+            // ostype
+            if($('select[name="ostype"]').size()){
+                $('select[name="ostype"]').closest(".lu-form-group").show();
+            }
+            // password
+            if($('input[name="password"]').size()){
+                $('input[name="password"]').closest(".lu-form-group").hide();
+            }
+            // sshkeys
+            if($('textarea[name="sshkeys"]').size()){
+                $('textarea[name="sshkeys"]').closest(".lu-form-group").hide();
+            }
+            // ciuser
+            if($('input[name="ciuser"]').size()){
+                $('input[name="ciuser"]').closest(".lu-form-group").hide();
+            }
+            // searchdomain
+            if($('input[name="searchdomain"]').size()){
+                $('input[name="searchdomain"]').closest(".lu-form-group").hide();
+            }
+            // nameserver
+            if($('input[name="nameserver[0]"]').size()){
+                $('input[name="nameserver[0]"]').closest(".lu-form-group").hide();
+                $('input[name="nameserver[1]"]').closest(".lu-form-group").hide();
+            }
+            //hide
+        }else{
+            if($("#isoImage").size()){
+                $("#isoImage").closest(".lu-form-group").hide();
+            }
+            if($("#secondaryIsoImage").size()){
+                $("#secondaryIsoImage").closest(".lu-form-group").hide();
+            }
+            // ostype
+            if($('select[name="ostype"]').size()){
+                $('select[name="ostype"]').closest(".lu-form-group").hide();
+            }
+            // password
+            if($('input[name="password"]').size()){
+                $('input[name="password"]').closest(".lu-form-group").show();
+            }
+            // sshkeys
+            if($('textarea[name="sshkeys"]').size()){
+                $('textarea[name="sshkeys"]').closest(".lu-form-group").show();
+            }
+            // ciuser
+            if($('input[name="ciuser"]').size()){
+                $('input[name="ciuser"]').closest(".lu-form-group").show();
+            }
+            // searchdomain
+            if($('input[name="searchdomain"]').size()){
+                $('input[name="searchdomain"]').closest(".lu-form-group").show();
+            }
+            // nameserver
+            if($('input[name="nameserver[0]"]').size()){
+                $('input[name="nameserver[0]"]').closest(".lu-form-group").show();
+                $('input[name="nameserver[1]"]').closest(".lu-form-group").show();
+            }
+        }
+    });
+    //fire event
+    $("#osTemplate").trigger("change");
+    //virtual network
+    var selectizedInstance = $('.pm-virtual-network-content-default .selectized').selectize();
+    selectizedInstance.each(function(){
+        this.selectize.destroy();
+    });
+    //create
+    $("#pm-add-new-virtual-network-button").on("click",function (e) {
+        e.preventDefault();
+        var content = $('.pm-virtual-network-content-default').clone();
+        content.removeClass("hidden");
+        content.removeClass("pm-virtual-network-content-default");
+        var index = $("#pm-add-new-virtual-network-button").closest('.lu-widget').find('.lu-widget').size();
+        content.find('select[name="virtualNetwork[id]"]').prop("name","virtualNetwork"+index+"[id]");
+        content.find('select[name="virtualNetwork[ip]"]').prop("name","virtualNetwork"+index+"[ip]");
+        $(this).closest('.lu-widget').find('.lu-widget').last().after(content);
+        $(this).closest('.lu-widget').find('.pm-vn-select').trigger("change");
+        $(this).closest('.lu-widget').find('.lu-alert').hide();
+        $(".pm-virtual-network-content-default").parent().find(".lu-alert").hide();
+    });
+    //delete
+    $(".mg-wrapper").delegate(".pm-delete-virtual-network-button","click",function (e) {
+        e.preventDefault();
+        $(this).closest('.lu-widget').remove();
+        if($(".pm-virtual-network-content-default").parent().find(".lu-widget").length <= 1)
+        {
+            $(".pm-virtual-network-content-default").parent().find(".lu-alert").show();
+        }
+    });
+    //change
+    $(".mg-wrapper").delegate(".pm-vn-select","change",function (e) {
+        var show = '.vn-ip-'+$(this).val();
+        $(this).closest('.lu-widget__content').find('.pm-vn-ip-select option').hide();
+        $(this).closest('.lu-widget__content').find(show).show();
+        var firstOption =  $(this).closest('.lu-widget__content').find('.pm-vn-ip-select '+show+':first').val();
+        $(this).closest('.lu-widget__content').find('.pm-vn-ip-select').val(firstOption);
+    });
+    //disk
+    var selectizedInstance = $('.pm-disk-content-default .selectized').selectize();
+    selectizedInstance.each(function(){
+        this.selectize.destroy();
+    });
+    //create
+    $("#pm-add-disk-button").on("click",function (e) {
+        e.preventDefault();
+        var content = $('.pm-disk-content-default').clone();
+        content.removeClass("hidden");
+        content.removeClass("pm-disk-content-default");
+        var index = $("#pm-add-disk-button").closest('.lu-widget').find('.lu-widget').size();
+        content.find('input[name="additionalDiskSize"]').prop("name","additionalDiskSize"+index);
+        content.find('select[name="additionalDiskBus"]').prop("name","additionalDiskBus"+index);
+        content.find('select[name="additionalDiskFormat"]').prop("name","additionalDiskFormat"+index);
+        content.find('select[name="additionalDiskBackup"]').prop("name","additionalDiskBackup"+index);
+        content.find('input[name="additionalDiskMp"]').prop("name","additionalDiskMp"+index);
+        $(this).closest('.lu-widget').find('.lu-widget').last().after(content);
+        $(".pm-disk-content-default ").parent().find(".lu-alert").hide();
+    });
+    //delete
+    $(".mg-wrapper").delegate(".pm-delete-disk-button","click",function (e) {
+        e.preventDefault();
+        $(this).closest('.lu-widget').remove();
+        if($(".pm-disk-content-default ").parent().find(".lu-widget").length <= 1)
+        {
+            $(".pm-disk-content-default ").parent().find(".lu-alert").show();
+        }
+    });
+    //cpuPriority change
+    $(".mg-wrapper").delegate("#cpuPriority","input",function (e) {
+        e.preventDefault();
+        var label = $(this).data("label"+$(this).val());
+        $("#outputcpuPriority").html(label);
+    });
+});
+
+/* VM Create done*/
+function pcVmCreatedAjaxDone(data) {
+    if(data.htmlData.redirectUrl)
+    {
+        window.location.href = data.htmlData.redirectUrl;
+    }
+}
+
+function pcOsTemplateLoadShowIsoFields(data) {
+    if($("#isoImage").size()){
+        $("#isoImage").closest(".lu-form-group").show();
+    }
+    if($("#secondaryIsoImage").size()){
+        $("#secondaryIsoImage").closest(".lu-form-group").show();
+    }
+    // ostype
+    if($('select[name="ostype"]').size()){
+        $('select[name="ostype"]').closest(".lu-form-group").show();
+    }
+    // password
+    if($('input[name="password"]').size()){
+        $('input[name="password"]').closest(".lu-form-group").hide();
+    }
+    // sshkeys
+    if($('textarea[name="sshkeys"]').size()){
+        $('textarea[name="sshkeys"]').closest(".lu-form-group").hide();
+    }
+    // ciuser
+    if($('input[name="ciuser"]').size()){
+        $('input[name="ciuser"]').closest(".lu-form-group").hide();
+    }
+    // searchdomain
+    if($('input[name="searchdomain"]').size()){
+        $('input[name="searchdomain"]').closest(".lu-form-group").hide();
+    }
+    // nameserver
+    if($('input[name="nameserver[0]"]').size()){
+        $('input[name="nameserver[0]"]').closest(".lu-form-group").hide();
+        $('input[name="nameserver[1]"]').closest(".lu-form-group").hide();
+    }
+}

+ 196 - 0
app/UI/Client/Templates/assets/js/vm/index.js

@@ -0,0 +1,196 @@
+function mgBytesToSize(bytes) {
+    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
+    if (bytes <= 1) {
+        if (bytes !== 0) {
+            var bytes = Number(bytes).toFixed(1);
+        }
+        return bytes + ' Byte';
+    }
+    var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
+    var total = bytes / Math.pow(1024, i) ;
+    if(sizes[i] == 'GB' || sizes[i] == 'TB' ){
+        return total.toFixed(2)+ ' ' + sizes[i];
+    }
+    return Math.round( total, 2) + ' ' + sizes[i];
+}
+
+function mgTooltipCpu(tooltipItem, data) {
+    var used = Number(tooltipItem.yLabel).toFixed(2);
+    return used + "%";
+}
+
+function mgTooltipServerLoad(tooltipItem, data) {
+    var used = Number(tooltipItem.yLabel).toFixed(2);
+    return used;
+}
+
+function mgTooltipCallbackForMemory(tooltipItem, data) {
+    return mgBytesToSize(tooltipItem.yLabel) + "/s";
+}
+
+function mgTooltipCallbackForNet(tooltipItem, data) {
+    return mgBytesToSize(tooltipItem.yLabel) + "/s";
+}
+
+function mgTooltipCallbackForDisk(tooltipItem, data) {
+    return mgBytesToSize(tooltipItem.yLabel) + "/s";
+}
+
+/*Disk support*/
+function pmToggleDiskButton(data) {
+    let button = $(".pmCreateDiskButton");
+    if(data.htmlData.createButtonStatus)
+    {
+        button.removeClass('hidden');
+    }
+    else
+    {
+        button.addClass('hidden');
+    }
+}
+/*Snapshot support*/
+function pmToggleSnapshotButton(data) {
+    let button = $(".pmCreateSnapshotButton");
+    if(data.htmlData.createButtonStatus)
+    {
+        button.removeClass('hidden');
+    }
+    else
+    {
+        button.addClass('hidden');
+    }
+}
+
+/*Backup*/
+function pmToggleBackupButton(data) {
+    let button = $(".pmCreateBackupButton");
+    if(data.htmlData.createButtonStatus)
+    {
+        button.removeClass('hidden');
+    }
+    else
+    {
+        button.addClass('hidden');
+    }
+}
+
+/*Firewall*/
+function pmToggleFirewallButton(data) {
+    let button = $(".pmCreateFirewallButton");
+    if(data.htmlData.createButtonStatus)
+    {
+        button.removeClass('hidden');
+    }
+    else
+    {
+        button.addClass('hidden');
+    }
+}
+
+function mgLocationReload(data) {
+    window.location.reload();
+}
+
+/* VM delete done*/
+function pcVmDeltedAjaxDone(data) {
+    if(data.htmlData.redirectUrl)
+    {
+        window.location.href = data.htmlData.redirectUrl;
+    }
+}
+
+$(document).ready(function () {
+    //virtual network
+    var selectizedInstance = $('.pm-virtual-network-content-default .selectized').selectize();
+    selectizedInstance.each(function(){
+        this.selectize.destroy();
+    });
+    //create
+    $("#pm-add-new-virtual-network-button").on("click",function (e) {
+        e.preventDefault();
+        var content = $('.pm-virtual-network-content-default').clone();
+        content.removeClass("hidden");
+        content.removeClass("pm-virtual-network-content-default");
+        var index = $("#pm-add-new-virtual-network-button").closest('.lu-widget').find('.lu-widget').size();
+        content.find('select[name="virtualNetwork[id]"]').prop("name","virtualNetwork"+index+"[id]");
+        content.find('select[name="virtualNetwork[ip]"]').prop("name","virtualNetwork"+index+"[ip]");
+        $(this).closest('.lu-widget').find('.lu-widget').last().after(content);
+        $(this).closest('.lu-widget').find('.pm-vn-select').trigger("change");
+        $(this).closest('.lu-widget').find('.lu-alert').hide();
+        $(".pm-virtual-network-content-default").parent().find(".lu-alert").hide();
+    });
+    //delete
+    $(".mg-wrapper").delegate(".pm-delete-virtual-network-button","click",function (e) {
+        e.preventDefault();
+        $(this).closest('.lu-widget').remove();
+        if($(".pm-virtual-network-content-default").parent().find(".lu-widget").length <= 1)
+        {
+            $(".pm-virtual-network-content-default").parent().find(".lu-alert").show();
+        }
+    });
+    //change
+    $(".mg-wrapper").delegate(".pm-vn-select","change",function (e) {
+        var show = '.vn-ip-'+$(this).val();
+        $(this).closest('.lu-widget__content').find('.pm-vn-ip-select option').hide();
+        $(this).closest('.lu-widget__content').find(show).show();
+        var firstOption =  $(this).closest('.lu-widget__content').find('.pm-vn-ip-select '+show+':first').val();
+        $(this).closest('.lu-widget__content').find('.pm-vn-ip-select').val(firstOption);
+    });
+    //disk
+    var selectizedInstance = $('.pm-disk-content-default .selectized').selectize();
+    selectizedInstance.each(function(){
+        this.selectize.destroy();
+    });
+
+    //create
+    $("#pm-add-disk-button").on("click",function (e) {
+        e.preventDefault();
+        var content = $('.pm-disk-content-default').clone();
+        content.removeClass("hidden");
+        content.removeClass("pm-disk-content-default");
+        var index = $("#pm-add-disk-button").closest('.lu-widget').find('.lu-widget').size();
+        content.find('input[name="additionalDiskSize"]').prop("name","additionalDiskSize"+index);
+        content.find('select[name="additionalDiskBus"]').prop("name","additionalDiskBus"+index);
+        content.find('select[name="additionalDiskFormat"]').prop("name","additionalDiskFormat"+index);
+        content.find('select[name="additionalDiskBackup"]').prop("name","additionalDiskBackup"+index);
+        content.find('input[name="additionalDiskMp"]').prop("name","additionalDiskMp"+index);
+        $(this).closest('.lu-widget').find('.lu-widget').last().after(content);
+        $(".pm-disk-content-default ").parent().find(".lu-alert").hide();
+    });
+    //delete
+    $(".mg-wrapper").delegate(".pm-delete-disk-button","click",function (e) {
+        e.preventDefault();
+        $(this).closest('.lu-widget').remove();
+        if($(".pm-disk-content-default ").parent().find(".lu-widget").length <= 1)
+        {
+            $(".pm-disk-content-default ").parent().find(".lu-alert").show();
+        }
+    });
+    //cpuPriority change
+    $(".mg-wrapper").delegate("#cpuPriority","input",function (e) {
+        e.preventDefault();
+        var label = $(this).data("label"+$(this).val());
+        $("#outputcpuPriority").html(label);
+    });
+});
+
+$(".mg-wrapper").on("change", "select[name='macro']", function () {
+    var disable = $(this).val()!='0';
+    if(disable){
+        $("input[name='sport']").closest(".lu-form-group").addClass("disabled");
+        $("input[name='dport']").closest(".lu-form-group").addClass("disabled");
+        $("select[name='proto']").closest(".lu-form-group").addClass("disabled");
+    }else{
+        $("input[name='sport']").closest(".lu-form-group").removeClass("disabled");
+        $("input[name='dport']").closest(".lu-form-group").removeClass("disabled");
+        $("select[name='proto']").closest(".lu-form-group").removeClass("disabled");
+    }
+});
+
+mgEventHandler.on('ModalLoaded', 'updateButton', function(id, params){
+    if(id != 'updateButton'){
+        return;
+    }
+    $(".mg-wrapper select[name='macro']").trigger('change');
+
+}, 1000);

+ 39 - 0
app/UI/CustomTemplate/Buttons/CreateButton.php

@@ -0,0 +1,39 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Modals\CreateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\BuildUrl;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class CreateButton extends ButtonCreate implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createButton');
+        $this->initLoadModalAction(new CreateModal());
+    }
+
+
+}

+ 36 - 0
app/UI/CustomTemplate/Buttons/DeleteButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class DeleteButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteButton');
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteModal());
+    }
+
+}

+ 36 - 0
app/UI/CustomTemplate/Buttons/UpdateButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Modals\UpdateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class UpdateButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateButton');
+        $this->initLoadModalAction(new UpdateModal());
+    }
+
+}

+ 59 - 0
app/UI/CustomTemplate/Forms/CreateForm.php

@@ -0,0 +1,59 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Providers\TemplateVmProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Helpers\AlertTypesConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+
+class CreateForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('createForm');
+        $this->setFormType('create');
+        $this->setProvider(new TemplateVmProvider());
+        $this->setInternalAlertMessage('confirmCreate');
+        $this->setInternalAlertMessageType(AlertTypesConstants::DANGER);
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+
+    private function initFields()
+    {
+        //vmId
+        $field = new Select('vmId');
+        $field->notEmpty();
+        $this->addField($field);
+        //description
+        $this->addField(new Textarea('description'));
+    }
+}

+ 53 - 0
app/UI/CustomTemplate/Forms/DeleteForm.php

@@ -0,0 +1,53 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Providers\DeleteTemplateVmProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Providers\DiskProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Providers\FirewallOptionProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class DeleteForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteForm');
+        $this->setFormType('delete');
+        $this->setProvider(new DeleteTemplateVmProvider());
+        $this->initFields();
+        $this->loadDataToForm();;
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDelete', ["name" => null]);
+        $this->addField(new Hidden("id"));
+        $this->addField(new Hidden("name"));
+    }
+
+}

+ 57 - 0
app/UI/CustomTemplate/Forms/UpdateForm.php

@@ -0,0 +1,57 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Providers\TemplateVmProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Providers\UpdateTemplateVmProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Helpers\AlertTypesConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+
+class UpdateForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('updateForm');
+        $this->setFormType('update');
+        $this->setProvider(new UpdateTemplateVmProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['update'];
+    }
+
+    private function initFields()
+    {
+        //vmId
+        $field = new Hidden('id');
+        $this->addField($field);
+        //description
+        $this->addField(new Textarea('description'));
+    }
+}

+ 37 - 0
app/UI/CustomTemplate/Modals/CreateModal.php

@@ -0,0 +1,37 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Forms\CreateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class CreateModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createModal');
+        $this->setModalSizeLarge();
+        $this->addForm(new  CreateForm());
+    }
+
+}

+ 35 - 0
app/UI/CustomTemplate/Modals/DeleteModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteModal extends ModalConfirmDanger implements AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteModal');
+        $this->addForm(new DeleteForm());
+    }
+
+}

+ 39 - 0
app/UI/CustomTemplate/Modals/UpdateModal.php

@@ -0,0 +1,39 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Forms\CreateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Forms\UpdateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class UpdateModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateModal');
+        $this->setModalSizeLarge();
+        $this->addForm(new  UpdateForm());
+    }
+
+}

+ 92 - 0
app/UI/CustomTemplate/Pages/CustomTemplateDataTable.php

@@ -0,0 +1,92 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Pages;
+
+use MGProvision\Proxmox\v2\VmFactory;
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Buttons\CreateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Buttons\ImportButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Buttons\UpdateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonRedirect;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\QueryDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\isAdmin;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class CustomTemplateDataTable extends DataTable implements ClientArea
+{
+
+    use ApiService;
+    use ProductService;
+
+    protected $id = 'customTemplateDataTable';
+    protected $name = 'customTemplateDataTable';
+    protected $title = 'customTemplateDataTable';
+    protected $searchable = false;
+    protected $tableLength = "100";
+
+    public function initContent()
+    {
+        $this->addClass('lu-text-left');
+        //Create
+        $this->addButton(new CreateButton());
+        //Update
+        $this->addActionButton(new UpdateButton());
+        //Delete
+        $this->addActionButton(new DeleteButton());
+    }
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('name')))
+            ->addColumn((new Column('description')));
+    }
+
+    public function replaceFieldDescription($key, $row)
+    {
+        $vmModel = VmModel::ofId($row->id)->firstOrFail();
+        $this->api();
+        $vm = (new VmFactory())->fromVmModel($vmModel);
+        if($vm->config()['description']){
+            return $vm->config()['description'];
+        }
+        return '-';
+    }
+
+    protected function loadData()
+    {
+        $query    = VmModel::select("id", "name", "vcpus", "memory", "disk","disks", "vmid","data")
+            ->ofHostingId($this->getWhmcsParamByKey('serviceid'))
+            ->ofTemplate()
+            ->getQuery();
+        $dataProv = new QueryDataProvider();
+        $dataProv->setDefaultSorting("name", 'ASC');
+        $dataProv->setData($query);
+        $this->setDataProvider($dataProv);
+    }
+
+
+}

+ 46 - 0
app/UI/CustomTemplate/Providers/DeleteTemplateVmProvider.php

@@ -0,0 +1,46 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Providers;
+
+use MGProvision\Proxmox\v2\VmFactory;
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\CloudService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+class DeleteTemplateVmProvider extends BaseDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+    public function read()
+    {
+
+        if ($this->actionElementId && $this->actionElementId != "diskDataTable")
+        {
+            $this->data['id'] = $this->actionElementId;
+            $this->data['name'] = VmModel::where("id", $this->actionElementId)->value("name");
+        }
+    }
+
+    public function update()
+    {
+    }
+
+    public function delete()
+    {
+        //init proxmox addon params
+        (new AppParams())->initFromWhmcsParams();
+        //get vm model
+        $vmModel = VmModel::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                          ->ofId($this->getFormDataValues()['id'])->firstOrFail();
+        //destory vm
+        (new CloudService())->delete($vmModel);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Template has been deleted successfully');
+    }
+}

+ 119 - 0
app/UI/CustomTemplate/Providers/TemplateVmProvider.php

@@ -0,0 +1,119 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Providers;
+
+use MGProvision\Proxmox\v2\repository\NodeRepository;
+use MGProvision\Proxmox\v2\VmFactory;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\MigrateVmJob;
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\Core\Queue\Models\Job;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class TemplateVmProvider extends BaseDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function read()
+    {
+        if (!$this->actionElementId )
+        {
+            return;
+        }
+        foreach (VmModel::ofHostingId($this->getWhmcsParamByKey('serviceid'))->notTemplate()->get() as $item)
+        {
+            $this->availableValues['vmId'][$item->id] = $item->name;
+        }
+    }
+
+    public function create()
+    {
+        $this->api();
+        $this->networkService = new NetworkService();
+        /**
+         * @var VmModel $vmModel
+         */
+        $vmModel = VmModel::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                            ->ofId($this->getFormDataValues()['vmId'])
+                            ->firstOrFail();
+        //VM
+        $vm = (new VmFactory())->fromVmModel($vmModel);
+        \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->setVm($vm);
+        //Stop
+        if($vm->isRunning()){
+            $vm->stop();
+            sleep(2);
+        }
+        //Delete interfaces & return ip addresses
+        $this->networkService->deleteByIpAddresses($vmModel->virtualInterfaces);
+        //Save description
+        $config = [
+            "name" => "custom{$this->getWhmcsParamByKey('serviceid')}-".$vmModel->name,
+            'description'=> $this->getFormDataValues()['description']
+        ];
+        $vm->updateConfig($config);
+        //Convert to template
+        $vm->convertToTemplate();
+        $vmModel->template =1;
+        $vmModel->save();
+        sl("lang")-> addReplacementConstant("name",$vmModel->name);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate("Virtual Machine :name: %s has been converted to template");
+    }
+
+    public function update()
+    {
+//        $vmModel = VmModel::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+//                            ->ofId($this->getFormDataValues()['vmId'])
+//                            ->firstOrFail();
+//        //VM
+//        $vm = (new VmFactory())->fromVmModel($vmModel);
+//        $attributes = [
+//            "targetNode" => $this->formData['target'],
+//            "online"     => $this->formData['online'] == "on" ? 1 : 0
+//        ];
+//        if (Job::where("job", MigrateVmJob::class. '@handle')->whereIn("status", ['waiting', "running", ""])
+//                                                  ->where("rel_id", $this->getWhmcsParamByKey("serviceid"))
+//                                                  ->where("rel_type", "hosting")
+//                                                  ->where("custom_id", $vmModel->id)
+//                                                  ->count())
+//        {
+//            return (new HtmlDataJsonResponse())
+//                ->setStatusError()
+//                ->setMessageAndTranslate("Task 'MigrateVm' already exist");
+//        }
+//        queue(MigrateVmJob::class, $attributes, null, "hosting", $this->getWhmcsParamByKey("serviceid"),$vmModel->id);
+//        sl("lang")-> addReplacementConstant("vmid",$vm->getVmid())-> addReplacementConstant("node", $this->formData['target']);
+//        return (new HtmlDataJsonResponse())
+//            ->setStatusSuccess()
+//            ->setMessageAndTranslate("Starting migration of VM :vmid: to :node:");
+    }
+
+
+}

+ 53 - 0
app/UI/CustomTemplate/Providers/UpdateTemplateVmProvider.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\CustomTemplate\Providers;
+
+use MGProvision\Proxmox\v2\VmFactory;
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\CloudService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+class UpdateTemplateVmProvider extends BaseDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function read()
+    {
+
+        if (!$this->actionElementId)
+        {
+            return;
+        }
+        $this->data['id'] = $this->actionElementId;
+        $vmModel = VmModel::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+            ->ofId($this->actionElementId)->firstOrFail();
+        $this->data['name'] = $vmModel->name;
+        $this->api();
+        $vm = (new VmFactory())->fromVmModel($vmModel);
+        $this->data['description'] =  $vm->config()['description'];
+    }
+
+    public function update()
+    {
+        //get vm model
+        $vmModel = VmModel::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+            ->ofId($this->getFormDataValues()['id'])->firstOrFail();
+        $this->api();
+        $vm = (new VmFactory())->fromVmModel($vmModel);
+        //update
+        $vm->updateConfig(['description'=> $this->getFormDataValues()['description'] ]);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Template has been updated successfully');
+    }
+
+    public function delete()
+    {
+    }
+}

+ 64 - 0
app/UI/Disk/Buttons/BackupSwitchButton.php

@@ -0,0 +1,64 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Buttons;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\DataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonSwitchAjax;
+
+class BackupSwitchButton extends ButtonSwitchAjax implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+    protected $switchColumn = 'backup';
+    protected $id= 'backupSwitchButton';
+    protected $name = 'backupSwitchButton';
+    protected $refreshActionIds = 'diskDataTable';
+
+    public function initContent()
+    {
+        parent::initContent();
+        $this->addHtmlAttribute(':disabled', 'dataRow.master == true');
+        if (!$this->configuration()->isPermissionAdditionalDiskBackup())
+        {
+            $this->htmlAttributes["disabled"] = "";
+        }
+    }
+
+    public function returnAjaxData()
+    {
+        try
+        {
+            $this->acl()->additionalDiskBackup();
+            $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+            $hdd = $vm->findHardDiskById($this->getRequestValue('actionElementId'));
+            $hdd->setBackup($this->getRequestValue("value") == "on" ? null : 0);
+            $hdd->update();
+        }
+        catch (\Exception $exc)
+        {
+            return (new DataJsonResponse())->setStatusError()->setMessage($exc->getMessage())->setCallBackFunction($this->callBackFunction)->addRefreshTargetId($this->refreshActionIds);
+        }
+        return (new DataJsonResponse())->setMessageAndTranslate('changesSaved')->setCallBackFunction($this->callBackFunction)->addRefreshTargetId($this->refreshActionIds);
+    }
+
+}

+ 35 - 0
app/UI/Disk/Buttons/CreateButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Modals\CreateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+
+class CreateButton extends ButtonCreate implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createDiskButton');
+        $this->initLoadModalAction(new CreateModal());
+    }
+
+}

+ 37 - 0
app/UI/Disk/Buttons/DeleteButton.php

@@ -0,0 +1,37 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class DeleteButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteDiskButton');
+        $this->setDisableByColumnValue("master", true);
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteModal());
+    }
+
+}

+ 35 - 0
app/UI/Disk/Buttons/UpdateButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Modals\UpdateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class UpdateButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateDiskButton');
+        $this->initLoadModalAction(new UpdateModal());
+    }
+
+}

+ 84 - 0
app/UI/Disk/Forms/CreateForm.php

@@ -0,0 +1,84 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Providers\DiskProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+
+class CreateForm extends BaseForm implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('createDiskForm');
+        $this->setFormType('create');
+        $this->setProvider(new DiskProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+
+    private function initFields()
+    {
+        //size
+        $field = new Text('size');
+        $resourceManager = new ResourceManager();
+        $field->addValidator(new NumberValidator($resourceManager->disk()->getMin(),$resourceManager->disk()->free(), true));
+        $field->setDefaultValue($this->configuration()->serverDiskSize->min);
+        $this->addField($field);
+        //bus
+        $field = new Select('bus');
+        $options=[];
+        foreach( $this->configuration()->getAdditionalDiskType() as $entery){
+            $options[$entery] = sl("lang")->abtr($entery);
+        }
+        $field->setAvailableValues($options);
+        $this->addField($field);
+        //format
+        $field = new Select('format');
+        $options=[];
+        foreach( $this->configuration()->getAdditionalDiskFormat() as $entery){
+            $options[$entery] = sl("lang")->abtr($entery);
+        }
+        $field->setAvailableValues($options);
+        $this->addField($field);
+        //backup
+        if ($this->configuration()->isPermissionAdditionalDiskBackup())
+        {
+            $field = new Switcher('backup');
+            $this->addField($field);
+        }
+
+    }
+}

+ 51 - 0
app/UI/Disk/Forms/DeleteForm.php

@@ -0,0 +1,51 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Providers\DiskProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Providers\FirewallOptionProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class DeleteForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteDiskForm');
+        $this->setFormType('delete');
+        $this->setProvider(new DiskProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDelete');
+        $this->addField(new Hidden("id"));
+    }
+
+}

+ 71 - 0
app/UI/Disk/Forms/UpdateForm.php

@@ -0,0 +1,71 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Providers\DiskProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Validators\DiskSizeValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+
+class UpdateForm extends BaseForm implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('updateDiskForm');
+        $this->setFormType('update');
+        $this->setProvider(new DiskProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['update'];
+    }
+
+    private function initFields()
+    {
+        //entity id
+        $this->addField(new Hidden("id"));
+        //size
+        $field = new Text('size');
+        $resourceManager = new ResourceManager();
+        /**
+         * @todo $resourceManager->disk()->free() + current disk size
+         */
+        $field->addValidator(new DiskSizeValidator());
+        $this->addField($field);
+        //backup
+        if ($this->configuration()->isPermissionAdditionalDiskBackup())
+        {
+            $field = new Switcher('backup');
+            $this->addField($field);
+        }
+    }
+}

+ 35 - 0
app/UI/Disk/Modals/CreateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Forms\CreateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class CreateModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createDiskModal');
+        $this->addForm(new CreateForm());
+    }
+
+}

+ 35 - 0
app/UI/Disk/Modals/DeleteModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteDiskModal');
+        $this->addForm(new DeleteForm());
+    }
+
+}

+ 35 - 0
app/UI/Disk/Modals/UpdateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Forms\UpdateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class UpdateModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateDiskModal');
+        $this->addForm(new UpdateForm());
+    }
+
+}

+ 145 - 0
app/UI/Disk/Pages/DiskDataTable.php

@@ -0,0 +1,145 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Libs\Format;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Buttons\BackupSwitchButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Buttons\CreateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Buttons\RestoreButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Buttons\UpdateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class DiskDataTable extends DataTable implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+    protected $id = 'diskDataTable';
+    protected $name = 'diskDataTable';
+    protected $title = 'diskDataTableTitle';
+
+    public function initContent()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $resourceManager = new ResourceManager();
+        if(!preg_match('/disk/', $vm->config()['hotplug'])){
+            $this->setInternalAlertMessage("Adding, editing or removing disk will reboot the virtual machine.");
+        }
+        //Create
+        $createButton = new CreateButton();
+        $createButton->addClass("pmCreateDiskButton");
+        if (!$resourceManager->disk()->hasFreeTotal())
+        {
+            $createButton->addClass("hidden");
+        }
+
+        $this->unsetShowTitle();
+
+        $this->addButton($createButton);
+        //Update
+        $this->addActionButton(new UpdateButton());
+        //Delete
+        $this->addActionButton(new DeleteButton());
+    }
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('name'))->setSearchable(true, "string")->setOrderable('ASC'))
+            ->addColumn((new Column('bus'))->setSearchable(true, "string")->setOrderable())
+            ->addColumn((new Column('format'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('backup'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('bytes'))->setSearchable(true)->setOrderable());
+    }
+
+    public function replaceFieldName($key, $row)
+    {
+        $id = preg_replace('/[^0-9]/', '', $row[$key]);
+        $id++;
+        sl("lang")->addReplacementConstant("id",$id);
+        return sl("lang")->abtr('Disk :id:');
+    }
+
+    public function replaceFieldBus($key, $row)
+    {
+        return sl("lang")->tr($row[$key]);
+    }
+
+    public function replaceFieldFormat($key, $row)
+    {
+        if ($row[$key])
+        {
+            return $row[$key];
+        }
+        return "raw";
+    }
+
+    public function replaceFieldBytes($key, $row)
+    {
+        return Format::convertBytes($row['bytes']);
+    }
+
+    public function replaceFieldCompress($key, $row)
+    {
+        return sl('lang')->tr($row['compress']);
+    }
+
+    public function customColumnHtmlBackup()
+    {
+        return (new BackupSwitchButton())->getHtml();
+    }
+
+    public function replaceFieldBackup($key, $row)
+    {
+        return $row['backup'] == "0" ? "off" : "on";
+    }
+
+    protected function loadData()
+    {
+        $data = [];
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        foreach ( $vm->getHardDisks() as $entity)
+        {
+            $data[] = [
+                "id"     => $entity->getId(),
+                "bus"    => $entity->getId(),
+                "name"   => $entity->getName(),
+                "format" => $entity->getFormat(),
+                "backup" => $entity->getBackup(),
+                "size"   => $entity->getSize(),
+                "bytes"  => $entity->getBytes(),
+                "master" => $entity->isMaster(),
+            ];
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setDefaultSorting("name", 'ASC');
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+
+}

+ 181 - 0
app/UI/Disk/Providers/DiskProvider.php

@@ -0,0 +1,181 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Providers;
+
+use MGProvision\Proxmox\v2\models\HardDisk;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\RebootVmJob;
+use ModulesGarden\ProxmoxAddon\App\Models\Job;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
+
+
+class DiskProvider extends BaseDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function read()
+    {
+        if ($this->actionElementId && $this->actionElementId != "diskDataTable")
+        {
+            $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+            $disk = $vm->findHardDiskById($this->actionElementId);
+            $this->data       = $disk->getAttributes();
+            $this->data['id'] = $this->actionElementId;
+            //backup
+            $backup               = $this->data['backup'];
+            $this->data['backup'] = $backup == "0" ? "off" : "on";
+            //size
+            $this->data['size'] = $disk->getGb();
+        }
+    }
+
+    public function create()
+    {
+        $storage = $this->configuration()->getAdditionalDiskStorage();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vmModel  = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
+        $ide     = $vm->findFreeIde($this->formData['bus']);
+        $id      = $this->formData['bus'] . $ide;
+        $hdd     = new HardDisk($id);
+        $hdd->setApi($this->api());
+        $hdd->setPath($vm->getPath() . "/config");
+        $hdd->setStorage($storage)
+            ->setSize($this->formData['size'])
+            ->setMedia("disk")
+            ->setFormat($this->formData['format'])
+            ->setBackup($this->configuration()->isPermissionAdditionalDiskBackup() && $this->formData['backup'] == "on" ? null : 0);
+        //disk speed
+        $hdd->setMbps_rd($this->configuration()->getAdditionalDiskMbpsRd())
+            ->setMbps_wr($this->configuration()->getAdditionalDiskMbpsWr());
+        //IOPS
+        $hdd->setIops_rd($this->configuration()->getAdditionalDiskIopsRd())
+            ->setIops_rd_max($this->configuration()->getAdditionalDiskIopsRdMax())
+            ->setIops_wr($this->configuration()->getAdditionalDiskIopsWr())
+            ->setIops_wr_max($this->configuration()->getAdditionalDiskIopsWrMax());
+        //cach
+        $hdd->setCache($this->configuration()->getAdditionalDiskCache());
+        //replicate
+        if ($this->configuration()->isAdditionalDiskReplicate())
+        {
+            $hdd->setReplicate(0);
+        }
+        //discard
+        if ($this->configuration()->isAdditionalDiskDiscard())
+        {
+            $hdd->setDiscard('on');
+        }
+        //iothread for VirtlO & SCSI 'VIRTIO', 'SCSI'
+        if ($this->configuration()->isAdditionalDiskIoThread() && in_array($this->formData['bus'], ['virtio', 'scsi']))
+        {
+            $hdd->setIothread(1);
+        }
+        $vmModel->disks += $this->formData['size'];
+        $hdd->create();
+        $vmModel->save();
+        $resourceManager = new ResourceManager();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The hard disk has been created successfully')
+            ->addData('createButtonStatus', $resourceManager->disk()->hasFreeTotal())
+            ->setCallBackFunction('pmToggleDiskButton');
+    }
+
+    public function update()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vmModel  = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
+        $vmId = $vmModel->id;
+        $hdd = $vm->findHardDiskById($this->formData['id']);
+        if ((int)$hdd->getGb() > (int)$this->formData['size'])
+        {
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('Downgrading the disk size is restricted');
+        }
+        //resize
+        if ((int)$hdd->getGb() < (int)$this->formData['size'])
+        {
+            $size = "+" . abs((int)$this->formData['size'] - (int)$hdd->getGb()) . "G";
+            $hdd->resize($size);
+        }
+        if($hdd->isMaster()){
+            $vm->config(true);
+            $vmModel->disk =  $vm->getMasterHddSize();
+        }else{
+            $vmModel->disks = $vm->getHardDiskRepostiory()->additionalSize();
+        }
+        $vmModel->save();
+        //backup
+        $backup = $this->formData['backup'] == "on" ? null : 0;
+        $hdd->setBackup($backup)->update();
+        if ($vm->isRunning() &&
+            !Job::waiting()->ofJob(RebootVmJob::class)->ofHostingId($this->getWhmcsParamByKey("serviceid"))->ofCustomId($vmId)->count())
+        {
+            queue(RebootVmJob::class, [], null, "hosting", $this->getWhmcsParamByKey("serviceid"),$vmId);
+        }
+        $resourceManager = new ResourceManager();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The hard disk has been updated successfully')
+            ->addData('createButtonStatus',$resourceManager->disk()->hasFreeTotal())
+            ->setCallBackFunction('pmToggleDiskButton');
+    }
+
+    public function delete()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vmModel  = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
+        $hdd = $vm->findHardDiskById($this->formData['id']);
+        if($hdd->isMaster()){
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('The master hard disk cannot be deleted');
+        }
+        $hdd->delete();
+
+        unset($this->vm);
+        foreach($vm->getHardDisks() as $hd){
+            if($hd->isMaster()){
+                continue;
+            }
+            if(preg_match('/unused/', $hd->getId())){
+                $hd->delete();
+                break;
+            }
+        }
+
+        $vmModel->disks = $vm->getHardDiskRepostiory()->additionalSize();
+        $vmModel->save();
+        $resourceManager = new ResourceManager();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The hard disk has been deleted successfully')
+            ->addData('createButtonStatus', $resourceManager->disk()->hasFreeTotal())
+            ->setCallBackFunction('pmToggleDiskButton');
+    }
+
+
+}

+ 84 - 0
app/UI/Disk/Validators/DiskSizeValidator.php

@@ -0,0 +1,84 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Validators;
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+class DiskSizeValidator extends BaseValidator
+{
+    protected $minValue = 0;
+    protected $maxValue = 0;
+    protected $required = true;
+
+    public function __construct( $required = true)
+    {
+        $this->required = $required;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        $resurceManager = new ResourceManager();
+        $diskId = $additionalData->get('formData')['id'];
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $hdd = $vm->getHardDiskRepostiory()->findById($diskId);
+        $size = $hdd->getGb();
+        $diskResource =    $resurceManager ->disk();
+        $diskResource->setUsed($diskResource->getUsed() - $size);
+        $this->maxValue = $diskResource->free();
+        $this->minValue =  $diskResource->getMin();
+        if(!$hdd->isMaster()){
+            $this->minValue =  $size;
+        }
+        if(preg_match("/\./", $data)){
+            $this->addValidationError('PleaseProvideANumericValueBetween', false, ['minValue' => $this->minValue, 'maxValue' => $this->maxValue]);
+            return false;
+        }
+        if (is_numeric($data) && $this->minValue === 0 && $this->maxValue === 0)
+        {
+            return true;
+        }
+        //Min & Max
+        if (is_numeric($data) && $this->minValue <= ((int)$data) && ((int)$data) <= $this->maxValue)
+        {
+            return true;
+        }
+        //Min
+        else
+        {
+            if (is_numeric($data) && !is_numeric($this->maxValue) && $this->minValue <= ((int)$data))
+            {
+                return true;
+            }
+        }
+
+        if ($this->minValue === $this->maxValue)
+        {
+            $this->addValidationError('PleaseProvideANumericValue');
+
+            return false;
+        }
+
+        if (is_numeric($this->minValue) && is_numeric($this->maxValue))
+        {
+            $this->addValidationError('PleaseProvideANumericValueBetween', false, ['minValue' => $this->minValue, 'maxValue' => $this->maxValue]);
+        }
+        else
+        {
+            if (is_numeric($this->minValue) && !is_numeric($this->maxValue))
+            {
+                $this->addValidationError('PleaseProvideANumericValueFrom', false, ['minValue' => $this->minValue]);
+            }
+        }
+
+
+        return false;
+    }
+
+}

+ 36 - 0
app/UI/Firewall/Buttons/CreateGroupButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals\CreateGroupModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem;
+
+
+class CreateGroupButton extends ButtonDropdownItem  implements ClientArea
+{
+    protected $icon  = 'lu-dropdown__link-icon lu-zmdi  lu-zmdi-shield-security';
+
+    public function initContent()
+    {
+        $this->initIds('createGroupButton');
+        $this->initLoadModalAction(new CreateGroupModal());
+    }
+}

+ 33 - 0
app/UI/Firewall/Buttons/CreateRuleButton.php

@@ -0,0 +1,33 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals\CreateRuleModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+
+class CreateRuleButton extends ButtonCreate implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('createRuleButton');
+        $this->initLoadModalAction(new CreateRuleModal());
+    }
+}

+ 36 - 0
app/UI/Firewall/Buttons/DeleteButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class DeleteButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteButton');
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteModal());
+    }
+
+}

+ 59 - 0
app/UI/Firewall/Buttons/EnableSwitchButton.php

@@ -0,0 +1,59 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons;
+
+
+use MGProvision\Proxmox\v2\models\FirewallRule;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\DataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonSwitchAjax;
+
+class EnableSwitchButton extends ButtonSwitchAjax implements ClientArea
+{
+
+    use ProductService;
+    use ApiService;
+    protected $switchColumn = 'enable';
+    protected $id ='enableSwitchButton';
+    protected $name='enableSwitchButton';
+    protected $refreshActionIds = 'enableSwitchDataTable';
+
+    public function returnAjaxData()
+    {
+        try
+        {
+            $data         = json_decode(base64_decode($this->getRequestValue('actionElementId')), true);
+            $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+            $firewallRule = new FirewallRule();
+            $firewallRule->setApi($this->api());
+            $pos = $data['pos'];
+            $firewallRule->setPath($vm->getPath() . "/firewall/rules/{$pos}");
+            $firewallRule->setEnable($this->getRequestValue("value") == "on" ? 1 : 0);
+            $firewallRule->update();
+        }
+        catch (\Exception $exc)
+        {
+            return (new DataJsonResponse())->setStatusError()->setMessage($exc->getMessage())->setCallBackFunction($this->callBackFunction)->addRefreshTargetId($this->refreshActionIds);
+        }
+        return (new DataJsonResponse())->setMessageAndTranslate('changesSaved')->setCallBackFunction($this->callBackFunction)->addRefreshTargetId($this->refreshActionIds);
+    }
+}

+ 54 - 0
app/UI/Firewall/Buttons/UpdateRuleButton.php

@@ -0,0 +1,54 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals\UpdateGroupModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals\UpdateRuleModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class UpdateRuleButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateButton');
+
+        if ($this->isUpdateGroup())
+        {
+            $this->initLoadModalAction(new UpdateGroupModal());
+            return;
+        }
+        $this->initLoadModalAction(new UpdateRuleModal());
+    }
+
+    private function isUpdateGroup()
+    {
+        $this->loadRequestObj();
+        $this->request->get('ajax') && $this->request->get('actionElementId');
+        if ($this->request->get('ajax') && $this->request->get('actionElementId'))
+        {
+            $this->data = json_decode(base64_decode($this->request->get('actionElementId')), true);
+            return $this->data['type'] == "group";
+        }
+        return false;
+    }
+
+}

+ 44 - 0
app/UI/Firewall/Forms/CreateGroupForm.php

@@ -0,0 +1,44 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Providers\FirewallProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class CreateGroupForm extends GroupForm implements ClientArea
+{
+    use ApiService;
+
+    public function initContent()
+    {
+        $this->initIds('createGroupForm');
+        $this->setFormType('create');
+        $this->setProvider(new FirewallProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+
+}

+ 42 - 0
app/UI/Firewall/Forms/CreateRuleForm.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Providers\FirewallProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class CreateRuleForm extends RuleForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('createRuleForm');
+        $this->setFormType('create');
+        $this->setProvider(new FirewallProvider());
+        $this->addClass('lu-row');
+        $this->initSections();
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+}

+ 50 - 0
app/UI/Firewall/Forms/DeleteForm.php

@@ -0,0 +1,50 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Providers\FirewallProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class DeleteForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteRuleForm');
+        $this->setFormType('delete');
+        $this->setProvider(new FirewallProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDelete');
+        $this->addField(new Hidden("pos"));
+    }
+
+}

+ 86 - 0
app/UI/Firewall/Forms/GroupForm.php

@@ -0,0 +1,86 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class GroupForm extends BaseForm implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+
+
+    protected function initFields()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        //enable
+        $field = new Switcher('enable');
+        $this->addField($field);
+        //pos
+        if ($this->getFormType() == "update")
+        {
+            $this->addField(new Hidden("pos"));
+        }
+        //action
+        $field   = new Select('action');
+        $options = [];
+        foreach ($this->api()->get("/cluster/firewall/groups", []) as $response)
+        {
+            $options[$response['group']] = sl("lang")->tr($response['group']);
+        }
+        $field->setAvailableValues($options);
+        $this->addField($field);
+        //iface
+        $field      = new Select('iface');
+        $ifaces     = [];
+        /**
+         * @deprecated
+        $interfaces = $this->configuration()->getFirewallInterfaces();
+        if (in_array("venet", $interfaces))
+        {
+            $ifaces["venet"] = sl('lang')->tr("venet");
+        }
+        if (in_array("eth", $interfaces))
+        {
+        }
+         */
+        foreach ($vm->getNetworkDevices() as $nd)
+        {
+            $ifaces[$nd->getId()] = $nd->getId();
+        }
+
+        $field->setAvailableValues($ifaces);
+        $this->addField($field);
+        //comment
+        $field = new Text('comment');
+        $this->addField($field);
+        //type
+        $this->addField((new Hidden("type"))->setDefaultValue('group'));
+    }
+
+}

+ 206 - 0
app/UI/Firewall/Forms/RuleForm.php

@@ -0,0 +1,206 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\PortValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\FileReader\Reader\Json;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ModuleConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\BaseField;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\RawSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+
+class RuleForm extends BaseForm implements ClientArea
+{
+    use  ApiService;
+    use ProductService;
+    private $mainSection;
+    private $topSection;
+    private $leftSection;
+    private $rightSection;
+    private $bottomSection;
+    private $sectionFields=[];
+
+    protected function initSections()
+    {
+        //Main
+        $this->mainSection = new RawSection('mainSection');
+        $this->mainSection->setMainContainer($this->mainContainer);
+        //Left
+        $this->leftSection = new HalfPageSection('leftSection');
+        $this->leftSection->setMainContainer($this->mainContainer);
+        //Right
+        $this->rightSection = new HalfPageSection('rightSection');
+        $this->rightSection->setMainContainer($this->mainContainer);
+        //Add Top
+        $this->topSection = new RawSection('topSection');
+        $this->topSection->setMainContainer($this->mainContainer);
+        //add main
+        $this->mainSection->addSection( $this->topSection )->addSection($this->leftSection)->addSection($this->rightSection);
+        $this->addSection($this->mainSection);
+        //Bottom
+        $this->bottomSection = new RawSection('bottomSection');
+        $this->bottomSection->setMainContainer($this->mainContainer);
+        $this->addSection($this->bottomSection);
+    }
+
+    protected function initFields()
+    {
+        /*Left*/
+        //enable
+        $field = new Switcher('enable');
+        $this->topSection->addField($field);
+        //type
+        $this->addFieldType();
+        //action
+        $this->addFieldAction();
+        //iface
+        $this->addFieldIface();
+        //source
+        $field = new Text('source');
+        $this->addSectionField($field);
+        //dest
+        $field = new Text('dest');
+        $this->addSectionField($field);
+        /*Right*/
+        //macro
+        $this->addFieldMacro();
+        //proto
+        $this->addFieldProto();
+        //sport
+        $field = new Text('sport');
+        $field->addValidator(new PortValidator());
+        $this->addSectionField($field);
+        //dport
+        $field = new Text('dport');
+        $field->addValidator(new PortValidator());
+        $this->addSectionField($field);
+        //comment
+        $field = new Text('comment');
+        $this->bottomSection->addField($field);
+        $this->addFieldsToSections();
+    }
+
+    protected function addFieldPos()
+    {
+        $field = new Hidden('pos');
+        $this->bottomSection->addField($field);
+    }
+
+    private function addFieldType()
+    {
+        $field = new Select('type');
+        $field->setAvailableValues([
+            "in"  => sl('lang')->tr("in"),
+            "out" => sl('lang')->tr("out")
+        ]);
+        $this->addSectionField($field);
+    }
+
+    private function addFieldAction()
+    {
+        $field    = new Select('action');
+        $entries = new Json('actions.json', ModuleConstants::getFullPath('storage', 'app', "firewall"));
+        $options  = [];
+        foreach ($entries->get() as $key => $v)
+        {
+            $options[$key] = sl('lang')->tr($v);
+        }
+        $field->setAvailableValues($options);
+        $this->addSectionField($field);
+    }
+
+    private function addFieldIface()
+    {
+        $field      = new Select('iface');
+        $ifaces     = [];
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        /**
+         * @deprecated
+        $interfaces = $this->configuration()->getFirewallInterfaces();
+        if (in_array("venet", $interfaces))
+        {
+            $ifaces["venet"] = sl('lang')->tr("venet");
+        }
+        if (in_array("eth", $interfaces))
+        {
+        }
+         */
+        foreach ($vm->getNetworkDevices() as $nd)
+        {
+            $ifaces[$nd->getId()] = $nd->getId();
+        }
+        $field->setAvailableValues($ifaces);
+        $this->addSectionField($field);
+    }
+
+    private function addFieldMacro()
+    {
+        $field  = new Select('macro');
+        $macros = ["0" => sl("lang")->tr("None")];
+        foreach ($this->api()->get("/cluster/firewall/macros", []) as $response)
+        {
+            $macros[$response['macro']] = sl("lang")->tr($response['descr']);
+        }
+        $field->setAvailableValues($macros);
+        $this->addSectionField($field);
+    }
+
+    private function addFieldProto()
+    {
+        $field    = new Select('proto');
+        $entries = new Json('protocols.json', ModuleConstants::getFullPath('storage', 'app', "firewall"));
+        $options  = [];
+        foreach ($entries->get() as $key => $v)
+        {
+            $options[$key] = sl('lang')->tr($v);
+        }
+        $field->setAvailableValues($options);
+        $this->addSectionField($field);
+    }
+
+    public function addSectionField(BaseField $field)
+    {
+        $this->sectionFields[] = $field;
+        return $this;
+    }
+
+    private function addFieldsToSections(){
+        foreach($this->sectionFields as $k => $field){
+            if($k % 2 == 0 ){
+                $this->leftSection->addField($field);
+            }else{
+                $this->rightSection->addField($field);
+            }
+        }
+        unset($this->sectionFields);
+    }
+
+
+}

+ 45 - 0
app/UI/Firewall/Forms/UpdateGroupForm.php

@@ -0,0 +1,45 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Providers\FirewallProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class UpdateGroupForm extends GroupForm implements ClientArea
+{
+    use ApiService;
+
+    public function initContent()
+    {
+        $this->initIds('createGroupForm');
+        $this->setFormType('update');
+        $this->setProvider(new FirewallProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['update'];
+    }
+
+
+}

+ 44 - 0
app/UI/Firewall/Forms/UpdateRuleForm.php

@@ -0,0 +1,44 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Providers\FirewallProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+
+class UpdateRuleForm extends RuleForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('updateForm');
+        $this->setFormType('update');
+        $this->setProvider(new FirewallProvider());
+        $this->addClass('lu-row');
+        $this->initSections();
+        $this->addFieldPos();
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['update'];
+    }
+}

+ 35 - 0
app/UI/Firewall/Modals/CreateGroupModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms\CreateGroupForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class CreateGroupModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createGroupModal');
+        $this->addForm(new CreateGroupForm());
+    }
+
+}

+ 35 - 0
app/UI/Firewall/Modals/CreateRuleModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms\CreateRuleForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class CreateRuleModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createRuleModal');
+        $this->addForm(new CreateRuleForm());
+    }
+
+}

+ 35 - 0
app/UI/Firewall/Modals/DeleteModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteRuleModal');
+        $this->addForm(new DeleteForm());
+    }
+
+}

+ 35 - 0
app/UI/Firewall/Modals/UpdateGroupModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms\UpdateGroupForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class UpdateGroupModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateGroupModal');
+        $this->addForm(new UpdateGroupForm());
+    }
+
+}

+ 35 - 0
app/UI/Firewall/Modals/UpdateRuleModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms\UpdateRuleForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class UpdateRuleModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateModal');
+        $this->addForm(new UpdateRuleForm());
+    }
+
+}

+ 178 - 0
app/UI/Firewall/Pages/FirewallDataTable.php

@@ -0,0 +1,178 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Pages;
+
+use MGProvision\Proxmox\v2\repository\FirewallRulesRepository;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\CreateGroupButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\CreateRuleButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\EnableSwitchButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\RestoreButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\UpdateRuleButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+
+class FirewallDataTable extends DataTable implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+    protected $id = 'firewallDataTable';
+    protected $name = 'firewallDataTable';
+    protected $title = 'firewallDataTableTitle';
+
+    public function initContent()
+    {
+        $this->unsetShowTitle();
+        //Create Rule
+        $createRule = new CreateRuleButton();
+        //Create Group
+        $createGroup = new CreateGroupButton();
+        $createRule->addClass("pmCreateFirewallButton");
+        $createGroup->addClass("pmCreateFirewallButton");
+        if (!$this->resourceGuard()->hasfirewallLimit())
+        {
+            $createRule->addClass("hidden");
+            $createGroup->addClass("hidden");
+        }
+        $this->addButton($createRule);
+        $this->addButton($createGroup);
+        //Update
+        $this->addActionButton(new UpdateRuleButton());
+        //Delete
+        $this->addActionButton(new DeleteButton());
+    }
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('enable')))
+            ->addColumn((new Column('type'))->setSearchable(true, "string")->setOrderable())
+            ->addColumn((new Column('action'))->setSearchable(true, "string")->setOrderable())
+            ->addColumn((new Column('iface'))->setSearchable(true, "string")->setOrderable())
+            ->addColumn((new Column('comment'))->setSearchable(true, "string")->setOrderable());
+    }
+
+    public function customColumnHtmlEnable()
+    {
+        return (new EnableSwitchButton())->getHtml();
+    }
+
+    public function replaceFieldEnable($key, $row)
+    {
+        return $row[$key] == "1" ? "on" : "off";
+    }
+
+    public function replaceFieldMacro($key, $row)
+    {
+        if ($row[$key])
+        {
+            return $row[$key];
+        }
+        return '-';
+    }
+
+    public function replaceFieldIface($key, $row)
+    {
+        if ($row[$key])
+        {
+            return $row[$key];
+        }
+        return '-';
+    }
+
+    public function replaceFieldSource($key, $row)
+    {
+        if ($row[$key])
+        {
+            return $row[$key];
+        }
+        return '-';
+    }
+
+    public function replaceFieldDest($key, $row)
+    {
+        if ($row[$key])
+        {
+            return $row[$key];
+        }
+        return '-';
+    }
+
+    public function replaceFieldProto($key, $row)
+    {
+        if ($row[$key])
+        {
+            return $row[$key];
+        }
+        return '-';
+    }
+
+    public function replaceFieldDport($key, $row)
+    {
+        if ($row[$key])
+        {
+            return $row[$key];
+        }
+        return '-';
+    }
+
+    public function replaceFieldSport($key, $row)
+    {
+        if ($row[$key])
+        {
+            return $row[$key];
+        }
+        return '-';
+    }
+
+    public function replaceFieldComment($key, $row)
+    {
+        if ($row[$key])
+        {
+            return $row[$key];
+        }
+        return '-';
+    }
+
+    protected function loadData()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $repository = new FirewallRulesRepository();
+        $repository->setApi($this->api());
+        $repository->findByVm($vm);
+        $data = [];
+        foreach ($repository->fetch() as $entity)
+        {
+            $row    = $entity->toArray();
+            $data[] = array_merge(['id' => base64_encode(json_encode($row))], $row);
+        }
+        $this->setCallBackFunction('pmToggleDropDownButtons');
+
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+
+}

+ 108 - 0
app/UI/Firewall/Providers/FirewallProvider.php

@@ -0,0 +1,108 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Providers;
+
+use MGProvision\Proxmox\v2\models\FirewallRule;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+
+class FirewallProvider extends BaseDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function read()
+    {
+        if ($this->actionElementId)
+        {
+            $this->data = json_decode(base64_decode($this->actionElementId), true);
+            //enable
+            $enable               = $this->data['enable'];
+            $this->data['enable'] = $enable == "1" ? "on" : "off";
+        }
+    }
+
+    public function create()
+    {
+        $this->acl()->firewall();
+        $this->resourceGuard()->firewallLimit();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $firewallRule = new FirewallRule();
+        $firewallRule->setApi($this->api());
+        $firewallRule->setPath($vm->getPath() . "/firewall/rules/");
+        $attributes           = $this->formData;
+        $attributes['enable'] = $this->formData['enable'] == "on" ? 1 : 0;
+        if ($attributes['proto'] == "0")
+        {
+            unset($attributes['proto']);
+        }
+        $firewallRule->setAttributes($attributes);
+        $firewallRule->create();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The firewall rule has been created successfully')
+            ->addData('createButtonStatus', $this->resourceGuard()->hasfirewallLimit())
+            ->setCallBackFunction('pmToggleFirewallButton');
+    }
+
+    public function update()
+    {
+        $this->acl()->firewall();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $firewallRule = new FirewallRule();
+        $firewallRule->setApi($this->api());
+        $pos = $this->formData['pos'];
+        unset($this->formData['pos']);
+        $firewallRule->setPath($vm->getPath() . "/firewall/rules/{$pos}");
+        $attributes           = $this->formData;
+        $attributes['enable'] = $this->formData['enable'] == "on" ? 1 : 0;
+        if ($attributes['proto'] == "0")
+        {
+            unset($attributes['proto']);
+        }
+        $firewallRule->setAttributes($attributes);
+        $firewallRule->update();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The firewall rule has been updated successfully');
+    }
+
+    public function delete()
+    {
+        $this->acl()->firewall();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $firewallRule = new FirewallRule();
+        $firewallRule->setApi($this->api());
+        $pos = $this->formData['pos'];
+        $firewallRule->setPath($vm->getPath() . "/firewall/rules/{$pos}");
+        $firewallRule->delete();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The firewall rule has been deleted successfully')
+            ->addData('createButtonStatus', $this->resourceGuard()->hasfirewallLimit())
+            ->setCallBackFunction('pmToggleFirewallButton');
+    }
+
+
+}

+ 38 - 0
app/UI/FirewallOption/Buttons/UpdateButton.php

@@ -0,0 +1,38 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\FirewallOption\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\FirewallOption\Modals\UpdateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+
+class UpdateButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    protected $icon = 'lu-zmdi lu-zmdi-edit';
+
+    public function initContent()
+    {
+        $this->initIds('updateFirewallButton');
+        $this->initLoadModalAction(new UpdateModal());
+    }
+
+}

+ 121 - 0
app/UI/FirewallOption/Forms/UpdateForm.php

@@ -0,0 +1,121 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\FirewallOption\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\FirewallOption\Providers\FirewallOptionProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+
+class UpdateForm extends BaseForm implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('updateForm');
+        $this->setFormType('update');
+        $this->setProvider(new FirewallOptionProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['update'];
+    }
+
+    private function initFields()
+    {
+        //logLevel
+        $logLevels = [
+            "nolog"   => sl("lang")->tr("nolog"),
+            "info"    => sl("lang")->tr("info"),
+            "err"     => sl("lang")->tr("err"),
+            "warning" => sl("lang")->tr("warning"),
+            "crit"    => sl("lang")->tr("crit"),
+            "alert"   => sl("lang")->tr("alert"),
+            "emerg"   => sl("lang")->tr("emerg"),
+            "debug"   => sl("lang")->tr("debug"),
+        ];
+        //enable
+        if($this->acl()->hasFirewallOption("enable")){
+            $field = new Switcher("enable");
+            $this->addField($field);
+        }
+        //dhcp
+        if($this->acl()->hasFirewallOption("dhcp")){
+            $field = new Switcher("dhcp");
+            $this->addField($field);
+        }
+        //ndp
+        if($this->acl()->hasFirewallOption("ndp")){
+            $field = new Switcher("ndp");
+            $field->setDefaultValue("on");
+            $this->addField($field);
+        }
+        //radv
+        if($this->acl()->hasFirewallOption("radv")){
+            $field = new Switcher("radv");
+            $this->addField($field);
+        }
+        //macfilter
+        if($this->acl()->hasFirewallOption("macfilter")){
+            $field = new Switcher("macfilter");
+            $field->setDefaultValue("on");
+            $this->addField($field);
+        }
+        //ipfilter
+        if($this->acl()->hasFirewallOption("ipfilter")){
+            $field = new Switcher("ipfilter");
+            $this->addField($field);
+        }
+        //log_level_in
+        $field = new Select('log_level_in');
+        $field->setAvailableValues($logLevels);
+        $this->addField($field);
+        //log_level_out
+        $field = new Select('log_level_out');
+        $field->setAvailableValues($logLevels);
+        $this->addField($field);
+        //policy_in
+        $field = new Select('policy_in');
+        $field->setAvailableValues([
+            "DROP"   => sl("lang")->tr("DROP"),
+            "ACCEPT" => sl("lang")->tr("ACCEPT"),
+            "REJECT" => sl("lang")->tr("REJECT"),
+        ]);
+        $field->setDefaultValue("DROP");
+        $this->addField($field);
+        //policy_out
+        $field = new Select('policy_out');
+        $field->setAvailableValues([
+            "DROP"   => sl("lang")->tr("DROP"),
+            "ACCEPT" => sl("lang")->tr("ACCEPT"),
+            "REJECT" => sl("lang")->tr("REJECT"),
+        ]);
+        $field->setDefaultValue("ACCEPT");
+        $this->addField($field);
+    }
+}

+ 35 - 0
app/UI/FirewallOption/Modals/UpdateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\FirewallOption\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\FirewallOption\Forms\UpdateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class UpdateModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateFirewallOptionModal');
+        $this->addForm(new UpdateForm());
+    }
+
+}

+ 84 - 0
app/UI/FirewallOption/Pages/FirewallOption.php

@@ -0,0 +1,84 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\FirewallOption\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\FirewallOption\Buttons\UpdateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Builder\BaseContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AjaxElementInterface;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\RawDataJsonResponse;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+/**
+ * Class FirewallOption
+ * @package ModulesGarden\Servers\ProxmoxCloudVps\App\UI\FirewallOption\Pages
+ * @todo - move html code to new class - new Label(some text, Label::DANGER)
+ */
+class FirewallOption extends BaseContainer implements ClientArea, AjaxElementInterface
+{
+    use ApiService;
+    use ProductService;
+
+    protected $id = 'firewallOption';
+    protected $name = 'firewallOption';
+    protected $title = 'firewallOptionTitle';
+    protected $vueComponent = true;
+    protected $defaultVueComponentName = 'mg-firewallOption';
+
+    public function initContent()
+    {
+        $this->unsetShowTitle();
+        $this->addButton(new UpdateButton());
+    }
+
+    public function returnAjaxData()
+    {
+        $vars = ['entries' => []];
+        $lang = sl("lang");
+        $allowed = ['log_level_in', 'log_level_out', 'policy_in', 'policy_out'];
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        foreach ($vm->firewallOptions()->read()->toArray() as $key => $value)
+        {
+            if(!in_array($key, $allowed) && !$this->acl()->hasFirewallOption($key)){
+                continue;
+            }
+            if (is_numeric($value) && $value == 1)
+            {
+                $vars['entries'][$lang->tr($key)] = '<span class="lu-label lu-label--success lu-label--status">' . sl('lang')->tr($value) . '</span>';
+            }
+            else
+            {
+                if (is_numeric($value) && $value == 0)
+                {
+                    $vars['entries'][$lang->tr($key)] = '<span class="lu-label lu-label--danger lu-label--status">' . sl('lang')->tr($value) . '</span>';
+                }
+                else
+                {
+                    $vars['entries'][$lang->tr($key)] = $lang->tr($value);
+                }
+            }
+        }
+        return (new RawDataJsonResponse(['data' => $vars]));
+    }
+
+
+}

+ 83 - 0
app/UI/FirewallOption/Providers/FirewallOptionProvider.php

@@ -0,0 +1,83 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\FirewallOption\Providers;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+
+class FirewallOptionProvider extends BaseDataProvider implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+
+    public function read()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $this->data              = $vm->firewallOptions()->read()->getAttributes();
+        $this->data["enable"]    = str_replace(["1", "0"], ["on", "off"], $this->data["enable"]);
+        $this->data["dhcp"]      = str_replace(["1", "0"], ["on", "off"], $this->data["dhcp"]);
+        $this->data["ndp"]       = str_replace(["1", "0"], ["on", "off"], $this->data["ndp"]);
+        $this->data["radv"]      = str_replace(["1", "0"], ["on", "off"], $this->data["radv"]);
+        $this->data["macfilter"] = str_replace(["1", "0"], ["on", "off"], $this->data["macfilter"]);
+        $this->data["ipfilter"]  = str_replace(["1", "0"], ["on", "off"], $this->data["ipfilter"]);
+    }
+
+
+    public function update()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $attributes              = $this->formData;
+        $attributes["enable"]    = str_replace(["on", "off"], ["1", "0"], $attributes["enable"]);
+        if(!$this->acl()->hasFirewallOption("enable")){
+            unset($attributes["enable"] );
+        }
+        $attributes["dhcp"]      = str_replace(["on", "off"], ["1", "0"], $attributes["dhcp"]);
+        if(!$this->acl()->hasFirewallOption("dhcp")){
+            unset($attributes["dhcp"] );
+        }
+        $attributes["ndp"]       = str_replace(["on", "off"], ["1", "0"], $attributes["ndp"]);
+        if(!$this->acl()->hasFirewallOption("ndp")){
+            unset($attributes["ndp"] );
+        }
+        $attributes["radv"]      = str_replace(["on", "off"], ["1", "0"], $attributes["radv"]);
+        if(!$this->acl()->hasFirewallOption("radv")){
+            unset($attributes["radv"] );
+        }
+        $attributes["macfilter"] = str_replace(["on", "off"], ["1", "0"], $attributes["macfilter"]);
+        if(!$this->acl()->hasFirewallOption("macfilter")){
+            unset($attributes["macfilter"] );
+        }
+        $attributes["ipfilter"]  = str_replace(["on", "off"], ["1", "0"], $attributes["ipfilter"]);
+        if(!$this->acl()->hasFirewallOption("ipfilter")){
+            unset($attributes["ipfilter"] );
+        }
+        $vm->firewallOptions()->setAttributes($attributes)->update();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The firewall options has been updated successfully')
+            ->setRefreshTargetIds(["firewallOption"]);
+    }
+
+
+}

+ 5 - 0
app/UI/FirewallOption/Templates/pages/firewallOption.tpl

@@ -0,0 +1,5 @@
+<mg-component-body-{$elementId|strtolower}
+        component_id='{$elementId}'
+        component_namespace='{$namespace}'
+        component_index='{$rawObject->getIndex()}'
+></mg-component-body-{$elementId|strtolower}>

+ 69 - 0
app/UI/FirewallOption/Templates/pages/firewallOption_components.js

@@ -0,0 +1,69 @@
+mgJsComponentHandler.addDefaultComponent('mg-firewallOption', {
+    template: '#t-mg-firewallOption',
+    props: [
+        'component_id',
+        'component_namespace',
+        'component_index'
+    ],
+    data: function () {
+        return {
+            data: {
+                entries: {}
+            },
+            loading_state: false,
+            passwordShow: false,
+            loaded: false,
+        };
+    },
+    mounted: function () {
+        var self = this;
+        
+        if(this.$el.offsetParent === null) {
+            setInterval(function(){
+                if(self.loaded === false && self.$el.offsetParent !== null)
+                {
+                    self.loadAjaxData();
+                    self.$parent.$root.$on('reloadMgData', self.updateMgData);
+                    clearInterval(this);
+                }
+            }, 500);
+        }else{
+            self.$nextTick(function () {
+                self.loadAjaxData();
+            });
+            self.$parent.$root.$on('reloadMgData', self.updateMgData);
+        }
+    },
+    methods: {
+        loadAjaxData: function () {
+            this.loaded = true;
+            var self = this;
+            self.loading_state = true;
+
+            var requestParams = {
+                loadData: self.component_id,
+                namespace: self.component_namespace,
+                index: self.component_index
+            };
+
+            var response = mgPageControler.vueLoader.vloadData(requestParams);
+            return response.done(function (data) {
+                self.data = data.data.rawData.data;
+                self.loading_state = false;
+            }).fail(function () {
+                self.loading_state = false;
+            });
+        },
+        loadModal: function (event, targetId, namespace, index, params, addSpinner) {
+            mgPageControler.vueLoader.loadModal(event, targetId,
+                typeof namespace !== 'undefined' ? namespace : getItemNamespace(targetId),
+                typeof index !== 'undefined' ? index : getItemIndex(targetId), params, addSpinner);
+        },
+        updateMgData: function(toReloadId){
+            if(this.component_id === toReloadId)
+            {
+                this.loadAjaxData();
+            }
+        }
+    }
+});

+ 50 - 0
app/UI/FirewallOption/Templates/pages/firewallOption_components.tpl

@@ -0,0 +1,50 @@
+<script type="text/x-template" id="t-mg-firewallOption-{$elementId|strtolower}"
+        :component_id="component_id"
+        :component_namespace="component_namespace"
+        :component_index="component_index"
+>
+    <div class="lu-row lu-row--eq-height" id="{$rawObject->getId()}" namespace="{$namespace}"
+         index="{$rawObject->getIndex()}" actionid="{$rawObject->getIndex()}">
+        <div class="lu-col-lg-12">
+            <div class="lu-widget">
+                <div class="lu-widget__header" style="border-bottom: none;">
+                    <div class="lu-widget__top lu-top">
+                        {if $rawObject->isShowTitle()}
+                            <div class="lu-top__title">
+                                {$MGLANG->absoluteT($title)}
+                            </div>
+                        {/if}
+
+                        <div class="lu-top__toolbar">
+                            {foreach from=$rawObject->getButtons() key=buttonKey item=buttonValue}
+                                {$buttonValue->getHtml()}
+                            {/foreach}
+                        </div>
+                    </div>
+                </div>
+                <div class="lu-widget__body">
+                    <div class="no-footer">
+                        <div>
+                            <table role="grid" class="lu-table lu-table--mob-collapsible no-footer dtr-column"
+                                   width="100%" v-if="data.entries">
+                                <tbody>
+                                <tr v-for="(value, key) in data.entries">
+                                    <td>{{ key }}</td>
+                                    <td v-html="value"></td>
+                                </tr>
+                                </tbody>
+                            </table>
+                            <div v-else style="padding: 15px; text-align: center; border-top: 1px solid #e9ebf0;">
+                                {$MGLANG->absoluteT('noDataAvalible')}
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="lu-preloader-container lu-preloader-container--full-screen lu-preloader-container--overlay"
+                     v-show="loading_state">
+                    <div class="lu-preloader lu-preloader--sm"></div>
+                </div>
+            </div>
+        </div>
+    </div>
+</script>

+ 40 - 0
app/UI/Graph/Pages/BaseSmallGraph.php

@@ -0,0 +1,40 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Line;
+use Illuminate\Database\Capsule\Manager as DB;
+
+
+class BaseSmallGraph extends Line implements ClientArea, AdminArea
+{
+    protected $tableRowCol = 'lu-col-md-3';
+    protected $graphSettingsEnabled = false;
+    protected $graphHeight = 70;
+    protected $graphWidth = 200;
+    protected $showTitle = false;
+    protected $title = '';
+    protected $legend = [
+        'display'  => false,
+        'position' => 'top'
+    ];
+    protected $timeframe = "day";
+    protected $displayScaleLabel = true;
+
+    protected function  rrdDataQuery(){
+        $hi = (int) $this->getWhmcsParamByKey('serviceid');
+        $now = new \DateTime();
+        $now->modify('-1 hours');
+        $since = $now->format("Y-m-d H:i:s");
+        $vmId = (int) \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        //Query
+        return DB::select("SELECT AVG(diskread) AS diskread, AVG(diskwrite) AS diskwrite, AVG(cpu) AS cpu, AVG(maxcpu) AS maxcpu , AVG(mem) AS mem, AVG(maxmem) AS maxmem, AVG(netin) AS netin, AVG(netout) AS netout, `date` FROM (SELECT id, hosting_id, vm_id, (diskread), (diskwrite), (cpu), (maxcpu), (mem), (maxmem), (netin), (netout), DATE_FORMAT(FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(time) / 300) * 300), '%Y-%m-%d %H:%i') as `date` FROM `ProxmoxAddon_RrdData` 
+        WHERE hosting_id = {$hi} AND vm_id ={$vmId} AND `time` >= '{$since}'
+) as x GROUP BY date ORDER BY `date` ASC");
+    }
+
+}

+ 109 - 0
app/UI/Graph/Pages/CpuGraph.php

@@ -0,0 +1,109 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Oct 1, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages;
+
+use ModulesGarden\ProxmoxAddon\Core\Helper\DatabaseCache;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Lang\Lang;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Line;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Models\DataSet;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\di;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class CpuGraph extends Line implements ClientArea, AdminArea
+{
+    use GraphData;
+    protected $graphSettingsEnabled = true;
+    protected $graphSettingsKey = 'cpuGraphSettings';
+    protected $displayScaleLabel = true;
+    protected $id = 'cpuGraph';
+    protected $graphHeight = null;
+    protected $graphWidth = null;
+
+    public function initContent()
+    {
+        $this->unsetShowTitle();
+
+        $this->initIds('cpuGraph');
+        $this->setRawTitle( di('lang')->translate('cpuGraph'));
+        //$this->unsetShowTitle();
+        $selectScope = new Select('timeframe');
+        $selectScope->setAvailableValues($this->chartOptions());
+        $selectScope->setDefaultValue('week');
+        $this->addSettingField($selectScope);
+        //yAxes
+        $this->updateChartScale('yAxes', [
+            [
+                'scaleLabel' => [
+                    'display'     => $this->displayScaleLabel,
+                    'labelString' => sl('lang')->tr("CPU Usage")
+                ],
+                'ticks'      => [
+                    'beginAtZero' => true,
+                    'fontSize' => 10
+                ],
+            ]]);
+        //Tooltip
+        $this->updateChartOption('tooltips', [
+            'callbacks' => [
+                'label' => 'mgTooltipCpu'
+            ]
+        ]);
+    }
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        if ($this->configChartsSettings->timeframe)
+        {
+            $this->timeframe = $this->configChartsSettings->timeframe;
+        }
+        $rrdata     = DatabaseCache::loadData(
+            $this->graphSettingsKey.$this->timeframe .$this->getWhmcsParamByKey('serviceid'). '_cacheData', [$this, 'chartData'], 30, true);
+        $labels     = [];
+        $dataSets   = [
+            'cpu'   => []
+        ];
+        $dateFormat = in_array($this->timeframe, ['hour', 'day']) ? "H:i:s" : "Y-m-d";
+        foreach ($this->convertData($rrdata) as $rrd)
+        {
+            $labels[]           = date($dateFormat, $rrd['time']);
+            $dataSets['cpu'][]  = (isset($rrd['cpu']) ? (float)$rrd['cpu'] : 0) * 100;
+        }
+
+        //Labels
+        $this->setLabels($labels);
+        //CPU Usage
+        $lang    = sl('lang');
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('CPU Usage'))
+            ->setData($dataSets['cpu'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => "rgba(174, 198, 57, 0.79)",
+                "borderColor"     => "rgba(174, 198, 57, 1)"
+            ]);
+        $this->addDataSet($dataSet);
+    }
+
+
+}

+ 90 - 0
app/UI/Graph/Pages/CpuSmallGraph.php

@@ -0,0 +1,90 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Oct 1, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages;
+
+use ModulesGarden\ProxmoxAddon\Core\Helper\DatabaseCache;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Models\DataSet;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\di;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class CpuSmallGraph extends  BaseSmallGraph
+{
+    protected $id = 'cpuSmallGraph';
+    protected $name = 'cpuSmallGraph';
+
+    public function initContent()
+    {
+        //yAxes
+        $this->updateChartScale('yAxes', [
+            [
+                'scaleLabel' => [
+                    'display'     => $this->displayScaleLabel,
+                    'labelString' => sl('lang')->tr("CPU %")
+                ],
+                'ticks'      => [
+                    'beginAtZero' => true,
+                    'fontSize' => 10
+                ],
+            ]]);
+        //Tooltip
+        $this->updateChartOption('tooltips', [
+            'callbacks' => [
+                'label' => 'mgTooltipCpu'
+            ]
+        ]);
+        //xAxes
+        $this->updateChartScale('xAxes', [
+            [
+                'display'   => false
+            ]]);
+
+        $this->configChartsSettings->timeframe = 'day';
+    }
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        $labels     = [];
+        $dataSets   = [
+            'cpu'   => []
+        ];
+        foreach ($this->rrdDataQuery() as $rrd)
+        {
+            $labels[]           = $rrd->date;
+            $dataSets['cpu'][]  = (isset($rrd->cpu) ? (float)$rrd->cpu : 0) * 100;
+        }
+        //Labels
+        $this->setLabels($labels);
+        //CPU Usage
+        $lang    = sl('lang');
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('CPU Usage'))
+            ->setData($dataSets['cpu'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => "rgba(174, 198, 57, 0.79)",
+                "borderColor"     => "rgba(174, 198, 57, 1)"
+            ]);
+        $this->addDataSet($dataSet);
+    }
+
+
+}

+ 117 - 0
app/UI/Graph/Pages/DiskGraph.php

@@ -0,0 +1,117 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Oct 1, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages;
+
+use ModulesGarden\ProxmoxAddon\Core\Helper\DatabaseCache;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Line;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Models\DataSet;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\di;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+
+class DiskGraph extends Line implements ClientArea, AdminArea
+{
+    use GraphData;
+    protected $id = 'diskGraph';
+    protected $graphSettingsEnabled = true;
+    protected $graphSettingsKey = 'diskGraphSettings';
+    protected $displayScaleLabel = true;
+    protected $graphHeight = null;
+    protected $graphWidth = null;
+
+    public function initContent()
+    {
+        $this->initIds('diskGraph');
+        $this->setRawTitle( di('lang')->translate('diskGraph'));
+        $selectScope = new Select('timeframe');
+        $selectScope->setAvailableValues($this->chartOptions());
+        $selectScope->setDefaultValue('week');
+        $this->addSettingField($selectScope);
+        $this->updateChartScale('yAxes', [
+            [
+                'scaleLabel' => [
+                    'display'     => $this->displayScaleLabel,
+                    'labelString' => sl('lang')->tr('Bytes/s'),
+                ],
+                'ticks'      => [
+                    'callback' => 'mgBytesToSize',
+                    'beginAtZero' => true,
+                    'fontSize' => 10
+                ],
+            ]]);
+        $this->updateChartOption('tooltips', [
+            'callbacks' => [
+                'label' => 'mgTooltipCallbackForDisk'
+            ]
+        ]);
+
+
+    }
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        if ($this->configChartsSettings->timeframe)
+        {
+            $this->timeframe = $this->configChartsSettings->timeframe;
+        }
+        $rrdata     = DatabaseCache::loadData(
+            $this->graphSettingsKey .$this->timeframe .$this->getWhmcsParamByKey('serviceid'). '_cacheData', [$this, 'chartData'], 30, true);
+        $labels     = [];
+        $dataSets   = [
+            'diskread'  => [],
+            'diskwrite' => [],
+        ];
+        $dateFormat = in_array($this->timeframe, ['hour', 'day']) ? "H:i:s" : "Y-m-d";
+        foreach ($this->convertData($rrdata) as $rrd)
+        {
+            $labels[]                   = date($dateFormat, $rrd['time']);
+            $dataSets['diskread'][]     = (isset($rrd['diskread']) ? $rrd['diskread'] : 0);
+            $dataSets['diskwrite'][]    = (isset($rrd['diskwrite']) ? $rrd['diskwrite'] : 0);
+        }
+
+        //Labels
+        $this->setLabels($labels);
+        //Memory
+        $lang    = sl('lang');
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Disk Read'))
+            ->setData($dataSets['diskread'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(174, 198, 57, 0.79)',
+                "borderColor"     => 'rgba(174, 198, 57, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+        //Total
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Disk Write'))
+            ->setData($dataSets['diskwrite'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(39, 133, 134, 0.91)',
+                "borderColor"     => 'rgba(39, 133, 134, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+    }
+
+}

+ 99 - 0
app/UI/Graph/Pages/DiskSmallGraph.php

@@ -0,0 +1,99 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Oct 1, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Models\DataSet;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class DiskSmallGraph extends BaseSmallGraph
+{
+    protected $id = 'diskSmallGraph';
+    protected $name = 'diskSmallGraph';
+
+    public function initContent()
+    {
+        //yAxes
+        $this->updateChartScale('yAxes', [
+            [
+                'scaleLabel' => [
+                    'display'     => $this->displayScaleLabel,
+                    'labelString' => sl('lang')->tr('Disk'),
+                ],
+                'ticks'      => [
+                    'callback' => 'mgBytesToSize',
+                    'beginAtZero' => true,
+                    'fontSize' => 10
+                ],
+            ]]);
+        //tooltips
+        $this->updateChartOption('tooltips', [
+            'callbacks' => [
+                'label' => 'mgTooltipCallbackForDisk'
+            ]
+        ]);
+        //xAxes
+        $this->updateChartScale('xAxes', [
+            [
+                'display'   => false
+            ]]);
+
+        $this->configChartsSettings->timeframe = 'day';
+        $this->timeframe = 'day';
+    }
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        $labels     = [];
+        $dataSets   = [
+            'diskread'  => [],
+            'diskwrite' => [],
+        ];
+        foreach ($this->rrdDataQuery() as $rrd)
+        {
+            $labels[]                   = $rrd->date;
+            $dataSets['diskread'][]     = (isset($rrd->diskread) ? $rrd->diskread: 0);
+            $dataSets['diskwrite'][]    = (isset($rrd->diskwrite) ? $rrd->diskwrite : 0);
+        }
+
+        //Labels
+        $this->setLabels($labels);
+        //Memory
+        $lang    = sl('lang');
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Disk Read'))
+            ->setData($dataSets['diskread'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(174, 198, 57, 0.79)',
+                "borderColor"     => 'rgba(174, 198, 57, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+        //Total
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Disk Write'))
+            ->setData($dataSets['diskwrite'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(39, 133, 134, 0.91)',
+                "borderColor"     => 'rgba(39, 133, 134, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+    }
+}

+ 96 - 0
app/UI/Graph/Pages/GraphData.php

@@ -0,0 +1,96 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\Core\Models\ModuleSettings\Model;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+trait GraphData
+{
+    use ProductService;
+    use ApiService;
+
+    protected $timeframe = "week";
+
+    public function chartData()
+    {
+        $request = [
+            "timeframe" => $this->timeframe,
+            "cf"        => "MAX",
+        ];
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        return $vm->rrdData($request);
+    }
+
+    protected function chartOptions()
+    {
+        $registrationDate = new \DateTime($this->getWhmcsParamByKey('model')->registrationDate->format("Y-m-d"));
+        $options          = ['hour' => sl("lang")->tr("Hour")];
+        $dnow             = new \DateTime();
+        $dDiff            = $registrationDate->diff($dnow);
+        if ($dDiff->days >= 1)
+        {
+            $options['day'] = sl("lang")->tr("Day");
+        }
+        if ($dDiff->days >= 7)
+        {
+            $options['week'] = sl("lang")->tr("Week");
+        }
+        if ($dDiff->days >= 30)
+        {
+            $options['month'] = sl("lang")->tr("Month");
+        }
+        if ($dDiff->y >= 1)
+        {
+            $options['year'] = sl("lang")->tr("year");
+        }
+        return $options;
+    }
+
+    protected function loadSettings()
+    {
+        $this->configChartsSettings = json_decode(Model::where('setting', $this->graphSettingsKey)->first()->value);
+
+        if ($this->configChartsSettings)
+        {
+            $this->setGraphFilterInfo(null, $this->configChartsSettings->start, $this->configChartsSettings->end);
+        }
+
+        return $this;
+    }
+
+    protected function convertData($data, $format = null)
+    {
+        return array_slice($data, 0, 24);
+
+        $format    = [];
+        //Format data
+        foreach($this->convertData($rrdata) as $record)
+        {
+            $time           = date('Y-m-d H', $record['time']);
+            $format[$time][]   = $record;
+        }
+
+        //calculate average value
+        foreach($format as $time => $records)
+        {
+            $sum = [];
+            $count = count($records);
+
+            foreach($records as $record)
+            {
+                foreach($records as $type => $value)
+                {
+                }
+
+                $sum['time']    = strtotime($time);
+            }
+        }
+
+
+    }
+
+
+}

+ 112 - 0
app/UI/Graph/Pages/MemoryGraph.php

@@ -0,0 +1,112 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Oct 1, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages;
+
+use ModulesGarden\ProxmoxAddon\Core\Helper\DatabaseCache;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Line;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Models\DataSet;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\di;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+
+class MemoryGraph extends Line implements ClientArea, AdminArea
+{
+    use GraphData;
+    protected $graphSettingsEnabled = true;
+    protected $graphSettingsKey = 'memoryGraphSettings';
+    protected $displayScaleLabel = true;
+    protected $graphHeight = null;
+    protected $graphWidth = null;
+
+    public function initContent()
+    {
+        $this->initIds('memoryGraph');
+        $this->setRawTitle( di('lang')->translate('memoryGraph'));
+        $selectScope = new Select('timeframe');
+        $selectScope->setAvailableValues($this->chartOptions());
+        $selectScope->setDefaultValue('week');
+        $this->addSettingField($selectScope);
+        $this->updateChartScale('yAxes', [
+            [
+                'scaleLabel' => [
+                    'display'     => $this->displayScaleLabel,
+                    'labelString' => sl('lang')->tr('MB')
+                ],
+                'ticks'      => [
+                    'callback' => 'mgBytesToSize',
+                    'beginAtZero' => true,
+                    'fontSize' => 10
+                ],
+            ]]);
+        $this->updateChartOption('tooltips', [
+            'callbacks' => [
+                'label' => 'mgTooltipCallbackForMemory'
+            ]
+        ]);
+    }
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        if ($this->configChartsSettings->timeframe)
+        {
+            $this->timeframe = $this->configChartsSettings->timeframe;
+        }
+        $rrdata     = DatabaseCache::loadData(
+            $this->graphSettingsKey .$this->timeframe .$this->getWhmcsParamByKey('serviceid'). '_cacheData', [$this, 'chartData'], 30, true);
+        $labels     = [];
+        $dataSets   = [
+            'maxmem'   => [],
+        ];
+        $dateFormat = in_array($this->timeframe, ['hour', 'day']) ? "H:i:s" : "Y-m-d";
+        foreach ($this->convertData($rrdata) as $rrd)
+        {
+            $labels[]               = date($dateFormat, $rrd['time']);
+            $dataSets['mem'][]      = isset($rrd['mem']) ? $rrd['mem'] : 0;
+            $dataSets['maxmem'][]   = isset($rrd['maxmem']) ? $rrd['maxmem'] : 0;
+        }
+
+        //Labels
+        $this->setLabels($labels);
+        //Memory
+        $lang    = sl('lang');
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Memory Usage'))
+            ->setData($dataSets['mem'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(39, 133, 134, 0.91)',
+                "borderColor"     => 'rgba(39, 133, 134, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+        //Total
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Total'))
+            ->setData($dataSets['maxmem'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(174, 198, 57, 0.79)',
+                "borderColor"     => 'rgba(174, 198, 57, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+    }
+}

+ 98 - 0
app/UI/Graph/Pages/MemorySmallGraph.php

@@ -0,0 +1,98 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Oct 1, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Models\DataSet;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class MemorySmallGraph extends BaseSmallGraph
+{
+    protected $id = 'memorySmallGraph';
+    protected $name = 'memorySmallGraph';
+
+    public function initContent()
+    {
+        $this->updateChartScale('yAxes', [
+            [
+                'scaleLabel' => [
+                    'display'     => $this->displayScaleLabel,
+                    'labelString' => sl('lang')->tr('Memory')
+                ],
+                'ticks'      => [
+                    'callback' => 'mgBytesToSize',
+                    'beginAtZero' => true,
+                    'fontSize' => 10
+                ],
+            ]]);
+        $this->updateChartOption('tooltips', [
+            'callbacks' => [
+                'label' => 'mgTooltipCallbackForMemory'
+            ]
+        ]);
+
+        $this->updateChartScale('xAxes', [
+            [
+                'display'   => false
+            ]]);
+
+        $this->configChartsSettings->timeframe = 'day';
+        $this->timeframe = 'day';
+    }
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        $labels     = [];
+        $dataSets   = [
+            'maxmem'   => [],
+        ];
+        foreach ($this->rrdDataQuery() as $rrd)
+        {
+            $labels[]               = $rrd->date;
+            $dataSets['mem'][]      = isset($rrd->mem) ? $rrd->mem : 0;
+            $dataSets['maxmem'][]   = isset($rrd->maxmem) ? $rrd->maxmem : 0;
+        }
+
+        //Labels
+        $this->setLabels($labels);
+        //Memory
+        $lang    = sl('lang');
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Memory Usage'))
+            ->setData($dataSets['mem'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(39, 133, 134, 0.91)',
+                "borderColor"     => 'rgba(39, 133, 134, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+        //Total
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Total'))
+            ->setData($dataSets['maxmem'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(174, 198, 57, 0.79)',
+                "borderColor"     => 'rgba(174, 198, 57, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+    }
+
+
+}

+ 117 - 0
app/UI/Graph/Pages/NetworkGraph.php

@@ -0,0 +1,117 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Oct 1, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages;
+
+use ModulesGarden\ProxmoxAddon\Core\Helper\DatabaseCache;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Line;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Models\DataSet;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\di;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+
+class NetworkGraph extends Line implements ClientArea, AdminArea
+{
+    use GraphData;
+    protected $id = 'networkGraph';
+    protected $graphSettingsEnabled = true;
+    protected $graphSettingsKey = 'networkGraphSettings';
+    protected $displayScaleLabel = true;
+    protected $graphHeight = null;
+    protected $graphWidth = null;
+
+    public function initContent()
+    {
+        $this->initIds('networkGraph');
+        $this->setRawTitle( di('lang')->translate('networkGraph'));
+        $selectScope = new Select('timeframe');
+        $selectScope->setAvailableValues($this->chartOptions());
+        $selectScope->setDefaultValue('week');
+        $this->addSettingField($selectScope);
+        $this->updateChartScale('yAxes', [
+            [
+                'scaleLabel' => [
+                    'display'     => $this->displayScaleLabel,
+                    'labelString' => sl('lang')->tr('Bytes/s')
+                ],
+                'ticks'      => [
+                    'callback' => 'mgBytesToSize',
+                    'beginAtZero' => true,
+                    'fontSize' => 10
+                ],
+            ]]);
+        $this->updateChartOption('tooltips', [
+            'callbacks' => [
+                'label' => 'mgTooltipCallbackForNet'
+            ]
+        ]);
+
+    }
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        if ($this->configChartsSettings->timeframe)
+        {
+            $this->timeframe = $this->configChartsSettings->timeframe;
+        }
+        $rrdata     = DatabaseCache::loadData(
+            $this->graphSettingsKey.$this->timeframe  .$this->getWhmcsParamByKey('serviceid'). '_cacheData', [$this, 'chartData'], 30, true);
+        $labels     = [];
+        $dataSets   = [
+            'netin'     => [],
+            'netout'    => [],
+        ];
+        $dateFormat = in_array($this->timeframe, ['hour', 'day']) ? "H:i:s" : "Y-m-d";
+
+        foreach ($this->convertData($rrdata) as $rrd)
+        {
+            $labels[]               = date($dateFormat, $rrd['time']);
+            $dataSets['netin'][]    = isset($rrd['netin']) ? (float)$rrd['netin'] : 0;
+            $dataSets['netout'][]   = isset($rrd['netout']) ? (float)$rrd['netout'] : 0;
+        }
+
+
+        //Labels
+        $this->setLabels($labels);
+        //net in
+        $lang    = sl('lang');
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Net In'))
+            ->setData($dataSets['netin'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(174, 198, 57, 0.79)',
+                "borderColor"     => 'rgba(174, 198, 57, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+        //net out
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Net Out'))
+            ->setData($dataSets['netout'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(39, 133, 134, 0.91)',
+                "borderColor"     => 'rgba(39, 133, 134, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+    }
+}

+ 99 - 0
app/UI/Graph/Pages/NetworkSmallGraph.php

@@ -0,0 +1,99 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Oct 1, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Models\DataSet;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class NetworkSmallGraph extends BaseSmallGraph
+{
+    protected $id = 'networkSmallGraph';
+    protected $name = 'networkSmallGraph';
+
+    public function initContent()
+    {
+        $this->updateChartScale('yAxes', [
+            [
+                'scaleLabel' => [
+                    'display'     => $this->displayScaleLabel,
+                    'labelString' => sl('lang')->tr('Network')
+                ],
+                'ticks'      => [
+                    'callback' => 'mgBytesToSize',
+                    'beginAtZero' => true,
+                    'fontSize' => 10
+                ],
+            ]]);
+        $this->updateChartOption('tooltips', [
+            'callbacks' => [
+                'label' => 'mgTooltipCallbackForNet'
+            ]
+        ]);
+
+        $this->updateChartScale('xAxes', [
+            [
+                'display'   => false
+            ]]);
+        $this->configChartsSettings->timeframe = 'day';
+        $this->timeframe = 'day';
+    }
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        $labels     = [];
+        $dataSets   = [
+            'netin'     => [],
+            'netout'    => [],
+        ];
+        foreach ($this->rrdDataQuery() as $rrd)
+        {
+            $labels[]               = $rrd->date;
+            $dataSets['netin'][]    = isset($rrd->netin) ? (float)$rrd->netin : 0;
+            $dataSets['netout'][]   = isset($rrd->netout) ? (float)$rrd->netout : 0;
+        }
+
+
+        //Labels
+        $this->setLabels($labels);
+        //net in
+        $lang    = sl('lang');
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Net In'))
+            ->setData($dataSets['netin'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(174, 198, 57, 0.79)',
+                "borderColor"     => 'rgba(174, 198, 57, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+        //net out
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Net Out'))
+            ->setData($dataSets['netout'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(39, 133, 134, 0.91)',
+                "borderColor"     => 'rgba(39, 133, 134, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+    }
+
+
+}

+ 12 - 0
app/UI/Home/Buttons/AbstractActionButton.php

@@ -0,0 +1,12 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonModal;
+
+class AbstractActionButton extends ButtonModal
+{
+    protected $class = [];
+}

+ 42 - 0
app/UI/Home/Buttons/DeleteVmButton.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals\DeleteVmModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals\StopModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\BuildUrl;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class DeleteVmButton extends AbstractActionButton implements ClientArea, AdminArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteVmButton');
+        $this->setIcon('lu-zmdi lu-zmdi-delete');
+        $this->addClass('lu-btn--danger');
+        $this->initLoadModalAction(new DeleteVmModal());
+    }
+
+    public function getImageUrl()
+    {
+        return BuildUrl::getAppAssetsURL() . DS . 'img' . DS . 'buttons' . DS  . 'stopButton.png';
+    }
+}

+ 42 - 0
app/UI/Home/Buttons/RebootButton.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals\RebootModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\BuildUrl;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class RebootButton extends AbstractActionButton implements ClientArea, AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('rebootButton');
+        $this->setIcon('lu-zmdi lu-zmdi-refresh-alt');
+        $this->addClass('lu-btn--primary');
+        $this->initLoadModalAction(new RebootModal());
+    }
+
+    public function getImageUrl()
+    {
+        return BuildUrl::getAppAssetsURL() . DS . 'img' . DS . 'buttons' . DS . $this->name . '.png';
+    }
+}

+ 80 - 0
app/UI/Home/Buttons/RedirectButton.php

@@ -0,0 +1,80 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class RedirectButton extends AbstractActionButton implements ClientArea, AdminArea
+{
+    protected $id = 'redirectButton';
+    protected $icon = 'lu-zmdi lu-zmdi-plus';
+    protected $title = 'redirectButton';
+    protected $imageUrl = null;
+    protected $htmlAttributes = [
+        'data-toggle' => 'lu-tooltip',
+    ];
+
+    public function afterInitContent()
+    {
+
+    }
+
+    public function initContent()
+    {
+        $this->addClass('lu-btn--primary');
+    }
+
+    /**
+     * @return string
+     */
+    public function getHref()
+    {
+        return $this->getHtmlAttribute("href");
+    }
+
+    /**
+     * @param string $href
+     */
+    public function setHref($href)
+    {
+        $this->addHtmlAttribute("href", $href);
+        return $this;
+    }
+
+    /**
+     * @return null
+     */
+    public function getImageUrl()
+    {
+        return $this->imageUrl;
+    }
+
+    /**
+     * @param null $imageUrl
+     */
+    public function setImageUrl($imageUrl)
+    {
+        $this->imageUrl = $imageUrl;
+    }
+
+}

+ 42 - 0
app/UI/Home/Buttons/ShutdownButton.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals\ShutdownModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\BuildUrl;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class ShutdownButton extends AbstractActionButton implements ClientArea, AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('shutdownButton');
+        $this->setIcon('lu-zmdi lu-zmdi-long-arrow-down');
+        $this->addClass('lu-btn--primary');
+        $this->initLoadModalAction(new ShutdownModal());
+    }
+
+    public function getImageUrl()
+    {
+        return BuildUrl::getAppAssetsURL() . DS . 'img' . DS . 'buttons' . DS . $this->name . '.png';
+    }
+}

+ 27 - 0
app/UI/Home/Buttons/SshKeyButton.php

@@ -0,0 +1,27 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals\DeleteVmModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals\SshKeyModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\BuildUrl;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class SshKeyButton extends AbstractActionButton implements ClientArea, AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('sshKeyButton');
+        $this->setIcon('lu-zmdi lu-zmdi-power');
+        $this->initLoadModalAction(new SshKeyModal());
+    }
+
+    public function getImageUrl()
+    {
+        return BuildUrl::getAppAssetsURL() . DS . 'img' . DS . 'buttons' . DS  . 'sshKey.png';
+    }
+}

+ 42 - 0
app/UI/Home/Buttons/StartButton.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals\StartModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\BuildUrl;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class StartButton extends AbstractActionButton implements ClientArea, AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('startButton');
+        $this->setIcon('lu-zmdi lu-zmdi-long-arrow-up');
+        $this->addClass('lu-btn--primary');
+        $this->initLoadModalAction(new StartModal());
+    }
+
+    public function getImageUrl()
+    {
+        return BuildUrl::getAppAssetsURL() . DS . 'img' . DS . 'buttons' . DS . $this->name . '.png';
+    }
+}

+ 42 - 0
app/UI/Home/Buttons/StopButton.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals\StopModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\BuildUrl;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class StopButton extends AbstractActionButton implements ClientArea, AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('stopButton');
+        $this->setIcon('lu-zmdi lu-zmdi-stop');
+        $this->addClass('lu-btn--primary');
+        $this->initLoadModalAction(new StopModal());
+    }
+
+    public function getImageUrl()
+    {
+        return BuildUrl::getAppAssetsURL() . DS . 'img' . DS . 'buttons' . DS . $this->name . '.png';
+    }
+}

+ 42 - 0
app/UI/Home/Forms/DeleteVmForm.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Providers\StatusProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+
+class DeleteVmForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteVmForm');
+        $this->setFormType('deleteVm');
+        $this->setProvider(new StatusProvider());
+        $this->setConfirmMessage('confirmDeleteVm');
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['deleteVm'];
+    }
+}

+ 42 - 0
app/UI/Home/Forms/RebootForm.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Providers\StatusProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+
+class RebootForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('rebootForm');
+        $this->setFormType('reboot');
+        $this->setProvider(new StatusProvider());
+        $this->setConfirmMessage('conforimReboot');
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['reboot'];
+    }
+}

+ 42 - 0
app/UI/Home/Forms/ShutdownForm.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Providers\StatusProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+
+class ShutdownForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('shutdownForm');
+        $this->setFormType('shutdown');
+        $this->setProvider(new StatusProvider());
+        $this->setConfirmMessage('conforimShutdown');
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['shutdown'];
+    }
+}

+ 29 - 0
app/UI/Home/Forms/SshKeyForm.php

@@ -0,0 +1,29 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms;
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Providers\SshKeyProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+
+class SshKeyForm extends BaseForm implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('sshKeyForm');
+        $this->setProvider(new SshKeyProvider());
+        $this->addField(new Textarea('public'));
+        if($this->configuration()->isSshDeletePrivateKey()){
+            $this->setConfirmMessage('SSH Private Key you can download only once.');
+        }
+        $this->loadDataToForm();
+    }
+
+
+}

+ 42 - 0
app/UI/Home/Forms/StartForm.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Providers\StatusProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+
+class StartForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('startForm');
+        $this->setFormType('start');
+        $this->setProvider(new StatusProvider());
+        $this->setConfirmMessage('conforimStart');
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['start'];
+    }
+}

+ 42 - 0
app/UI/Home/Forms/StopForm.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Providers\StatusProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+
+class StopForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('stopForm');
+        $this->setFormType('stop');
+        $this->setProvider(new StatusProvider());
+        $this->setConfirmMessage('conforimStop');
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['stop'];
+    }
+}

+ 37 - 0
app/UI/Home/Modals/DeleteVmModal.php

@@ -0,0 +1,37 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms\DeleteVmForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms\StopForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteVmModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteVmModal');
+        $this->setModalSizeLarge();
+        $this->addForm(new DeleteVmForm());
+    }
+
+}

+ 36 - 0
app/UI/Home/Modals/RebootModal.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms\RebootForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class RebootModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('rebootModal');
+        $this->setModalSizeLarge();
+        $this->addForm(new RebootForm());
+    }
+
+}

+ 36 - 0
app/UI/Home/Modals/ShutdownModal.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms\ShutdownForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class ShutdownModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('shutdownModal');
+        $this->setModalSizeLarge();
+        $this->addForm(new ShutdownForm());
+    }
+
+}

+ 52 - 0
app/UI/Home/Modals/SshKeyModal.php

@@ -0,0 +1,52 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals;
+
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\UrlService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons\RedirectButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms\SshKeyForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ModalActionButtons\BaseAcceptButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ModalActionButtons\BaseCancelButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseModal;
+
+class SshKeyModal extends BaseModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('sshKeyModal');
+        $this->setModalSizeLarge();
+        $this->addForm(new SshKeyForm());
+
+    }
+
+    protected function initActionButtons()
+    {
+        if (!empty($this->actionButtons))
+        {
+            return $this;
+        }
+        if(\ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->keyPair->getPrivate()){
+            $vmId = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+            //URL
+            $urlService = new UrlService();
+            $rd         = new RedirectButton("sshPrivateKeyDownloadButton");
+            $rd->replaceClasses(['lu-btn lu-btn--success closeModal']);
+            $rd->setHref($urlService->getUrl("sshKey", "sshPrivateKeyDownload",['vm'=> $vmId]));
+            $rd->setIcon(null);
+            $rd->setShowTitle();
+            $rd->deleteHtmlAttribute('data-toggle');
+            $rd->addHtmlAttribute('@click', 'closeModal($event)');
+            $this->addActionButton($rd);
+        }
+        $this->addActionButton(new BaseCancelButton);
+
+        return $this;
+    }
+
+
+}

+ 36 - 0
app/UI/Home/Modals/StartModal.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms\StartForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseModal;
+
+class StartModal extends BaseModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('startModal');
+        $this->setModalSizeLarge();
+        $this->addForm(new StartForm());
+    }
+
+}

+ 36 - 0
app/UI/Home/Modals/StopModal.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Forms\StopForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class StopModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('stopModal');
+        $this->setModalSizeLarge();
+        $this->addForm(new StopForm());
+    }
+
+}

+ 34 - 0
app/UI/Home/Pages/AccountSummary.php

@@ -0,0 +1,34 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages;
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\AccountSummary\Providers\AccountSummaryProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceGraph\Pages\ServiceCpuGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceGraph\Pages\ServiceDiskGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceGraph\Pages\ServiceMemoryGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceGraph\Pages\ServiceNetworkGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Container;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use function ModulesGarden\ProxmoxAddon\Core\Helper\sl;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\di;
+
+class AccountSummary extends Container implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->customTplVars['bars']    = (new AccountSummaryProvider())->read();
+    }
+
+    public function initGraphs(){
+        $this->addElement(ServiceDiskGraph::class);
+        $this->addElement(ServiceCpuGraph::class);
+        $this->addElement(ServiceMemoryGraph::class);
+        $this->addElement(ServiceNetworkGraph::class);
+
+        return $this;
+    }
+}

+ 25 - 0
app/UI/Home/Pages/ErrorContainer.php

@@ -0,0 +1,25 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Builder\BaseContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class ErrorContainer extends BaseContainer implements ClientArea, AdminArea
+{
+
+    use UserService;
+
+    public function initContent()
+    {
+        if (!$this->isUser())
+        {
+            $this->customTplVars['warning'] = sl("lang")->abtr('User account does not exist. Please, create an account firstly.');
+        }
+    }
+
+}

+ 122 - 0
app/UI/Home/Pages/ServiceActions.php

@@ -0,0 +1,122 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages;
+
+
+use ModulesGarden\ProxmoxAddon\App\Models\KeyPair;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\UrlServiceHelper;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons\DeleteVmButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons\MigrateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons\RebootButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons\RedirectButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons\ShutdownButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons\SshKeyButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons\StartButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons\StopButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\BuildUrl;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Builder\BaseContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\isAdmin;
+
+
+class ServiceActions extends BaseContainer implements ClientArea, AdminArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function initContent()
+    {
+        $this->initIds('serviceActions');
+        //Start
+        if (isAdmin() || $this->configuration()->isPermissionStart())
+        {
+            $this->addButton(new StartButton("startButton"));
+        }
+        //Reboot
+        if (isAdmin() || $this->configuration()->isPermissionReboot())
+        {
+            $this->addButton(new RebootButton("rebootButon"));
+        }
+        //Stop
+        if (isAdmin() || $this->configuration()->isPermissionStop())
+        {
+            $this->addButton(new StopButton("stopButton"));
+        }
+        //Shutdown
+        if (isAdmin() || $this->configuration()->isPermissionShutdown())
+        {
+            $this->addButton(new ShutdownButton("shutdownButton"));
+        }
+
+        //noVNC
+        $serviceUrl = new UrlServiceHelper();
+        if (isAdmin() || $this->configuration()->isPermissionNovnc())
+        {
+
+            $redirectButton = new RedirectButton('novnc');
+            $redirectButton->setImageUrl(BuildUrl::getAppAssetsURL() . DS . 'img' . DS . 'buttons' . DS . 'novnc.png');
+            $redirectButton->addHtmlAttribute("onclick", "window.open('{$serviceUrl->getNoVncConsoleUrl()}', '', 'width=900,height=700'); return false;");
+            $redirectButton->setHref("#");
+            $redirectButton->setIcon('lu-zmdi lu-zmdi-fullscreen');
+            $this->addButton($redirectButton);
+        }
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        //Spice Console
+        if (isAdmin() || $this->configuration()->isPermissionSpice())
+        {
+            $redirectButton = new RedirectButton('spice');
+            $redirectButton->setImageUrl(BuildUrl::getAppAssetsURL() . DS . 'img' . DS . 'buttons' . DS . 'spice.png');
+            $redirectButton->setHref($serviceUrl->getSpiceConsoleUrl());
+           if($vm->getVmid()!=0  || !$vm->hasSpiceproxy()){
+               $redirectButton->addHtmlAttribute("disabled",true);
+           }
+            $redirectButton->setIcon('lu-zmdi lu-zmdi-fullscreen');
+            $this->addButton($redirectButton);
+        }
+        //Xterm.js Console
+        if (isAdmin() || $this->configuration()->isPermissionXtermjs())
+        {
+            $redirectButton = new RedirectButton('xtermjs');
+            $redirectButton->setImageUrl(BuildUrl::getAppAssetsURL() . DS . 'img' . DS . 'buttons' . DS . 'xtermjs.png');
+            $redirectButton->addHtmlAttribute("onclick", "window.open('{$serviceUrl->getXTermConsoleUrl()}', '', 'width=900,height=700'); return false;");
+            $redirectButton->setIcon('lu-zmdi lu-zmdi-fullscreen');
+            $this->addButton($redirectButton);
+        }
+        //Migration
+        if (isAdmin())
+        {
+            $this->addButton(new MigrateButton());
+        }
+        //ssh key lxc only
+        $keyPair = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->keyPair;
+        if( $keyPair instanceof  KeyPair){
+            $this->addButton(new SshKeyButton());
+        }
+        //Delete VM
+        $this->addButton(new DeleteVmButton('deleteVmButton'));
+        $this->customTplVars['buttonSyle'] = $this->configuration()->getButtonSyle();
+    }
+
+
+}

+ 52 - 0
app/UI/Home/Pages/ServiceDetails.php

@@ -0,0 +1,52 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages;
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages\CpuSmallGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages\DiskSmallGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages\MemorySmallGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages\NetworkSmallGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Pages\ServiceInformation;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+
+class ServiceDetails extends HalfPageSection implements ClientArea, AdminArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function initContent()
+    {
+        $this->initIds('serviceDetails');
+        $this->customTplVars['ajaxStat'] = new ServiceInformation();
+
+        $this->addElement(DiskSmallGraph::class)
+            ->addElement(CpuSmallGraph::class)
+            ->addElement(MemorySmallGraph::class)
+            ->addElement(NetworkSmallGraph::class);
+
+    }
+}

+ 107 - 0
app/UI/Home/Pages/ServiceManagement.php

@@ -0,0 +1,107 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\UrlService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons\RedirectButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\BuildUrl;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Builder\BaseContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\isAdmin;
+
+
+class ServiceManagement extends BaseContainer implements ClientArea, AdminArea
+{
+    use ProductService;
+    /**
+     * @var UrlService
+     */
+    private $urlService;
+
+    public function initContent()
+    {
+        $this->initIds('serviceManagement');
+        //Url Service
+        $this->urlService = new UrlService();
+        //Reinstall
+        if (isAdmin() || $this->configuration()->isPermissionReinstall())
+        {
+            $this->addServiceButton('reinstall');
+        }
+        //Backups
+        if (isAdmin() || $this->configuration()->isPermissionBackup() || $this->configuration()->isPermissionBackupJob())
+        {
+            $this->addServiceButton('backup');
+        }
+        //Backup Jobs
+        if (isAdmin() || $this->configuration()->isPermissionBackupJob())
+        {
+            $this->addServiceButton('backupJob');
+        }
+        //Graphs
+        if (isAdmin() || $this->configuration()->isPermissionGraph())
+        {
+            $this->addServiceButton('graph');
+        }
+        //Task History
+        if (isAdmin() || $this->configuration()->isPermissionTaskHistory())
+        {
+            $this->addServiceButton('taskHistory');
+        }
+        //Network
+        if (isAdmin() || $this->configuration()->isPermissionNetwork())
+        {
+            $this->addServiceButton('network');
+        }
+        //Snapshots
+        if (isAdmin() || $this->configuration()->isPermissionSnapshot())
+        {
+            $this->addServiceButton('snapshot');
+        }
+        //Firewall
+        if (isAdmin() || $this->configuration()->isPermissionFirewall())
+        {
+            $this->addServiceButton('firewall');
+        }
+        //Firewall Options
+        if (isAdmin() || $this->configuration()->isPermissionFirewallOption())
+        {
+            $this->addServiceButton('firewallOption');
+        }
+        //Disks
+        if (isAdmin() || $this->configuration()->isPermissionDisk())
+        {
+            $this->addServiceButton('disk');
+        }
+    }
+
+    private function addServiceButton($id)
+    {
+        $rd = new RedirectButton($id);
+        $rd->setHref($this->urlService->getUrl($id));
+        $rd->setImageUrl(BuildUrl::getAppAssetsURL() . DS . 'img' . DS . 'buttons' . DS . $id . '.png');
+        $this->addButton($rd);
+    }
+
+
+}

+ 69 - 0
app/UI/Home/Pages/VmBuild.php

@@ -0,0 +1,69 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages;
+
+
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CloneQemuJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateLxcJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateQemuJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\LoadBalancer\UpgradeVmJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\MigrateVmJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Reinstall\CreateVmJob;
+use ModulesGarden\ProxmoxAddon\App\Models\Job;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Builder\BaseContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+/**
+ * Class VmBuild
+ * @package ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages
+ * @todo
+ */
+class VmBuild extends BaseContainer implements ClientArea, AdminArea
+{
+
+    public function initContent()
+    {
+        if ($this->isVmCreate())
+        {
+            $this->customTplVars['warning'] = sl("lang")->abtr('The process of Virtual Machine creation is in progress.');
+        }
+        else if ($this->isVmReinstall()) {
+                $this->customTplVars['warning'] = sl("lang")->abtr('Rebuild VM in progress. Please try again later.');
+        } else if ($this->isVmUpgrade()){
+            $this->customTplVars['warning'] = sl("lang")->abtr('Upgrading VM in progress. Please try again later.');
+        }else {
+            $this->customTplVars['warning'] = sl("lang")->abtr('Unknown error.');
+        }
+    }
+
+    private function isVmCreate()
+    {
+        $jobs = [
+            CloneQemuJob::class,
+            CreateQemuJob::class,
+            CreateLxcJob::class,
+        ];
+        return Job::waiting()->ofHostingId($this->getWhmcsParamByKey("serviceid"))->ofJobs($jobs)->count();
+    }
+
+    private function isVmReinstall()
+    {
+        $jobs = [
+            CreateVmJob::class
+        ];
+        return Job::waiting()->ofHostingId($this->getWhmcsParamByKey("serviceid"))->ofJobs($jobs)->count();
+    }
+
+    private function isVmUpgrade()
+    {
+        $jobs = [
+            MigrateVmJob::class,
+            \ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\RestoreVm::class,
+            UpgradeVmJob::class
+        ];
+        return Job::waiting()->ofHostingId($this->getWhmcsParamByKey("serviceid"))->ofJobs($jobs)->count();
+    }
+}

+ 22 - 0
app/UI/Home/Providers/SshKeyProvider.php

@@ -0,0 +1,22 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Providers;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+class SshKeyProvider extends BaseDataProvider implements ClientArea
+{
+
+    public function read()
+    {
+        $this->data['public'] = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->keyPair->getPublic();
+
+    }
+
+    public function update()
+    {
+    }
+}

+ 121 - 0
app/UI/Home/Providers/StatusProvider.php

@@ -0,0 +1,121 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Providers;
+
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\RebootVmJob;
+use ModulesGarden\ProxmoxAddon\App\Models\Job;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\HighAvailabilityClusterService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\CloudService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\UrlServiceHelper;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
+
+
+class StatusProvider extends BaseDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function start()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vm->start();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Virtual Machine has been booted successfully')
+            ->addData('refreshState', 'serverinformationTable')
+            ->addRefreshTargetId('serviceInformationDataTable');
+    }
+
+    public function reboot()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $ha = new HighAvailabilityClusterService();
+        if ($ha->exist())
+        {
+            //reboot
+            if (!Job::waiting()->ofJob(RebootVmJob::class)->ofHostingId($this->getWhmcsParamByKey("serviceid"))->count())
+            {
+                queue(RebootVmJob::class, [], null, "hosting", $this->getWhmcsParamByKey("serviceid"));
+            }
+            return (new HtmlDataJsonResponse())
+                ->setStatusSuccess()
+                ->setMessageAndTranslate('Rebooting container in progress')
+                ->addData('refreshState', 'serverinformationTable')
+                ->addRefreshTargetId('serviceInformationDataTable');
+        }
+        else
+        {
+            $vm->restart();
+            return (new HtmlDataJsonResponse())
+                ->setStatusSuccess()
+                ->setMessageAndTranslate('The Virtual Machine has been rebooted successfully')
+                ->addData('refreshState', 'serverinformationTable')
+                ->addRefreshTargetId('serviceInformationDataTable');
+        }
+
+    }
+
+    public function stop()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vm->stop();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Virtual Machine has been stopped successfully')
+            ->addData('refreshState', 'serverinformationTable')
+            ->addRefreshTargetId('serviceInformationDataTable');
+    }
+
+    public function shutdown()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vm->shutdown();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Virtual Machine has been shut down successfully')
+            ->addData('refreshState', 'serverinformationTable')
+            ->addRefreshTargetId('serviceInformationDataTable');
+    }
+
+    public function deleteVm()
+    {
+        $vmModel = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
+        //destory vm
+        (new CloudService())->delete($vmModel);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setCallBackFunction('pcVmDeltedAjaxDone')
+            ->addData('redirectUrl' , (new UrlServiceHelper())->home())
+            ->setMessageAndTranslate('The Virtual Machine has been deleted successfully');
+    }
+
+    public function read()
+    {
+    }
+
+    public function update()
+    {
+    }
+}

+ 31 - 0
app/UI/Home/Templates/pages/accountSummary.tpl

@@ -0,0 +1,31 @@
+<div class="lu-row">
+    <div class="col-md-5">
+        <h4 class="text-left">{$MGLANG->translate('virtualDataCenter')}</h4>
+        <div class=" lu-m-t-2x">
+            {foreach from=$customTplVars.bars item=bar}
+                <div class="lu-progress lu-progress--h lu-progress--s lu-progress__label">
+                    <div class="lu-progress__label">
+                        {$bar.name} {*({$bar.used}/{$bar.max}{if $bar.unit} {$bar.unit}{/if})*}
+                    </div>
+                    <div class="lu-progress__bar progress-bar-danger">
+                        <div class="lu-progress__fill" style="width: {$bar.value}%"></div>
+                    </div>
+                </div>
+            {/foreach}
+        </div>
+    </div>
+
+    <div class="lu-col-md-7">
+        <div class="lu-row">
+            {foreach from=$elements key=nameElement item=dataElement}
+                <div id="{$dataElement->getId()}" class="{$dataElement->getClasses()} lu-col-md-6">
+                    {$dataElement->getHtml()}
+                </div>
+            {/foreach}
+        </div>
+    </div>
+</div>
+
+
+
+

+ 5 - 0
app/UI/Home/Templates/pages/errorContainer.tpl

@@ -0,0 +1,5 @@
+<div class="alert alert-warning" role="alert">
+    <button type="button" class="close" data-dismiss="alert"></button>
+    <p>{$customTplVars.warning}</p>
+    {if $customTplVars.warningMessage}<p>{$customTplVars.warningMessage}</p>{/if}
+</div>

+ 15 - 0
app/UI/Home/Templates/pages/manageService.tpl

@@ -0,0 +1,15 @@
+<div class="h4 lu-m-b-3x lu-m-t-3x">{$MGLANG->absoluteT('serverCA','home','pagesHeader')}</div>
+<div class="lu-tiles lu-row lu-row--eq-height">
+    {foreach from=$rawObject->getPages() key=controller item=settings}
+        <div class="lu-col-sm-20p" style="justify-content: center;">
+            <a class="lu-tile lu-tile--btn" href="{$rawObject->getURL($controller)}">
+                <div class="lu-i-c-6x">
+                    <img src="{$rawObject->getImageUrl($controller)}"
+                         alt="{$MGLANG->absoluteT('serverCA' , 'iconTitle' ,$controller)}"/>
+                </div>
+                <div class="lu-tile__title">{$MGLANG->absoluteT('serverCA' , 'iconTitle' ,$controller)}</div>
+            </a>
+        </div>
+    {/foreach}
+</div>
+

+ 37 - 0
app/UI/Home/Templates/pages/serviceActions.tpl

@@ -0,0 +1,37 @@
+{*Tiles*}
+{if !$customTplVars.buttonSyle || $customTplVars.buttonSyle=='tiles'}
+<div class="lu-tiles lSu-row lu-row--eq-height">
+    <hr class="lu-m-v-2x"/>
+    {foreach from=$rawObject->getButtons() key=buttonId item=dataElement}
+    <div class="lu-col-sm-20p {if $buttonId == 'deleteVmButton'} lu-pull-right{/if}" style="justify-content: center;" data-button-id="{$buttonId}">
+        <a class="lu-tile lu-tile--btn" {foreach $dataElement->getHtmlAttributes() as $aValue} {$aValue@key}="{$aValue}" {/foreach}
+        data-title="{$MGLANG->absoluteT('buttons','actions', $dataElement->getTitle())}">
+        <div class="lu-i-c-6x">
+            <img src="{$dataElement->getImageUrl()}"
+                 alt="{$MGLANG->absoluteT('serverCA' , 'iconTitle' ,$dataElement->getTitle())}"/>
+        </div>
+        <span class="lu-tile__title">{$MGLANG->absoluteT('serverCA' , 'iconTitle' ,$dataElement->getTitle())}</span>
+        </a>
+    </div>
+    {/foreach}
+    <hr class="lu-m-t-0x lu-m-b-3x"/>
+</div>
+{*Custom Button*}
+{elseif $customTplVars.buttonSyle=='buttons'}
+    <div class="lu-widget vm-actions">
+        <div class="lu-widget__body">
+            <div class="lu-widget__content">
+                {foreach from=$rawObject->getButtons() key=buttonId item=dataElement}
+                    <a class="lu-btn lu-btn--xs lu-justify-content-between lu-m-b-1x lu-m-t-0x lu-m-l-0x lu-m-r-1x  lu-btn--primary {$dataElement->getClasses()}" {foreach $dataElement->getHtmlAttributes() as $aValue} {$aValue@key}="{$aValue}" {/foreach}
+                    data-title="{$MGLANG->absoluteT('buttons','actions', $dataElement->getTitle())}">
+                    <i class="btn__icon {$dataElement->getIcon()}"></i>
+                    <span class="lu-btn__text">{$MGLANG->absoluteT('serverCA' , 'iconTitle' ,$dataElement->getTitle())}</span>
+                    </a>
+                {/foreach}
+            </div>
+        </div>
+    </div>
+{/if}
+
+
+

+ 15 - 0
app/UI/Home/Templates/pages/serviceDetails.tpl

@@ -0,0 +1,15 @@
+<div class="lu-row">
+    <div class="col-md-6">
+        {$customTplVars.ajaxStat->getHtml()}
+    </div>
+
+    <div class="lu-col-md-6">
+        <div class="lu-row lu-m-t-3x">
+            {foreach from=$elements key=nameElement item=dataElement}
+                <div id="{$dataElement->getId()}" class="{$dataElement->getClasses()} lu-col-md-6">
+                    {$dataElement->getHtml()}
+                </div>
+            {/foreach}
+        </div>
+    </div>
+</div>

+ 17 - 0
app/UI/Home/Templates/pages/serviceManagement.tpl

@@ -0,0 +1,17 @@
+<div class="h4 lu-m-b-3x lu-m-t-3x">{$MGLANG->absoluteT('serverCA','home',$rawObject->getId())}</div>
+<div class="lu-tiles lu-row lu-row--eq-height">
+    {foreach from=$rawObject->getButtons() key=setting item=dataElement}
+        <div class="lu-col-sm-20p" style="justify-content: center;">
+            <a class="{$dataElement->getClasses()}" href="{$dataElement->getHref()}" {if $dataElement->isRawTitle()}title="{$dataElement->getRawTitle()}"{elseif $dataElement->getTitle()}title="{$MGLANG->T('button', $dataElement->getTitle())}"{/if}  {foreach $dataElement->getHtmlAttributes() as $aValue} {$aValue@key}="{$aValue}"{/foreach}>
+                <div class="lu-i-c-6x">
+                    {if $dataElement->getImageUrl()}
+                        <img src="{$dataElement->getImageUrl()}"
+                             alt="{$MGLANG->absoluteT('serverCA' , 'iconTitle' , $dataElement->getId())}"/>
+                    {/if}
+                </div>
+                <div class="lu-tile__title">{$MGLANG->absoluteT('serverCA' , 'iconTitle' , $dataElement->getId())}</div>
+            </a>
+        </div>
+    {/foreach}
+</div>
+

+ 5 - 0
app/UI/Home/Templates/pages/vmBuild.tpl

@@ -0,0 +1,5 @@
+<div class="alert alert-warning" role="alert">
+    <button type="button" class="close" data-dismiss="alert"></button>
+    <p>{$customTplVars.warning}</p>
+    {if $customTplVars.warningMessage}<p>{$customTplVars.warningMessage}</p>{/if}
+</div>

+ 35 - 0
app/UI/IpAddress/Buttons/CreateButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Modals\CreateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+
+class CreateButton extends ButtonCreate implements AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createButton');
+        $this->initLoadModalAction(new CreateModal());
+    }
+
+}

+ 37 - 0
app/UI/IpAddress/Buttons/DeleteButton.php

@@ -0,0 +1,37 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class DeleteButton extends ButtonDataTableModalAction implements AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteButton');
+        $this->setDisableByColumnValue("master", true);
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteModal());
+    }
+
+}

+ 73 - 0
app/UI/IpAddress/Forms/CreateForm.php

@@ -0,0 +1,73 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Forms;
+
+
+use ModulesGarden\ProxmoxAddon\App\UI\Validators\MacAddressValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Providers\DiskProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Providers\IpAddressProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\CidrValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\IpAddressValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+
+class CreateForm extends BaseForm implements AdminArea
+{
+    public function initContent()
+    {
+        $this->initIds('createForm');
+        $this->setFormType('create');
+        $this->setProvider(new IpAddressProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+
+    private function initFields()
+    {
+        //ip
+        $field = new Text('ip');
+        $field->addValidator(new IpAddressValidator(true));
+        $this->addField($field);
+        // mac_address
+        $field = new Text('mac_address');
+        $field->addValidator(new MacAddressValidator());
+        $this->addField($field);
+        //subnet_mask
+        $field = new Text('subnet_mask');
+        $field->addValidator(new IpAddressValidator(false));
+        $this->addField($field);
+        //gateway
+        $field = new Text('gateway');
+        $field->addValidator(new IpAddressValidator(false));
+        $this->addField($field);
+        $field = new Text('cidr');
+        $field->addValidator(new CidrValidator(true));
+        $field->setPlaceholder('24');
+        $this->addField($field);
+
+    }
+}

+ 53 - 0
app/UI/IpAddress/Forms/DeleteForm.php

@@ -0,0 +1,53 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Providers\DiskProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Providers\FirewallOptionProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Providers\IpAddressProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class DeleteForm extends BaseForm implements AdminArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteForm');
+        $this->setFormType('delete');
+        $this->setProvider(new IpAddressProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDelete', ["ip" => null]);
+        $this->addField(new Hidden("id"));
+        $this->addField(new Hidden("ip"));
+    }
+
+}

+ 35 - 0
app/UI/IpAddress/Modals/CreateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Forms\CreateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmSuccess;
+
+class CreateModal extends ModalConfirmSuccess implements AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createModal');
+        $this->addForm(new CreateForm());
+    }
+
+}

+ 35 - 0
app/UI/IpAddress/Modals/DeleteModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteModal extends ModalConfirmDanger implements AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteModal');
+        $this->addForm(new DeleteForm());
+    }
+
+}

+ 109 - 0
app/UI/IpAddress/Pages/IpAddressDataTable.php

@@ -0,0 +1,109 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Buttons\CreateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\QueryDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\isAdmin;
+
+class IpAddressDataTable extends DataTable implements ClientArea, AdminArea
+{
+    protected $id = 'ipAddressDataTable';
+    protected $name = 'ipAddressDataTable';
+    protected $title = 'ipAddressDataTable';
+
+    public function initContent()
+    {
+        $this->addClass('lu-text-left')
+            ->addClass('lu-col-md-12');
+
+        if (isAdmin())
+        {
+            $this->addButton(new CreateButton());
+            $this->addActionButton(new DeleteButton());
+        }
+        else
+        {
+            $this->unsetShowTitle();
+        }
+    }
+
+    protected function loadHtml()
+    {
+        if (isAdmin())
+        {
+            $this->addColumn((new Column('vmid')));
+        }
+        $this->addColumn((new Column('ip')))
+            ->addColumn((new Column('mac_address')))
+            ->addColumn((new Column('subnet_mask')))
+            ->addColumn((new Column('gateway')));
+    }
+
+    public function replaceFieldMac_address($key, $row)
+    {
+        return $row->{$key} ? $row->{$key} : '-';
+    }
+
+    public function replaceFieldSubnet_mask($key, $row)
+    {
+        return $row->{$key} ? $row->{$key} : '-';
+    }
+
+    public function replaceFieldGateway($key, $row)
+    {
+        return $row->{$key} ? $row->{$key} : '-';
+    }
+
+    public function replaceFieldVmid($key, $row)
+    {
+        return $row->{$key} ? $row->{$key} : '-';
+    }
+
+    protected function loadData()
+    {
+        $vm = (new VmModel())->getTable();
+        $i = (new VmIpAddress)->getTable();
+        $query    = VmIpAddress::select("{$vm}.vmid", "{$i}.id", "{$i}.ip", "{$i}.mac_address", "{$i}.subnet_mask", "{$i}.gateway")
+            ->leftJoin($vm,"{$vm}.id", "=", "{$i}.vm_id")
+                ->where("{$i}.hosting_id", $this->getWhmcsParamByKey('serviceid'));
+        $query =  $query->getQuery();
+        $dataProv = new QueryDataProvider();
+        $dataProv->setDefaultSorting("ip", 'ASC');
+        $dataProv->setData($query);
+        $this->setDataProvider($dataProv);
+    }
+    public function isViewFooter()
+    {
+        return false;
+    }
+
+    public function isViewTopBody()
+    {
+        return false;
+    }
+}

+ 135 - 0
app/UI/IpAddress/Providers/IpAddressProvider.php

@@ -0,0 +1,135 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Providers;
+
+use MGProvision\Proxmox\v2\Api;
+use MGProvision\Proxmox\v2\VmFactory;
+use ModulesGarden\ProxmoxAddon\App\Models\IpAddress;
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualInterface;
+use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\IpSetIpFilterService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Utility;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+use Illuminate\Database\Capsule\Manager as DB;
+use function ModulesGarden\ProxmoxAddon\Core\Helper\sl;
+
+class IpAddressProvider extends BaseDataProvider implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+
+
+    private $networkService;
+    /**
+     * @var IpSetIpFilterService
+     */
+    private $ipSetIpFilterService;
+
+    /**
+     * IpAddressProvider constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->networkService       = new NetworkService();
+        $this->ipSetIpFilterService = new IpSetIpFilterService();
+    }
+
+    public function read()
+    {
+        if ($this->actionElementId && $this->actionElementId != "diskDataTable")
+        {
+            $this->data['id'] = $this->actionElementId;
+            $this->data['ip'] = VmIpAddress::where("id", $this->actionElementId)->value("ip");
+        }
+    }
+
+    public function create()
+    {
+        $ip = new VmIpAddress();
+        $ip->fill($this->formData);
+        $ip->hosting_id = $this->getWhmcsParamByKey("serviceid");
+        $ip->server_id  = $this->getWhmcsParamByKey("serverid");
+        $this->networkService->create([$ip]);
+
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The IP Address has been added successfully');
+    }
+
+    public function update()
+    {
+    }
+
+    public function delete()
+    {
+        try {
+            $this->api();
+            DB::beginTransaction();
+            Api::beginTransaction();
+            //delete ip
+            /**
+             * @var VmIpAddress $ip
+             */
+            $ip = VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                ->where("id", $this->formData['id'])
+                ->firstOrFail();
+            $ip->delete();
+            //unlock in proxmox addon
+            IpAddress::where('ip', $ip->ip)
+                ->where('hosting_id', $ip->hosting_id)
+                ->update(["hosting_id" => "0", 'last_check' => Utility::timeStamp()]);
+            //delete network device
+            if($ip->vm_id && $ip->net){
+                $vm = (new VmFactory)->fromVmModel($ip->vmModel);
+                sl('Vm')->setVm($vm);
+                if($vm->config()[$ip->net]){
+                    $vm->deleteConfig($ip->net);
+                }
+            }
+            //delete virtual interface
+            VirtualInterface::ofHostingId($ip->hosting_id)
+                ->ofIp($ip->ip)
+                ->delete();
+            //delete in hosting
+            $ip->hosting->ipDelete($ip->ip);
+            if ($this->configuration()->isIpsetIpFilter() && $vm)
+            {
+                $this->ipSetIpFilterService->create();
+            }
+            DB::commit();
+            Api::commit();
+            return (new HtmlDataJsonResponse())
+                ->setStatusSuccess()
+                ->setMessageAndTranslate('The IP Address has been deleted successfully');
+        }catch (\Exception $ex){
+            DB::rollBack();
+            Api::commit();
+            throw $ex;
+        }
+    }
+
+
+}

+ 66 - 0
app/UI/MountPoint/Buttons/BackupSwitchButton.php

@@ -0,0 +1,66 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Buttons;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\DataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonSwitchAjax;
+
+class BackupSwitchButton extends ButtonSwitchAjax implements ClientArea
+{
+
+    use ApiService;
+    use ProductService;
+    protected $switchColumn = 'backup';
+    protected $id = 'backupSwitchButton';
+    protected $name = 'backupSwitchButton';
+    protected $refreshActionIds = 'mountPointDataTable';
+
+    public function initContent()
+    {
+        parent::initContent();
+        $this->addHtmlAttribute(':disabled', 'dataRow.master == true');
+        if (!$this->configuration()->isPermissionMountPointBackup())
+        {
+            $this->addHtmlAttribute('disabled', '');
+        }
+
+    }
+
+    public function returnAjaxData()
+    {
+        try
+        {
+            $this->acl()->backup();
+            $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+            $hdd = $vm->getMounPoints()->findMountPointById($this->getRequestValue('actionElementId'));
+            $hdd->setBackup($this->getRequestValue("value") == "on" ? 1 : null);
+            $hdd->update();
+        }
+        catch (\Exception $exc)
+        {
+            return (new DataJsonResponse())->setStatusError()->setMessage($exc->getMessage())->setCallBackFunction($this->callBackFunction)->addRefreshTargetId($this->refreshActionIds);
+        }
+        return (new DataJsonResponse())->setMessageAndTranslate('changesSaved')->setCallBackFunction($this->callBackFunction)->addRefreshTargetId($this->refreshActionIds);
+    }
+
+}

+ 35 - 0
app/UI/MountPoint/Buttons/CreateButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Modals\CreateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+
+class CreateButton extends ButtonCreate implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createButton');
+        $this->initLoadModalAction(new CreateModal());
+    }
+
+}

+ 37 - 0
app/UI/MountPoint/Buttons/DeleteButton.php

@@ -0,0 +1,37 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class DeleteButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteButton');
+        $this->setDisableByColumnValue("master", true);
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteModal());
+    }
+
+}

+ 35 - 0
app/UI/MountPoint/Buttons/UpdateButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Modals\UpdateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class UpdateButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateButton');
+        $this->initLoadModalAction(new UpdateModal());
+    }
+
+}

+ 70 - 0
app/UI/MountPoint/Forms/CreateForm.php

@@ -0,0 +1,70 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Providers\MountPointProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+
+class CreateForm extends BaseForm implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('createDiskForm');
+        $this->setFormType('create');
+        $this->setProvider(new MountPointProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+
+    private function initFields()
+    {
+        //size
+        $field = new Text('size');
+        $resourceManager = new ResourceManager();
+        $field->addValidator(new NumberValidator($resourceManager->disk()->getMin(),$resourceManager->disk()->free(), true));
+        $field->setDefaultValue($this->configuration()->serverDiskSize->min);
+        $this->addField($field);
+        //mp
+        $field = new Text('mp');
+        $field->setPlaceholder("/some/path");
+        $field->notEmpty();
+        $this->addField($field);
+        //backup
+        if ($this->configuration()->isPermissionMountPointBackup())
+        {
+            $field = new Switcher('backup');
+            $this->addField($field);
+        }
+    }
+}

+ 51 - 0
app/UI/MountPoint/Forms/DeleteForm.php

@@ -0,0 +1,51 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Providers\FirewallOptionProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Providers\MountPointProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class DeleteForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteDiskForm');
+        $this->setFormType('delete');
+        $this->setProvider(new MountPointProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDelete');
+        $this->addField(new Hidden("id"));
+    }
+
+}

+ 66 - 0
app/UI/MountPoint/Forms/UpdateForm.php

@@ -0,0 +1,66 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Providers\MountPointProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Validators\DiskSizeValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+class UpdateForm extends BaseForm implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('updateDiskForm');
+        $this->setFormType('update');
+        $this->setProvider(new MountPointProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['update'];
+    }
+
+    private function initFields()
+    {
+        //entity id
+        $this->addField(new Hidden("id"));
+        //size
+        $field = new Text('size');
+        $field->addValidator(new DiskSizeValidator(true));
+        $this->addField($field);
+        //backup
+        if ($this->configuration()->isPermissionMountPointBackup())
+        {
+            $field = new Switcher('backup');
+            $this->addField($field);
+        }
+
+    }
+}

+ 35 - 0
app/UI/MountPoint/Modals/CreateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Forms\CreateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class CreateModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createDiskModal');
+        $this->addForm(new CreateForm());
+    }
+
+}

+ 35 - 0
app/UI/MountPoint/Modals/DeleteModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteDiskModal');
+        $this->addForm(new DeleteForm());
+    }
+
+}

+ 35 - 0
app/UI/MountPoint/Modals/UpdateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Forms\UpdateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class UpdateModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateDiskModal');
+        $this->addForm(new UpdateForm());
+    }
+
+}

+ 134 - 0
app/UI/MountPoint/Pages/MountPointDataTable.php

@@ -0,0 +1,134 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Libs\Format;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Buttons\BackupSwitchButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Buttons\CreateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Buttons\RestoreButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Buttons\UpdateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class MountPointDataTable extends DataTable implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+    protected $id = 'mountPointDataTable';
+    protected $name = 'mountPointDataTable';
+    protected $title = 'mountPointDataTableTitle';
+
+    public function initContent()
+    {
+        $resourceManager = new ResourceManager();
+        $this->setInternalAlertMessage("Adding, editing or removing disk will reboot the virtual machine.");
+        //Create
+        $createButton = new CreateButton();
+        $createButton->addClass("pmCreateDiskButton");
+        if (! $resourceManager->disk()->hasFreeTotal())
+        {
+            $createButton->addClass("hidden");
+        }
+        $this->unsetShowTitle();
+
+        $this->addButton($createButton);
+        //Update
+        $this->addActionButton(new UpdateButton());
+        //Delete
+        $this->addActionButton(new DeleteButton());
+    }
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('id'))->setSearchable(true, "string")->setOrderable('DESC'))
+            ->addColumn((new Column('name'))->setSearchable(true, "string")->setOrderable())
+            ->addColumn((new Column('mp'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('backup'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('bytes'))->setSearchable(true)->setOrderable());
+    }
+
+    public function replaceFieldName($key, $row)
+    {
+        $id = preg_replace('/[^0-9]/', '', $row[$key]);
+        $id++;
+        sl("lang")->addReplacementConstant("id",$id);
+        return sl("lang")->abtr('Disk :id:');
+    }
+
+    public function replaceFieldPath($key, $row)
+    {
+        if ($row[$key])
+        {
+            return $row[$key];
+        }
+        return '-';
+    }
+
+    public function customColumnHtmlBackup()
+    {
+        return (new BackupSwitchButton())->getHtml();
+    }
+
+    public function replaceFieldBackup($key, $row)
+    {
+        if ($row['master'])
+        {
+            return "on";
+        }
+        return $row['backup'] == "1" ? "on" : "off";
+    }
+
+    public function replaceFieldBytes($key, $row)
+    {
+        return Format::convertBytes($row['bytes']);
+    }
+
+    protected function loadData()
+    {
+        $data = [];
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        foreach ( $vm->getMounPoints()->fetch() as $entity)
+        {
+            $data[] = [
+                "id"     => $entity->getId(),
+                "name"   => $entity->getName(),
+                "mp"   => $entity->getMp(),
+                "backup" => $entity->getBackup(),
+                "size"   => $entity->getSize(),
+                "bytes"  => $entity->getBytes(),
+                "master" => $entity->getId() == "rootfs"
+            ];
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setDefaultSorting("id", 'DESC');
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+
+}

+ 160 - 0
app/UI/MountPoint/Providers/MountPointProvider.php

@@ -0,0 +1,160 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Providers;
+
+use MGProvision\Proxmox\v2\models\MountPoint;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\RebootVmJob;
+use ModulesGarden\ProxmoxAddon\App\Models\Job;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
+
+
+class MountPointProvider extends BaseDataProvider implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+
+    public function read()
+    {
+        if ($this->actionElementId && $this->actionElementId != "mountPointDataTable")
+        {
+            $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+
+            $disk = $vm->getMounPoints()->findMountPointById($this->actionElementId);
+            $this->data       = $disk->toArray();
+            $this->data['id'] = $this->actionElementId;
+            //backup
+            $backup               = $this->data['backup'];
+            $this->data['backup'] = $backup == "1" ? "on" : "off";
+            //size
+            $this->data['size'] = (int)$disk->getGb();
+        }
+    }
+
+    public function create()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vmModel = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
+        //disk storage
+        $storage              = $this->configuration()->getMountPointStorage();
+        $mountPointRepository = $vm->getMounPoints();
+        $hdd                  = new MountPoint($mountPointRepository->nextId());
+        $vmModel->disks += $this->formData['size'];
+        $hdd->setLocation($storage . ":" . $this->formData['size'])
+            ->setAcl($this->configuration()->getMountPointAcl() == "default" ? null : $this->configuration()->getMountPointAcl())
+            ->setRo($this->configuration()->isMountPointRo() ? 1 : null)
+            ->setQuota($this->configuration()->isMountPointQuota() ? 1 : null)
+            ->setBackup($this->configuration()->isPermissionMountPointBackup() && $this->formData['backup'] == "on" ? 1 : null)
+            ->setReplicate($this->configuration()->isMountPointReplicate() ? '0' : null)
+            ->setMp($this->formData['mp'])
+            ->setPath($vm->getPath() . "/config")
+            ->setApi($this->api())
+            ->create();
+        $vmModel->save();
+        $resourceManager = new ResourceManager();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The hard disk has been created successfully')
+            ->addData('createButtonStatus', $resourceManager->disk()->hasFreeTotal())
+            ->setCallBackFunction('pmToggleDiskButton');
+    }
+
+    public function update()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vmModel = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
+        $hdd = $vm->getMounPoints()->findMountPointById($this->formData['id']);
+        if ((int)$hdd->getGb() > (int)$this->formData['size'])
+        {
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('Downgrading the disk size is restricted');
+        }
+        //resize
+        if ((int)$hdd->getGb() < (int)$this->formData['size'])
+        {
+            $size = "+" . abs((int)$this->formData['size'] - (int)$hdd->getGb()) . "G";
+            $hdd->resize($size);
+        }
+        if($hdd->isMaster()){
+            $vm->config(true);
+            $vmModel->disk =  (int)$this->formData['size'];
+        }else{
+            sleep(2);
+            $vmModel->disks = $vm->getMounPoints()->additionalSize();
+        }
+        $vmModel->save();
+        //backup
+        $backup = $this->configuration()->isPermissionMountPointBackup() && $this->formData['backup'] == "on" ? 1 : null;
+        if ($backup != $hdd->getBackup())
+        {
+            $hdd->setBackup($backup);
+            $hdd->update();
+        }
+        //reboot
+        $vmId = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        if ($vm->isRunning() &&
+            !Job::waiting()->ofJob(RebootVmJob::class)->ofHostingId($this->getWhmcsParamByKey("serviceid"))->ofCustomId($vmId)->count())
+        {
+            queue(RebootVmJob::class, [], null, "hosting", $this->getWhmcsParamByKey("serviceid"),$vmId);
+        }
+        $resourceManager = new ResourceManager();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The hard disk has been updated successfully')
+            ->addData('createButtonStatus', $resourceManager->disk()->hasFreeTotal())
+            ->setCallBackFunction('pmToggleDiskButton');
+    }
+
+    public function delete()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vmModel  = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
+        $hdd =  $vm->getMounPoints()->findMountPointById($this->formData['id']);
+        if($hdd->getId() == "rootfs"){
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('The master hard disk cannot be deleted');
+        }
+        $hdd->delete();
+        foreach($vm->getMounPoints()->fetch() as $hd){
+            if(preg_match('/unused/', $hd->getId())){
+                $hd->delete();
+                break;
+            }
+        }
+        sleep(1);
+        $vmModel->disks = $vm->getMounPoints()->additionalSize();
+        $vmModel->save();
+        $resourceManager = new ResourceManager();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The hard disk has been deleted successfully')
+            ->addData('createButtonStatus', $resourceManager->disk()->hasFreeTotal())
+            ->setCallBackFunction('pmToggleDiskButton');
+    }
+
+
+}

+ 81 - 0
app/UI/MountPoint/Validators/DiskSizeValidator.php

@@ -0,0 +1,81 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Validators;
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+class DiskSizeValidator extends BaseValidator
+{
+    protected $minValue = 0;
+    protected $maxValue = 0;
+    protected $required = true;
+
+    public function __construct( $required = true)
+    {
+        $this->required = $required;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        $resurceManager = new ResourceManager();
+        $diskId = $additionalData->get('formData')['id'];
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $size = $vm->getMounPoints()->findMountPointById($diskId)->getGb();
+        $diskResource =    $resurceManager ->disk();
+        $diskResource->setUsed($diskResource->getUsed() - $size);
+        $this->maxValue = $diskResource->free();
+        $this->minValue =  $diskResource->getMin();
+
+        if(preg_match("/\./", $data)){
+            $this->addValidationError('PleaseProvideANumericValueBetween', false, ['minValue' => $this->minValue, 'maxValue' => $this->maxValue]);
+            return false;
+        }
+        if (is_numeric($data) && $this->minValue === 0 && $this->maxValue === 0)
+        {
+            return true;
+        }
+        //Min & Max
+        if (is_numeric($data) && $this->minValue <= ((int)$data) && ((int)$data) <= $this->maxValue)
+        {
+            return true;
+        }
+        //Min
+        else
+        {
+            if (is_numeric($data) && !is_numeric($this->maxValue) && $this->minValue <= ((int)$data))
+            {
+                return true;
+            }
+        }
+
+        if ($this->minValue === $this->maxValue)
+        {
+            $this->addValidationError('PleaseProvideANumericValue');
+
+            return false;
+        }
+
+        if (is_numeric($this->minValue) && is_numeric($this->maxValue))
+        {
+            $this->addValidationError('PleaseProvideANumericValueBetween', false, ['minValue' => $this->minValue, 'maxValue' => $this->maxValue]);
+        }
+        else
+        {
+            if (is_numeric($this->minValue) && !is_numeric($this->maxValue))
+            {
+                $this->addValidationError('PleaseProvideANumericValueFrom', false, ['minValue' => $this->minValue]);
+            }
+        }
+
+
+        return false;
+    }
+
+}

+ 37 - 0
app/UI/Network/Buttons/CreateButton.php

@@ -0,0 +1,37 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Modals\CreateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+/**
+ * @deprecated
+ */
+class CreateButton extends ButtonCreate implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createButton');
+        $this->initLoadModalAction(new CreateModal());
+    }
+
+}

+ 42 - 0
app/UI/Network/Buttons/DeleteButton.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Buttons;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+/**
+ * @deprecated
+ */
+class DeleteButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('deleteButton');
+        $this->switchToRemoveBtn();
+        $this->setDisableByColumnValue("bridge", $this->configuration()->getBridge());
+        $this->initLoadModalAction(new DeleteModal());
+    }
+
+}

+ 38 - 0
app/UI/Network/Buttons/InfoButton.php

@@ -0,0 +1,38 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Buttons;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Modals\InfoModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Modals\UpdateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class InfoButton extends ButtonDataTableModalAction implements ClientArea
+{
+    protected $icon = 'lu-btn__con lu-zmdi lu-zmdi-info-outline';
+
+    public function initContent()
+    {
+        $this->initIds('infoNetworkButton');
+        $this->initLoadModalAction(new InfoModal());
+    }
+
+}

+ 53 - 0
app/UI/Network/Forms/CreateForm.php

@@ -0,0 +1,53 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Providers\NetworkProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+/**
+ * @deprecated
+ */
+class CreateForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('createForm');
+        $this->setFormType('create');
+        $this->setProvider(new NetworkProvider());
+        $this->setConfirmMessage('confirmCreate');
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+
+    private function initFields()
+    {
+        //bridge
+        $field = new Hidden('bridge');
+        $this->addField($field);
+    }
+}

+ 52 - 0
app/UI/Network/Forms/DeleteForm.php

@@ -0,0 +1,52 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Providers\NetworkProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+/**
+ * @deprecated
+ */
+class DeleteForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteForm');
+        $this->setFormType('delete');
+        $this->setProvider(new NetworkProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDelete');
+        $this->addField(new Hidden("id"));
+    }
+
+}

+ 38 - 0
app/UI/Network/Modals/CreateModal.php

@@ -0,0 +1,38 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Forms\CreateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmSuccess;
+
+/**
+ * @deprecated
+ */
+class CreateModal extends ModalConfirmSuccess implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createModal');
+        $this->addForm(new CreateForm());
+    }
+
+}

+ 37 - 0
app/UI/Network/Modals/DeleteModal.php

@@ -0,0 +1,37 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+/**
+ * @deprecated
+ */
+class DeleteModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteModal');
+        $this->addForm(new DeleteForm());
+    }
+
+}

+ 68 - 0
app/UI/Network/Modals/InfoModal.php

@@ -0,0 +1,68 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Modals;
+
+use MGProvision\Proxmox\v2\models\Kvm;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Forms\InfoForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ModalActionButtons\BaseCancelButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class InfoModal extends  BaseEditModal implements ClientArea
+{
+
+    use ProductService;
+    use ApiService;
+
+    public function initContent()
+    {
+        $this->initIds('infoNetworkModal');
+        $networkId = $this->getRequestValue('actionElementId');
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        foreach ($vm->getNetworkDevices() as $nd)
+        {
+            if($nd->getId() != $networkId){
+                continue;
+            }
+            if($vm instanceof  Kvm){
+                $ipConfig = $vm->getIpConfig()->findByNetworkId($nd->getId())->fetch()[0];
+            }
+            if ($ipConfig)
+            {
+                $this->customTplVars['network'] = array_merge($nd->getAttributes(), $ipConfig->getAttributes());
+            }else{
+                $this->customTplVars['network'] =  $nd->getAttributes();
+            }
+            break;
+        }
+    }
+
+    protected function initActionButtons()
+    {
+        if (!empty($this->actionButtons))
+        {
+            return $this;
+        }
+        $this->addActionButton(new BaseCancelButton());
+        return $this;
+    }
+}

+ 155 - 0
app/UI/Network/Pages/NetworkLxcDataTable.php

@@ -0,0 +1,155 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Buttons\InfoButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Buttons\MailtoSwitchButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Buttons\RestoreButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class NetworkLxcDataTable extends DataTable implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    protected $id = 'networkDataTable';
+    protected $title = 'networkLxcDataTable';
+
+    public function initContent()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+
+        $this->unsetShowTitle();
+        //Info
+        $this->addActionButton(new InfoButton());
+    }
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('id'))->setSearchable(true, "string")->setOrderable('ASC'))
+            ->addColumn((new Column('name'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('firewall'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('hwaddr'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('ip'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('gw'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('rate'))->setSearchable(true)->setOrderable());
+    }
+
+
+    public function replaceFieldFirewall($key, $row)
+    {
+        if ($row['firewall'])
+        {
+            return '<span class="lu-label lu-label--success lu-label--status">' . sl('lang')->tr("Active") . '</span>';
+        }
+        return '<span class="lu-label lu-label--danger lu-label--status">' . sl('lang')->tr("Disabled") . '</span>';
+    }
+
+    public function replaceFieldIp($key, $row)
+    {
+        if (!$row['ip'] && !$row['ip6'])
+        {
+            return '-';
+        }
+        $ip = [];
+        if ($row['ip'] && $row['cidr'])
+        {
+            $ip[] = sprintf("%s/%s", $row['ip'], $row['cidr']);
+        }
+        else
+        {
+            if ($row['ip'])
+            {
+                $ip[] = $row['ip'];
+            }
+        }
+        if ($row['ip6'] && $row['cidr6'])
+        {
+            $ip[] = sprintf("%s/%s", $row['ip6'], $row['cidr6']);
+        }
+        else
+        {
+            if ($row['ip6'])
+            {
+                $ip[] = $row['ip6'];
+            }
+        }
+        return implode("<br/>", $ip);
+    }
+
+    public function replaceFieldGw($key, $row)
+    {
+        if ($row['gw'] && $row['gw6'])
+        {
+            return sprintf('%s<br>%s', $row['gw'], $row['gw6']);
+        }
+        if ($row['gw'])
+        {
+            return $row['gw'];
+        }
+        if ($row['gw6'])
+        {
+            return $row['gw6'];
+        }
+        return "-";
+    }
+
+    public function replaceFieldTag($key, $row)
+    {
+        if ($row['tag'])
+        {
+            return $row['tag'];
+        }
+        return '-';
+    }
+
+    public function replaceFieldRate($key, $row)
+    {
+        if (isset($row['rate']))
+        {
+            return sprintf('%s MB/s %s (Mbps)', $row['rate'], $row['rate'] * 8);
+        }
+        return sl('lang')->abtr("Unlimited");
+    }
+
+    protected function loadData()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $data = [];
+        foreach ( $vm->getNetworkDevices() as $nd)
+        {
+            $data[] = $nd->getAttributes();
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setDefaultSorting("id", 'ASC');
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+
+}

+ 158 - 0
app/UI/Network/Pages/NetworkQemuDataTable.php

@@ -0,0 +1,158 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Buttons\InfoButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Buttons\RestoreButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class NetworkQemuDataTable extends DataTable implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+    protected $id = 'networkDataTable';
+    protected $title = 'networkQemuDataTable';
+
+    public function initContent()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $this->unsetShowTitle();
+        //Info
+        $this->addActionButton(new InfoButton());
+    }
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('id'))->setSearchable(true, "string")->setOrderable('ASC'))
+            ->addColumn((new Column('firewall'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('macAddress'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('ip'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('gw'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('rate'))->setSearchable(true)->setOrderable());
+    }
+
+    public function replaceFieldFirewall($key, $row)
+    {
+        if ($row['firewall'])
+        {
+            return '<span class="lu-label lu-label--success lu-label--status">' . sl('lang')->tr("Active") . '</span>';
+        }
+        return '<span class="lu-label lu-label--danger lu-label--status">' . sl('lang')->tr("Disabled") . '</span>';
+    }
+
+    public function replaceFieldTag($key, $row)
+    {
+        if ($row['tag'])
+        {
+            return $row['tag'];
+        }
+        return '-';
+    }
+
+    public function replaceFieldIp($key, $row)
+    {
+        if (!$row['ip'] && !$row['ip6'])
+        {
+            return '-';
+        }
+        $ip = [];
+        if ($row['ip'] && $row['cidr'])
+        {
+            $ip[] = sprintf("%s/%s", $row['ip'], $row['cidr']);
+        }
+        else
+        {
+            if ($row['ip'])
+            {
+                $ip[] = $row['ip'];
+            }
+        }
+        if ($row['ip6'] && $row['cidr6'])
+        {
+            $ip[] = sprintf("%s/%s", $row['ip6'], $row['cidr6']);
+        }
+        else
+        {
+            if ($row['ip6'])
+            {
+                $ip[] = $row['ip6'];
+            }
+        }
+        return implode("<br/>", $ip);
+    }
+
+    public function replaceFieldGw($key, $row)
+    {
+        if ($row['gw'] && $row['gw6'])
+        {
+            return sprintf('%s<br>%s', $row['gw'], $row['gw6']);
+        }
+        if ($row['gw'])
+        {
+            return $row['gw'];
+        }
+        if ($row['gw6'])
+        {
+            return $row['gw6'];
+        }
+        return "-";
+    }
+
+    public function replaceFieldRate($key, $row)
+    {
+        if (isset($row['rate']))
+        {
+            return sprintf('%s MB/s %s (Mbps)', $row['rate'], $row['rate'] * 8);
+        }
+        return sl('lang')->abtr("Unlimited");
+    }
+
+    protected function loadData()
+    {
+        $data = [];
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        foreach ( $vm->getNetworkDevices() as $nd)
+        {
+            $ipConfig =  $vm->getIpConfig()->findByNetworkId($nd->getId())->fetch()[0];
+            if ($ipConfig)
+            {
+                $data[] = array_merge($nd->getAttributes(), $ipConfig->getAttributes());
+            }
+            else
+            {
+                $data[] = $nd->getAttributes();
+            }
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setDefaultSorting("id", 'ASC');
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+
+}

+ 53 - 0
app/UI/Network/Pages/NetworkTab.php

@@ -0,0 +1,53 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Pages;
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Pages\BackupDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Pages\BackupRawDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Pages\BackupJobDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Pages\IpAddressDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Pages\NetworkLxcDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Pages\NetworkQemuDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Pages\VirtualInterfaceDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\TabsWidget\TabsWidget;
+
+class NetworkTab extends TabsWidget implements ClientArea
+{
+    use ProductService;
+
+    protected $id   = 'networkTab';
+    protected $name = 'networkTabName';
+    protected $title = 'networkTabTitle';
+
+
+    public function initContent()
+    {
+        $this->unsetShowTitle();
+
+        //Public Ips
+        /**
+         * @deprecated
+         * $this->addElement(new IpAddressDataTable());
+         */
+        //Virtual Network
+        if($this->configuration()->isPermissionVirtualNetwork())
+        {
+            $this->addElement(VirtualInterfaceDataTable::class);
+        }
+
+        //Interfaces
+        if ($this->configuration()->isQemu() && $this->configuration()->isPermissionNetwork())
+        {
+            $this->addElement(new NetworkQemuDataTable());
+        }
+        if ($this->configuration()->isLxc() && $this->configuration()->isPermissionNetwork())
+        {
+            $this->addElement(new NetworkLxcDataTable());
+        }
+
+    }
+}

+ 124 - 0
app/UI/Network/Providers/NetworkProvider.php

@@ -0,0 +1,124 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Providers;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+/**
+ * @deprecated
+ */
+class NetworkProvider extends BaseDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+    /**
+     * @var NetworkService
+     */
+    private $networkService;
+
+    public function read()
+    {
+        if ($this->actionElementId)
+        {
+            $this->data['id'] = $this->actionElementId;
+        }
+        $this->data['bridge'] = $this->configuration()->getPrivateBridge();
+    }
+
+    public function create()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        if ($vm->getNetworkDevices($this->configuration()->getPrivateBridge()))
+        {
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('Private network limit exceeded');
+        }
+        $this->networkService = new NetworkService();
+        if (!$this->networkService->hasPrivateIpAddress())
+        {
+            throw new \Exception("Private IP Addresses are not available.");
+        }
+        if ($this->configuration()->isLxc())
+        {
+            $this->lxc();
+        }
+        else
+        {
+            if ($this->configuration()->isQemu())
+            {
+                $this->qemu();
+            }
+        }
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Network Device has been created successfully')
+            ->addData('createButtonStatus', false)
+            ->setCallBackFunction('pmToggleButton');
+    }
+
+    private function lxc()
+    {
+        //Get Private IP Addresses
+        $ip = $this->networkService->getPrivateIpAddress();
+        $ip->vm_id = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        //Create network device
+        $this->networkService->addPrivate([$ip]);
+
+    }
+
+    private function qemu()
+    {
+        //Get Private IP Addresses
+        $ip = $this->networkService->getPrivateIpAddress();
+        $ip->vm_id = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        //Create network device
+        $this->networkService->addPrivate([$ip]);
+    }
+
+    public function update()
+    {
+    }
+
+    public function delete()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        if (!$vm->getNetworkDevices($this->configuration()->getPrivateBridge()))
+        {
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('Private network device not found');
+        }
+        $this->networkService = new NetworkService();
+        $this->networkService->deleteByNetworkId([$this->formData['id']]);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Network Device has been deleted successfully')
+            ->addData('createButtonStatus', true)
+            ->setCallBackFunction('pmToggleButton');
+    }
+
+
+}

+ 142 - 0
app/UI/Network/Templates/modals/infoModal.tpl

@@ -0,0 +1,142 @@
+{**********************************************************************
+* ProxmoxAddon product developed. (2017-11-16)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+**********************************************************************}
+
+{**
+* @author Sławomir Miśkowicz <slawomir@modulesgarden.com>
+*}
+<div class="lu-modal show lu-modal--{$rawObject->getModalSize()}" id="confirmationModal"
+     namespace="{$rawObject->getNamespace()}" index="{$rawObject->getId()}">
+    <div class="lu-modal__dialog">
+        <div class="lu-modal__content" id="mgModalContainer">
+            <div class="lu-modal__top lu-top">
+                <div class="lu-top__title lu-type-6">
+                    <span class="lu-text-faded lu-font-weight-normal">
+                {if $rawObject->isRawTitle()}{$rawObject->getRawTitle()}{elseif $rawObject->getTitle()}{$MGLANG->T('modal', $rawObject->getTitle())}{/if}
+            </span>
+                </div>
+                <div class="lu-top__toolbar">
+                    <button class="lu-btn lu-btn--xs lu-btn--default lu-btn--icon lu-btn--link lu-btn--plain closeModal"
+                            data-dismiss="lu-modal" aria-label="Close" @click='closeModal($event)'>
+                        <i class="lu-btn__icon lu-zmdi lu-zmdi-close"></i>
+                    </button>
+                </div>
+            </div>
+            <div class="lu-modal__body">
+                <div class="lu-col-md-12">
+                    <ul class="lu-list lu-list--info">
+                        <li class="lu-list__item">
+                            <span class="lu-list__item-title">{$MGLANG->tr('ID')}</span>
+                            <span class="lu-list__value"> {$customTplVars.network.id} </span>
+                        </li>
+                        {if $customTplVars.network.name}
+                            <li class="lu-list__item">
+                                <span class="lu-list__item-title">{$MGLANG->tr('Name')} </span>
+                                 <span class="lu-list__value"> {$customTplVars.network.name} </span>
+                            </li>
+                        {/if}
+                        <li class="lu-list__item">
+                            <span class="lu-list__item-title">{$MGLANG->tr('Bridge')}</span>
+                            <span class="lu-list__value">{$customTplVars.network.bridge}</span>
+                        </li>
+                        <li class="lu-list__item">
+                            <span class="lu-list__item-title">{$MGLANG->tr('Firewall')}</span>
+                            <span class="lu-list__value">
+                                {if $customTplVars.network.firewall}
+                                    <span class="lu-label lu-label--success lu-label--status">{$MGLANG->tr('Active')}</span>
+                                {else}
+                                    <span class="lu-label lu-label--danger lu-label--status">{$MGLANG->tr('Disabled')}</span>
+                                {/if}
+                            </span>
+                        </li>
+                        <li class="lu-list__item">
+                            <span class="lu-list__item-title">{$MGLANG->tr('MAC Address')}</span>
+                            <span class="lu-list__value">{$customTplVars.network.hwaddr} {$customTplVars.network.macAddress}</span>
+                        </li>
+                        <li class="lu-list__item">
+                            <span class="lu-list__item-title">{$MGLANG->tr('IP Address')}</span>
+                            <span class="lu-list__value">
+                                {if !$customTplVars.network.ip && !$customTplVars.network.ip6}
+                                    -
+                                {elseif $customTplVars.network.ip && $customTplVars.network.cidr }
+                                    {$customTplVars.network.ip}/{$customTplVars.network.cidr}
+                                    <br/>
+                                {elseif $customTplVars.network.ip }
+                                    {$customTplVars.network.ip}   <br/>
+                                {/if}
+                                {if $customTplVars.network.ip6 && $customTplVars.network.cidr6 }
+                                    {$customTplVars.network.ip6}/{$customTplVars.network.cidr6}
+                                {elseif $customTplVars.network.ip6}
+                                    {$customTplVars.network.ip6}
+                                {/if}
+                            </span>
+                        </li>
+                        <li class="lu-list__item">
+                            <span class="lu-list__item-title">{$MGLANG->tr('Gateway')}</span>
+                            <span class="lu-list__value">
+                                {if !$customTplVars.network.gw && !$customTplVars.network.gw6}
+                                    -
+                                {elseif $customTplVars.network.gw && $customTplVars.network.gw6}
+                                    {$customTplVars.network.gw}
+                                    <br/>
+                                    {$customTplVars.network.gw6}
+                                {else}
+                                    {$customTplVars.network.gw}
+                                    {$customTplVars.network.gw6}
+                                {/if}
+                            </span>
+                        </li>
+                        <li class="lu-list__item">
+                            <span class="lu-list__item-title">{$MGLANG->tr('Tag')}</span>
+                            <span class="lu-list__value">
+                                {if !$customTplVars.network.tag}
+                                    -
+                                {/if}
+                                {$customTplVars.network.tag}
+                            </span>
+                        </li>
+                        <li class="lu-list__item">
+                            <span class="lu-list__item-title">{$MGLANG->tr('Rate')}</span>
+                            <span class="lu-list__value">
+                                {if $customTplVars.network.rate}
+                                    {$customTplVars.network.rate} MB/s {$customTplVars.network.rate*8} (Mbps)
+                                {else}
+                                    {$MGLANG->tr('Unlimited')}
+                                {/if}
+                            </span>
+                        </li>
+                    </ul>
+                </div>
+
+            </div>
+            <div class="lu-modal__actions">
+                {foreach from=$rawObject->getActionButtons() item=actionButton}
+                    {$actionButton->getHtml()}
+                {/foreach}
+            </div>
+            {if ($isDebug eq true AND (count($MGLANG->getMissingLangs()) != 0))}{literal}
+                <div class="lu-modal__actions">
+                <div class="lu-row">
+            {/literal}{foreach from=$MGLANG->getMissingLangs() key=varible item=value}{literal}
+                <div class="lu-col-md-12"><b>{/literal}{$varible}{literal}</b> = '{/literal}{$value}{literal}';</div>
+            {/literal}{/foreach}{literal}
+                </div>
+                </div>
+            {/literal}{/if}
+        </div>
+    </div>
+</div>

+ 38 - 0
app/UI/Reinstall/Buttons/IsoInstallButton.php

@@ -0,0 +1,38 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Modals\IsoInstallModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class IsoInstallButton extends ButtonDataTableModalAction implements ClientArea, AdminArea
+{
+
+    protected $icon = 'lu-zmdi lu-zmdi-time-restore-setting';
+
+    public function initContent()
+    {
+        $this->initIds('isoInstallButton');
+        $this->initLoadModalAction(new IsoInstallModal());
+    }
+
+}

+ 38 - 0
app/UI/Reinstall/Buttons/TemplateInstallButton.php

@@ -0,0 +1,38 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Modals\TemplateInstallModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class TemplateInstallButton extends ButtonDataTableModalAction implements ClientArea, AdminArea
+{
+
+    protected $icon = 'lu-zmdi lu-zmdi-time-restore-setting';
+
+    public function initContent()
+    {
+        $this->initIds('templateInstallButton');
+        $this->initLoadModalAction(new TemplateInstallModal());
+    }
+
+}

+ 57 - 0
app/UI/Reinstall/Forms/IsoInstallForm.php

@@ -0,0 +1,57 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Providers\IsoInstallProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Helpers\AlertTypesConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+
+
+class IsoInstallForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+
+        $this->initIds('isoInstallForm');
+        $this->setFormType("processQemu");
+        $this->setProvider(new IsoInstallProvider());
+        $this->setInternalAlertMessage('confirmReinstall');
+        $this->setInternalAlertMessageType(AlertTypesConstants::DANGER);
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ["processQemu"];
+    }
+
+    private function initFields()
+    {
+        //entity id
+        $this->addField(new Hidden("id"));
+        //secondaryIsoImage
+        $this->addField(new Select('secondaryIsoImage')); 
+
+    }
+}

+ 70 - 0
app/UI/Reinstall/Forms/TemplateInstallForm.php

@@ -0,0 +1,70 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Providers\TemplateInstallProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\PasswordValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Helpers\AlertTypesConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+
+class TemplateInstallForm extends BaseForm implements ClientArea, AdminArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function initContent()
+    {
+
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $this->initIds('templateInstallForm');
+        $this->setFormType("process" . ucfirst($vm->getVirtualization()));
+        $this->setProvider(new TemplateInstallProvider());
+        $this->setInternalAlertMessage('confirmReinstall');
+        $this->setInternalAlertMessageType(AlertTypesConstants::DANGER);
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ["processQemu", "processLxc"];
+    }
+
+    private function initFields()
+    {
+
+        //entity id
+        $this->addField(new Hidden("id"));
+        //password
+        $field = new Text('password');
+        $field->setDescription("tip");
+        $field->notEmpty();
+        $field->addValidator(new PasswordValidator(true, 5));
+        $this->addField($field);
+
+    }
+}

+ 35 - 0
app/UI/Reinstall/Modals/IsoInstallModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Forms\IsoInstallForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class IsoInstallModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('isoInstallModal');
+        $this->addForm(new IsoInstallForm());
+    }
+
+}

+ 36 - 0
app/UI/Reinstall/Modals/TemplateInstallModal.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Forms\TemplateInstallForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class TemplateInstallModal extends ModalConfirmDanger implements ClientArea, AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('templateInstallModal');
+        $this->addForm(new TemplateInstallForm());
+    }
+
+}

+ 47 - 0
app/UI/Reinstall/Pages/GraphsTab.php

@@ -0,0 +1,47 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages\CpuGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages\DiskGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages\MemoryGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Graph\Pages\NetworkGraph;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\TabsWidget\TabsWidget;
+
+class GraphsTab extends TabsWidget implements ClientArea, AdminArea
+{
+    protected $id = 'graphsTab';
+    protected $name = 'graphsTab';
+    protected $title = 'graphsTabTitle';
+    protected $vueComponent = true;
+
+    public function initContent()
+    {
+        $this->unsetShowTitle();
+
+        $this->addElement(CpuGraph::class)
+        ->addElement(DiskGraph::class)
+        ->addElement(MemoryGraph::class)
+        ->addElement(NetworkGraph::class);
+    }
+}

+ 42 - 0
app/UI/Reinstall/Pages/IsoDataTable.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons\BackupSwitchButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons\CreateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons\RestoreButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+
+class IsoDataTable extends DataTable implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+    use IsoTrait;
+
+    protected $id = 'isoDataTable';
+    protected $title = 'isoDataTable';
+
+
+}

+ 38 - 0
app/UI/Reinstall/Pages/IsoRawDataTable.php

@@ -0,0 +1,38 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\RawDataTable\RawDataTable;
+
+class IsoRawDataTable extends RawDataTable implements ClientArea, AdminArea
+{
+    use ApiService;
+    use ProductService;
+    use IsoTrait;
+
+    protected $id = 'isoDataTable';
+    protected $title = 'isoDataTable';
+
+
+}

+ 72 - 0
app/UI/Reinstall/Pages/IsoTrait.php

@@ -0,0 +1,72 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons\IsoInstallButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+trait IsoTrait
+{
+
+
+    public function initContent()
+    {
+        $this->setInternalAlertMessage("Select the template for reinstallation. If you proceed, all data located on the virtual machine will be lost.");
+
+        $this->unsetShowTitle();
+        //Install
+        $this->addActionButton(new IsoInstallButton());
+    }
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('name'))->setSearchable(true, "string")->setOrderable('ASC'));
+    }
+
+    public function replaceFieldName($key, $row)
+    {
+        return sl("lang")->abtr("template", $row[$key]);
+    }
+
+    protected function loadData()
+    {
+        $data = [];
+        foreach ($this->isoRepository()->fetch() as $entity)
+        {
+
+            if ($this->configuration()->isPermissionIsoImages() && !in_array($entity->getVolid(), $this->configuration()->getPermissionIsoImages()))
+            {
+                continue;
+            }
+            $data[] = [
+                "id"   => $entity->getVolid(),
+                "name" => $entity->getFriendlyName(),
+            ];
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setDefaultSorting("name", 'ASC');
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+}

+ 42 - 0
app/UI/Reinstall/Pages/ReinstallTab.php

@@ -0,0 +1,42 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\TabsWidget\TabsWidget;
+
+class ReinstallTab extends TabsWidget implements ClientArea, AdminArea
+{
+    protected $id = 'reinstallTab';
+    protected $name = 'reinstallTab';
+    protected $title = 'reinstallTabTitle';
+    protected $vueComponent = true;
+
+    public function initContent()
+    {
+        $this->unsetShowTitle();
+
+        $this->addElement(new TemplateRawDataTable());
+        $this->addElement(new IsoRawDataTable());
+
+    }
+}

+ 40 - 0
app/UI/Reinstall/Pages/TemplateDataTable.php

@@ -0,0 +1,40 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons\BackupSwitchButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons\CreateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons\RestoreButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+
+class TemplateDataTable extends DataTable implements ClientArea, AdminArea
+{
+    use TemplateTrait; 
+
+    protected $id = 'templatDataTable';
+    protected $name = 'templatDataTable';
+    protected $title = 'templatDataTableTitle';
+
+
+}

+ 19 - 0
app/UI/Reinstall/Pages/TemplateRawDataTable.php

@@ -0,0 +1,19 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\RawDataTable\RawDataTable;
+
+class TemplateRawDataTable extends RawDataTable implements ClientArea, AdminArea
+{
+    use TemplateTrait;
+
+    protected $id = 'templatDataTable';
+    protected $title = 'templatDataTable';
+
+
+}

+ 116 - 0
app/UI/Reinstall/Pages/TemplateTrait.php

@@ -0,0 +1,116 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages;
+
+
+use MGProvision\Proxmox\v2\repository\ClusterResourcesRepository;
+use MGProvision\Proxmox\v2\repository\FileRepository;
+use MGProvision\Proxmox\v2\repository\StorageRepository;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Buttons\TemplateInstallButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+trait TemplateTrait
+{
+    use ApiService;
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->setInternalAlertMessage("Select the template for reinstallation. If you proceed, all data located on the virtual machine will be lost.");
+
+        $this->unsetShowTitle();
+        //Update
+        $this->addActionButton(new TemplateInstallButton());
+    }
+
+    protected function loadHtml()
+    {
+        //name
+        $this->addColumn((new Column('name'))->setSearchable(true, "string")->setOrderable('ASC'));
+        //description
+        if($this->configuration()->isQemu()){
+            $this->addColumn((new Column('description'))->setSearchable(true, "string"));
+        }
+    }
+
+    public function replaceFieldName($key, $row)
+    {
+        return sl("lang")->abtr("template", $row[$key]);
+    }
+
+    protected function loadData()
+    {
+        $data           = [];
+        $fileRepository = new FileRepository();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $nodes          = [$vm->getNode()];
+        //LXC
+        if ($this->configuration()->isLxc())
+        {
+            $storageRepository = new StorageRepository();
+            $storageRepository->findByNodes($nodes);
+            $storageRepository->findEnabed();
+            $storages = $storageRepository->fetchAsArray();
+            $fileRepository->findByNodes($nodes)
+                ->findByStorages($storages);
+            $fileRepository->findByContent('vztmpl');
+            foreach ($fileRepository->fetch() as $entity)
+            {
+                if ($this->configuration()->isPermissionOsTemplates() && !in_array($entity->getVolid(), $this->configuration()->getPermissionOsTemplates()))
+                {
+                    continue;
+                }
+
+                $data[] = [
+                    "id"   => $entity->getVolid(),
+                    "name" => $entity->getFriendlyName(),
+
+                ];
+            }
+        }//KVM
+        else
+        {
+            if ($this->configuration()->isQemu())
+            {
+                $clusterResurces = new ClusterResourcesRepository();
+                $clusterResurces->findKvmTemplate();
+                if (!$this->configuration()->isOsTemplatesInAllNodes())
+                {
+                    $clusterResurces->findByNodes($vm->getNode());
+                }
+
+                foreach ($clusterResurces->fetchWithUniqueNames($vm->getNode()) as $entity)
+                {
+                    if ($entity->isCustom() && !$entity->matchName($this->getWhmcsParamByKey("serviceid")))
+                    {
+                        continue;
+                    }
+                    if ($this->configuration()->isPermissionOsTemplates() && !in_array($entity->getName(), $this->configuration()->getPermissionOsTemplates()))
+                    {
+                        continue;
+                    }
+                    $id     = "{$entity->getNode()}/{$entity->getVmid()}";
+                    $description = $entity->getVm()->config()['description'];
+                    if(!$description){
+                        $description = '-';
+                    }
+                    $data[] = [
+                        "id" => $id,
+                        "name"     => $entity->getName(),
+                        'description' =>  sl('lang')->abtr('template_desc' ,$description)
+                    ];
+                }
+            }
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setDefaultSorting("name", 'ASC');
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+}

+ 174 - 0
app/UI/Reinstall/Providers/IsoInstallProvider.php

@@ -0,0 +1,174 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Providers;
+
+
+use MGProvision\Proxmox\v2\repository\FileRepository;
+use MGProvision\Proxmox\v2\repository\SnapshotRepository;
+use MGProvision\Proxmox\v2\repository\StorageRepository;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\HighAvailabilityClusterService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\IpSetIpFilterService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class IsoInstallProvider extends BaseDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+    /**
+     * @var HighAvailabilityClusterService
+     */
+    private $highAvailabilityClusterService;
+    /**
+     * @var IpSetIpFilterService
+     */
+    private $ipSetIpFilterService;
+
+    public function read()
+    {
+        if ($this->actionElementId)
+        {
+            $this->data['id'] = $this->actionElementId;
+        }
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $storageRepository = new StorageRepository();
+        $storageRepository->findByNodes([$vm->getNode()])
+             ->findEnabed();
+        $storages            = $storageRepository->fetchAsArray();
+        $isoRepository = new FileRepository();
+        $isoRepository->findByNodes([$vm->getNode()])
+                      ->findByStorages($storages);
+        $isoRepository->findIso();
+        $this->availableValues['secondaryIsoImage'][0] = sl('lang')->abtr("None");
+        foreach ($isoRepository->fetch() as $entity)
+        {
+            if ($this->configuration()->isPermissionSecondaryIsoImages() && !in_array($entity->getVolid(), $this->configuration()->getPermissionSecondaryIsoImages()))
+            {
+                continue;
+            }
+            $this->availableValues['secondaryIsoImage'][$entity->getVolid()] = sl('lang')->abtr( "template", $entity->getFriendlyName());
+        }
+    }
+
+    public function update()
+    {
+
+    }
+
+    private function initServices()
+    {
+        $this->highAvailabilityClusterService = new HighAvailabilityClusterService();
+        $this->ipSetIpFilterService           = new IpSetIpFilterService();
+    }
+
+    public function processQemu()
+    {
+        $this->initServices();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        //Empyty template
+        if (!$this->formData['id'])
+        {
+            throw new \Exception ("Provide OS Template");
+        }
+        $spanshootRepostiory = new SnapshotRepository();
+        $spanshootRepostiory->findByVm($vm)
+            ->ignoreCurrent(true);
+        if ($spanshootRepostiory->count())
+        {
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('Remove the snapshots before reinstallation.');
+        }
+        \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->data['osTemplate'] =   null;
+        \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->save();
+        //ha
+        if ($this->highAvailabilityClusterService->exist())
+        {
+            $this->highAvailabilityClusterService->delete();
+        }
+        //stop
+        if ($vm->isRunning())
+        {
+            $vm->stop();
+        }
+        //Remove cloud-init drive
+        foreach ($vm->config() as $id => $v)
+        {
+            if (preg_match('/cloudinit/', $v))
+            {
+                $vm->deleteConfig($id);
+            }
+        }
+        //insert unattended iso
+        $cdroms = $vm->getCdRom()->fetch();
+        if(!$cdroms[0] || ($this->formData['secondaryIsoImage'] && !$cdroms[1])){
+            throw new \MGProvision\Proxmox\v2\ProxmoxApiException("CD-ROM volume not found");
+        }
+        $cdroms[0]->setLocation($this->formData['id'])->update();
+        //secondaryIsoImage
+        if($this->formData['secondaryIsoImage'] ){
+            $cdroms[1]->setLocation($this->formData['secondaryIsoImage'])->update();
+        }
+        //remove hard drive and recreate a new one, (the drive have to be empty)
+        $masterHdd = $vm->getMasterHardDisk();
+        $masterHdd->delete();
+        sleep(1);
+        //Delete Unused Disk
+        foreach ($vm->config(true) as $id => $v)
+        {
+            if (preg_match('/unused/', $id))
+            {
+                $vm->deleteConfig($id);
+            }
+        }
+        //create new disk
+        $bytes = $masterHdd->getBytes();
+        $size  = (int)$bytes / pow(1024, 3);
+        $masterHdd->setSize($size);
+        $masterHdd->create();
+        sleep(1);
+        //Boot disk
+        $vm->updateConfig(['bootdisk' => $masterHdd->getId()]);
+        //set bootorder to disk, cdrom, network (if cdrom would be first, the installer will run on every boot -> bootloop)
+        $vm->changeBootOrder('cdn');
+        //ipset
+        if ($this->configuration()->isIpsetIpFilter())
+        {
+            $this->ipSetIpFilterService->create();
+        }
+        //HA
+        if ($this->configuration()->getClusterState())
+        {
+            $this->highAvailabilityClusterService->create();
+        }
+        //start vps
+        $vm->start();
+        //show message that installation is now processing. The login information will be available in the noVNC console after installation.
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('Installation is now processing. The login information will be available in the noVNC console.');
+
+    }
+
+}

+ 152 - 0
app/UI/Reinstall/Providers/TemplateInstallProvider.php

@@ -0,0 +1,152 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Providers;
+
+
+use MGProvision\Proxmox\v2\models\Kvm;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Reinstall\BackupVmJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Reinstall\CreateVmJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Reinstall\DeleteVmJob;
+use ModulesGarden\ProxmoxAddon\App\Libs\Format;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\HostingService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\Core\Queue\Models\Job;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+
+class TemplateInstallProvider extends BaseDataProvider implements ClientArea, AdminArea
+{
+    use ProductService;
+    use ApiService;
+    use HostingService;
+
+    public function read()
+    {
+        if ($this->actionElementId)
+        {
+            $this->data['id']       = $this->actionElementId;
+            $this->data['password'] =  \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->getPassword();
+        }
+    }
+
+    public function update()
+    {
+
+    }
+
+    public function processLxc()
+    {
+        if($this->jobExist()){
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate("Task 'Reinstall' already exist");
+        }
+        $arguments = [
+            'hostingId'  => $this->getWhmcsParamByKey('serviceid'),
+            "osTemplate" => $this->formData['id'],
+            "password"   => encrypt(html_entity_decode($this->formData['password'],ENT_QUOTES)),
+        ];
+        \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->data['osTemplate'] =   $this->formData['id'];
+        \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->save();
+        $vmId = $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        if ($this->configuration()->isBackupVmBeforeReinstall())
+        {
+            $job = queue(BackupVmJob::class, $arguments, null, "hosting", $this->getWhmcsParamByKey("serviceid"),$vmId);
+        }
+        $job = queue(DeleteVmJob::class, $arguments, $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"),$vmId);
+        $job = queue(CreateVmJob::class, $arguments, $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"),$vmId);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The virtual server is being reinstalled')
+            ->setCallBackFunction('mgLocationReload');
+
+    }
+
+    private function jobExist(){
+        $vmId = $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        return Job::where("job", CreateVmJob::class. '@handle')->whereIn("status", ['waiting', "running", ""])
+            ->where("rel_id", $this->getWhmcsParamByKey("serviceid"))
+            ->where("rel_type", "hosting")
+                ->where("custom_id", $vmId)
+                ->count() > 0;
+    }
+
+    public function processQemu()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vmId =  \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        if($this->jobExist()){
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate("Task 'Reinstall' already exist");
+        }
+        list($node, $vmid) = explode("/", $this->formData['id']);
+        $vmTemplate = new Kvm($node, $vmid);
+        $vmTemplate ->setApi($this->api());
+        $templateSize =  $vmTemplate->getMasterHardDisk()->getBytes();
+        if ($templateSize > $vm->getMasterHardDisk()->getBytes())
+        {
+            sl("lang")->addReplacementConstant("size", Format::convertBytes($templateSize));
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('OS Template require disk size :size:');
+        }
+        \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->data['osTemplate'] =  $vmTemplate->status()['name'];
+        \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->save();
+        $arguments = [
+            'hostingId'  => $this->getWhmcsParamByKey('serviceid'),
+            "osTemplate" => $this->formData['id'],
+            "password"   => encrypt(html_entity_decode($this->formData['password'],ENT_QUOTES)),
+        ];
+        //automaticaly configure administartor username for window
+        $this->setHostingId($this->getWhmcsParamByKey('serviceid'));
+        if( $this->configuration()->isAgent() &&
+            $this->configuration()->isAgentPassword() &&
+            preg_match('/w/', $vmTemplate ->config()['ostype'])){
+            $arguments['username'] =  'Administrator';
+        }
+        elseif($this->configuration()->isQemu() && $this->configuration()->getCiuser()){
+            $arguments['username'] = $this->configuration()->getCiuser();
+        }
+        if ($this->configuration()->isBackupVmBeforeReinstall())
+        {
+            $job = queue(BackupVmJob::class, $arguments, null, "hosting", $this->getWhmcsParamByKey("serviceid"),$vmId);
+        }
+        $job = queue(DeleteVmJob::class, $arguments, $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"),$vmId);
+        $job = queue(CreateVmJob::class, $arguments, $job->id, "hosting", $this->getWhmcsParamByKey("serviceid"),$vmId);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The virtual server is being reinstalled')
+            ->setCallBackFunction('mgLocationReload');
+
+    }
+
+    public function iso()
+    {
+
+    }
+
+}

+ 36 - 0
app/UI/ServiceGraph/Pages/BaseGraph.php

@@ -0,0 +1,36 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceGraph\Pages;
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Line;
+use Illuminate\Database\Capsule\Manager as DB;
+
+class BaseGraph extends Line implements ClientArea, AdminArea
+{
+    use ProductService;
+    protected $graphSettingsEnabled = false;
+    protected $graphHeight = 70;
+    protected $graphWidth = 200;
+    protected $showTitle = false;
+    protected $title = '';
+    protected $legend = [
+        'display'  => false,
+        'position' => 'top'
+    ];
+
+    protected function  rrdDataQuery(){
+        $hi = (int) $this->getWhmcsParamByKey('serviceid');
+        $now = new \DateTime();
+        $now->modify('-1 hours');
+        $since = $now->format("Y-m-d H:i:s");
+        //Query
+        return DB::select("SELECT AVG(diskread) AS diskread, AVG(diskwrite) AS diskwrite, AVG(cpu) AS cpu, AVG(maxcpu) AS maxcpu , AVG(mem) AS mem, AVG(maxmem) AS maxmem, AVG(netin) AS netin, AVG(netout) AS netout, `date` FROM (SELECT id, hosting_id, vm_id, (diskread), (diskwrite), (cpu), (maxcpu), (mem), (maxmem), (netin), (netout), DATE_FORMAT(FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(time) / 300) * 300), '%Y-%m-%d %H:%i') as `date` FROM `ProxmoxAddon_RrdData` 
+        WHERE hosting_id = {$hi} AND `time` >= '{$since}'
+) as x GROUP BY date ORDER BY `date` ASC");
+    }
+}

+ 100 - 0
app/UI/ServiceGraph/Pages/ServiceCpuGraph.php

@@ -0,0 +1,100 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Oct 1, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceGraph\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Models\RrdData;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Line;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Models\DataSet;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+/**
+ * Class ServiceCpuGraph
+ * @package ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceGraph\Pages
+ */
+class ServiceCpuGraph extends BaseGraph
+{
+
+    protected $id = 'serviceCpuGraph';
+    protected $name = 'serviceCpuGraph';
+
+    /**
+     *
+     */
+    public function initContent()
+    {
+        $this->unsetShowTitle();
+        //yAxes
+        $this->updateChartScale('yAxes', [
+            [
+                'scaleLabel' => [
+                    'display'     => true,
+                    'labelString' => sl('lang')->tr("CPU %")
+                ],
+                'ticks'      => [
+                    'beginAtZero' => true,
+                    'fontSize' => 10
+                ],
+            ]]);
+        //xAxes
+        $this->updateChartScale('xAxes', [
+            [
+                'display' => false,
+            ]]);
+        //Tooltip
+        $this->updateChartOption('tooltips', [
+            'callbacks' => [
+                'label' => 'mgTooltipCpu'
+            ]
+        ]);
+    }
+
+    /**
+     * @throws \Exception+
+     */
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        $labels   = [];
+        $dataSets = [
+            'cpu' => []
+        ];
+        foreach ($this->rrdDataQuery() as $rrd)
+        {
+            $labels[]             = $rrd->date;
+            $dataSets['cpu'][] = (isset($rrd->cpu) ? (float)$rrd->cpu : 0) * 100;
+        }
+        //Labels
+        $this->setLabels($labels);
+        //CPU Usage
+        $lang    = sl('lang');
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('CPU Usage'))
+            ->setData($dataSets['cpu'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => "rgba(174, 198, 57, 0.79)",
+                "borderColor"     => "rgba(174, 198, 57, 1)"
+            ]);
+        $this->addDataSet($dataSet);
+    }
+}

+ 102 - 0
app/UI/ServiceGraph/Pages/ServiceDiskGraph.php

@@ -0,0 +1,102 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Oct 1, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceGraph\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Models\RrdData;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Line;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Models\DataSet;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class ServiceDiskGraph extends BaseGraph
+{
+    use ProductService;
+
+    protected $id = 'serviceDiskGraph';
+    protected $name = 'serviceDiskGraph';
+
+    public function initContent()
+    {
+        $this->updateChartScale('yAxes', [
+            [
+                'scaleLabel' => [
+                    'display'     => true,
+                    'labelString' => sl('lang')->tr('Disk')
+                ],
+                'ticks'      => [
+                    'callback'    => 'mgBytesToSize',
+                    'beginAtZero' => true,
+                    'fontSize' => 10
+                ],
+            ]]);
+        //xAxes
+        $this->updateChartScale('xAxes', [
+            [
+                'display' => false,
+            ]]);
+
+        $this->updateChartOption('tooltips', [
+            'callbacks' => [
+                'label' => 'mgTooltipCallbackForDisk'
+            ]
+        ]);
+    }
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        $labels   = [];
+        $dataSets = [
+            'diskread'  => [],
+            'diskwrite' => [],
+        ];
+        foreach ($this->rrdDataQuery() as $rrd)
+        {
+            $labels[]             = $rrd->date;
+            $dataSets['diskread'][]  = isset($rrd->diskread) ? $rrd->diskread : 0;
+            $dataSets['diskwrite'][] = isset($rrd->diskwrite) ? $rrd->diskwrite : 0;
+        }
+        //Labels
+        $this->setLabels($labels);
+        //Memory
+        $lang    = sl('lang');
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Disk Read'))
+            ->setData($dataSets['diskread'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(174, 198, 57, 0.79)',
+                "borderColor"     => 'rgba(174, 198, 57, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+        //Total
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Disk Write'))
+            ->setData($dataSets['diskwrite'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(39, 133, 134, 0.91)',
+                "borderColor"     => 'rgba(39, 133, 134, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+    }
+
+}

+ 18 - 0
app/UI/ServiceGraph/Pages/ServiceGraphs.php

@@ -0,0 +1,18 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceGraph\Pages;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Container;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class ServiceGraphs extends Container implements ClientArea
+{
+    public function initContent()
+    {
+        $this->addElement(ServiceCpuGraph::class);
+        $this->addElement(ServiceMemoryGraph::class);
+        $this->addElement(ServiceNetworkGraph::class);
+    }
+}

+ 101 - 0
app/UI/ServiceGraph/Pages/ServiceMemoryGraph.php

@@ -0,0 +1,101 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Oct 1, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceGraph\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Models\RrdData;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Line;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Models\DataSet;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+
+class ServiceMemoryGraph extends BaseGraph
+{
+    protected $id = 'serviceMemoryGraph';
+    protected $name = 'serviceMemoryGraph';
+
+
+    public function initContent()
+    {
+        $this->updateChartScale('yAxes', [
+            [
+                'scaleLabel' => [
+                    'display'     => true,
+                    'labelString' => sl('lang')->tr('Memory')
+                ],
+                'ticks'      => [
+                    'callback'    => 'mgBytesToSize',
+                    'beginAtZero' => true,
+                    'fontSize' => 10
+                ],
+            ]]);
+        //xAxes
+        $this->updateChartScale('xAxes', [
+            [
+                'display' => false,
+            ]]);
+
+        $this->updateChartOption('tooltips', [
+            'callbacks' => [
+                'label' => 'mgTooltipCallbackForMemory'
+            ]
+        ]);
+    }
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        $labels   = [];
+        $dataSets = [
+            'maxmem' => [],
+        ];
+        foreach ($this->rrdDataQuery() as $rrd)
+        {
+            $labels[]             = $rrd->date;
+            $dataSets['mem'][]    = isset($rrd->mem) ? $rrd->mem : 0;
+            $dataSets['maxmem'][] = isset($rrd->maxmem) ? $rrd->maxmem : 0;
+        }
+        //Labels
+        $this->setLabels($labels);
+        //Memory
+        $lang    = sl('lang');
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Memory Usage'))
+            ->setData($dataSets['mem'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(39, 133, 134, 0.91)',
+                "borderColor"     => 'rgba(39, 133, 134, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+        //Total
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Total'))
+            ->setData($dataSets['maxmem'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(174, 198, 57, 0.79)',
+                "borderColor"     => 'rgba(174, 198, 57, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+    }
+
+}

+ 102 - 0
app/UI/ServiceGraph/Pages/ServiceNetworkGraph.php

@@ -0,0 +1,102 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Oct 1, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceGraph\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Models\RrdData;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Line;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Graphs\Models\DataSet;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class ServiceNetworkGraph extends BaseGraph
+{
+    use ProductService;
+
+    protected $id = 'serviceNetworkGraph';
+    protected $name = 'serviceNetworkGraph';
+
+    public function initContent()
+    {
+        $this->updateChartScale('yAxes', [
+            [
+                'scaleLabel' => [
+                    'display'     => true,
+                    'labelString' => sl('lang')->tr('Network')
+                ],
+                'ticks'      => [
+                    'callback'    => 'mgBytesToSize',
+                    'beginAtZero' => true,
+                    'fontSize' => 10
+                ],
+            ]]);
+        //xAxes
+        $this->updateChartScale('xAxes', [
+            [
+                'display' => false,
+            ]]);
+
+        $this->updateChartOption('tooltips', [
+            'callbacks' => [
+                'label' => 'mgTooltipCallbackForNet'
+            ]
+        ]);
+    }
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        $labels   = [];
+        $dataSets = [
+            'netin'  => [],
+            'netout' => [],
+        ];
+        foreach ($this->rrdDataQuery() as $rrd)
+        {
+            $labels[]             = $rrd->date;
+            $dataSets['netin'][]  = isset($rrd->netin) ? $rrd->netin : 0;
+            $dataSets['netout'][] = isset($rrd->netout) ? $rrd->netout : 0;
+        }
+        //Labels
+        $this->setLabels($labels);
+        //Net in
+        $lang    = sl('lang');
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Net In'))
+            ->setData($dataSets['netin'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(174, 198, 57, 0.79)',
+                "borderColor"     => 'rgba(174, 198, 57, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+        //Net out
+        $dataSet = new DataSet();
+        $dataSet->setTitle($lang->tr('Net Out'))
+            ->setData($dataSets['netout'])
+            ->setConfigurationDataSet([
+                "backgroundColor" => 'rgba(39, 133, 134, 0.91)',
+                "borderColor"     => 'rgba(39, 133, 134, 1)',
+            ]);
+        $this->addDataSet($dataSet);
+    }
+
+}

+ 39 - 0
app/UI/ServiceInformation/Buttons/SshPrivateKeyDownloadButton.php

@@ -0,0 +1,39 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Modals\SshPublicKeyDownloadModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+/**
+ * @deprecated
+ */
+class SshPrivateKeyDownloadButton extends ButtonDataTableModalAction implements ClientArea
+{
+    protected $id = 'sshPrivateKeyDownloadButton';
+    protected $icon = 'lu-zmdi lu-zmdi-shield-check';
+
+    public function initContent()
+    {
+        $this->initLoadModalAction(new  SshPublicKeyDownloadModal());
+    }
+
+}

+ 37 - 0
app/UI/ServiceInformation/Buttons/UpdateButton.php

@@ -0,0 +1,37 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Modals\UpdateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class UpdateButton extends ButtonDataTableModalAction implements ClientArea, AdminArea
+{
+    protected $id = 'updateeButton';
+    protected $icon = 'lu-zmdi lu-zmdi-edit';
+
+    public function initContent()
+    {
+        $this->initLoadModalAction(new UpdateModal());
+    }
+
+}

+ 35 - 0
app/UI/ServiceInformation/Forms/SshPublicKeyDownloadForm.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+/**
+ * @deprecated
+ */
+class SshPublicKeyDownloadForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('sshPublicKeyDownloadForm');
+        $this->setConfirmMessage('SSH Key you can download only once.');
+    }
+
+}

+ 90 - 0
app/UI/ServiceInformation/Forms/UpdateForm.php

@@ -0,0 +1,90 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Providers\UpdateProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\HostnameValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\SshPublicKeyValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\isAdmin;
+
+class UpdateForm extends BaseForm implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function initContent()
+    {
+        $this->initIds('updateForm');
+        $this->setFormType('update');
+        $this->setProvider(new UpdateProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['update'];
+    }
+
+    private function initFields()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        //Hostname
+        $field = new Text("hostname");
+        $field->addValidator(new HostnameValidator());
+        $this->addField($field);
+        if ($this->configuration()->isLxc())
+        {
+            return;
+        }
+        //ISO
+        if(isAdmin() || $this->configuration()->isPermissionIsoImage() && $vm->getCdRom()->count()){
+            $field = new Select("iso");
+            $field->notEmpty();
+            $this->addField($field);
+        }
+        //boot device 1
+        $field = new Select("bootOrder0");
+        $field->notEmpty();
+        $this->addField($field);
+        //boot device 2
+        $field = new Select("bootOrder1");
+        $field->notEmpty();
+        $this->addField($field);
+        //boot device 3
+        $field = new Select("bootOrder2");
+        $field->notEmpty();
+        $this->addField($field);
+        //sshkeys for kvm only
+        if($this->configuration()->isPermissionSshkeys()){
+            $field = new Textarea("sshkeys");
+            $field->addValidator(new SshPublicKeyValidator(false));
+            $this->addField($field);
+        }
+
+    }
+}

+ 62 - 0
app/UI/ServiceInformation/Modals/SshPublicKeyDownloadModal.php

@@ -0,0 +1,62 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Modals;
+
+use ModulesGarden\ProxmoxAddon\App\Services\UrlService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons\RedirectButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Forms\SshPublicKeyDownloadForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ModalActionButtons\BaseCancelButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseModal;
+/**
+ * @deprecated
+ */
+class SshPublicKeyDownloadModal extends BaseModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('sshPublicKeyDownloadModal');
+        $this->addForm(new SshPublicKeyDownloadForm());
+    }
+
+    protected function initActionButtons()
+    {
+        if (!empty($this->actionButtons))
+        {
+            return $this;
+        }
+        $vmId = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        //URL
+        $urlService = new UrlService();
+        $rd         = new RedirectButton("sshPrivateKeyDownloadButton");
+        $rd->replaceClasses(['lu-btn lu-btn--success closeModal']);
+        $rd->setHref($urlService->getUrl("sshKey", "sshPrivateKeyDownload",['vm'=> $vmId]));
+        $rd->setIcon(null);
+        $rd->setShowTitle();
+        $rd->deleteHtmlAttribute('data-toggle');
+        $rd->addHtmlAttribute('@click', 'closeModal($event)');
+        $this->addActionButton($rd);
+        $this->addActionButton(new BaseCancelButton());
+        return $this;
+    }
+
+
+}

+ 37 - 0
app/UI/ServiceInformation/Modals/UpdateModal.php

@@ -0,0 +1,37 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Forms\UpdateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+
+class UpdateModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateModal');
+        $this->setModalSizeLarge();
+        $this->addForm(new UpdateForm());
+    }
+
+}

+ 209 - 0
app/UI/ServiceInformation/Pages/ServiceInformation.php

@@ -0,0 +1,209 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Pages;
+
+use MGProvision\Proxmox\v2\models\Kvm;
+use MGProvision\Proxmox\v2\models\Lxc;
+use MGProvision\Proxmox\v2\models\NetworkDeviceKvm;
+use MGProvision\Proxmox\v2\models\NetworkDeviceLxc;
+use ModulesGarden\ProxmoxAddon\App\Libs\Format;
+use ModulesGarden\ProxmoxAddon\App\Models\KeyPair;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\UrlService;
+use ModulesGarden\ProxmoxAddon\App\Services\Utility;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Buttons\RedirectButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Buttons\SshPrivateKeyDownloadButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Buttons\UpdateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Builder\BaseContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AjaxElementInterface;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\RawDataJsonResponse;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\isAdmin;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class ServiceInformation extends BaseContainer implements ClientArea, AdminArea, AjaxElementInterface
+{
+
+    use ProductService;
+    use ApiService;
+
+    protected $id = 'serviceInformationDataTable';
+    protected $title = 'serviceInformationDataTable';
+    protected $vueComponent = true;
+    protected $defaultVueComponentName = 'mg-serviceInformationDataTable';
+
+    public function initContent()
+    {
+        $this->addClass('lu-text-left')
+            ->addClass('lu-col-md-12');
+
+        //Update
+        $this->addButton(new UpdateButton());
+        if ($this->configuration()->isLxc() && KeyPair::ofHostingId($this->getWhmcsParamByKey('serviceid'))->count())
+        {
+            $vmId = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+            /**
+             * @deprecated
+            $keyPairs = KeyPair::ofHostingId($this->getWhmcsParamByKey('serviceid'))->ofVmId($vmId)
+            ->first();
+            //Private Key
+            $deletePrivateKey = $this->configuration()->isSshDeletePrivateKey();
+            if (!$deletePrivateKey && $keyPairs && $keyPairs->isPrivate())
+            {
+            $rd = new RedirectButton("sshPrivateKeyDownloadButton");
+            $rd->replaceClasses(['lu-btn lu-btn--sm lu-btn lu-btn--link lu-btn--icon lu-btn--plain lu-btn--default']);
+            $rd->setIcon('lu-zmdi lu-zmdi-shield-check');
+            $rd->setHref($urlService->getUrl("sshKey", "sshPrivateKeyDownload",['vm'=> $vmId]));
+            $this->addButton($rd);
+            }
+            else
+            {
+            if ($deletePrivateKey && $keyPairs && $keyPairs->isPrivate())
+            {
+            $this->addButton(new SshPrivateKeyDownloadButton());
+            }
+            }
+             */
+
+            //URL
+            $urlService = new UrlService();
+            //Public Key
+            $rd = new RedirectButton("sshPublicKeyDownloadButton");
+            $rd->replaceClasses(['lu-btn lu-btn--sm lu-btn lu-btn--link lu-btn--icon lu-btn--plain lu-btn--default']);
+            $rd->setIcon('lu-zmdi lu-zmdi-shield-security');
+            $rd->setHref($urlService->getUrl("sshKey", "sshPublicKeyDownload",['vm'=> $vmId]));
+            $this->addButton($rd);
+
+
+        }
+    }
+
+    public function returnAjaxData()
+    {
+        //Close session, it speed up page loading
+        session_write_close();
+
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vmModel = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
+        $vars                = [];
+        //Status
+        $status         =  $vm->status();
+        $vars['status'] = [
+            "uptime" => Utility::uptime($status['uptime']),
+            'cpu'    => Utility::cpuUsage($status['cpu']),
+            'cpus' => (int) $status['cpus']
+        ];
+        switch ($status['status'])
+        {
+            case 'running':
+                $vars['status']['status'] = '<span class="lu-label lu-label--success lu-label--status">' . sl('lang')->abtr($status['status']) . '</span>';
+                break;
+            case 'stoped':
+                $vars['status']['status'] = '<span class="lu-label lu-label--danger lu-label--status">' . sl('lang')->abtr($status['status']) . '</span>';
+            default:
+                $vars['status']['status'] = '<span class="lu-label lu-label--danger lu-label--status">' . sl('lang')->abtr($status['status']) . '</span>';
+        }
+        //Memory
+        $vars['status']['memPercent'] = (int) round($status['mem'] / $status['maxmem'] * 100);
+        $vars['status']['maxmem']     = Format::convertBytes($status['maxmem']);
+        $vars['status']['mem']        = Format::convertBytes($status['mem']);
+        if ( $vm instanceof Lxc)
+        {
+            //SWAP
+            $vars['status']['swapPercent'] = (int) round($status['swap'] / $status['maxswap'] * 100);
+            $vars['status']['swap']        = Format::convertBytes($status['swap']);
+            $vars['status']['maxswap']     = Format::convertBytes($status['maxswap']);
+            //Disk
+            $vars['status']['diskPercent'] = (int) round($status['disk'] / $status['maxdisk'] * 100);
+            $vars['status']['disk']        = Format::convertBytes($status['disk']);
+            $vars['status']['maxdisk']     = Format::convertBytes($status['maxdisk']);
+            $vars['status']['diskwrite']   = Format::convertBytes($status['diskwrite']);
+            //Key Pairs
+            if (KeyPair::ofHostingId($this->getWhmcsParamByKey('serviceid'))->count())
+            {
+                $keyPairs                    = KeyPair::ofHostingId($this->getWhmcsParamByKey('serviceid'))->first();
+                $vars['keyPairs']['public']  = $keyPairs->isPrivate();
+                $vars['keyPairs']['private'] = $keyPairs->isPrivate();
+            }
+        }
+        if ($status['balloon_min'])
+        {
+            $vars['status']['balloon_min'] = Format::convertBytes($status['balloon_min']);
+        }
+        //Config
+        $vars['config'] = [
+            "name" =>  $vm->config()['name'] ?  $vm->config()['name'] :  $vm->config()['hostname']
+        ];
+        if (isAdmin())
+        {
+            $vars['node'] =  $vm->getNode();
+        }
+        $vars['virtualization'] =  $vm->getVirtualization();
+        //NetworkRate
+        /** @var NetworkDeviceKvm|NetworkDeviceLxc $networkDevice */
+        $networkDevice =  $vm->getNetworkDevices($this->configuration()->getBridge())[0];
+        if ($networkDevice && $networkDevice->getRate())
+        {
+            $vars['networkRate'] = "{$networkDevice->getRate()} MB/s ({$networkDevice->getRateMbps()} Mbps)";
+        }
+        //KVM
+        if ( $vm instanceof Kvm)
+        {
+            //CD-ROM
+            $vars['cdrom'] =  $vm->getIso();
+            //Boot order
+            $vars['bootOrder'] = [];
+            foreach ( $vm->getBootOrder() as $device)
+            {
+                $vars['bootOrder'][] = sl("lang")->tr("bootOrder", $device);
+            }
+            $vars['bootOrder'] = implode(", ", $vars['bootOrder']);
+            //SSH Public Key
+            $vars['sshkeysName'] =  $vm->sshkeysName();
+        }
+        //OS Info
+        if (isAdmin() &&  $vm->config()['agent'] == 1)
+        {
+            try
+            {
+                $vars['osinfo']                  =  $vm->agent()->getOsinfo()['result'];
+                $vars['osinfo']['kernelrelease'] = $vars['osinfo']['kernel-release'];
+                $vars['hostname']                =  $vm->agent()->getHostname()['result']['host-name'];
+            }
+            catch (\Exception $ex)
+            {
+                $vars['quemuAgent'] = $ex->getMessage();
+            }
+        }
+        if (isAdmin() &&  $vm instanceof  Lxc)
+        {
+            $features =   $vm->config()['features'];
+            $vars['features'] = $features ? $features : "-";
+        }
+        $vars['created_at'] =  fromMySQLDate($vmModel->created_at);
+        $vars['description'] = $vm->config()['description'] ? $vm->config()['description'] : '-';
+
+        return (new RawDataJsonResponse(['data' => $vars]));
+    }
+
+
+}

+ 143 - 0
app/UI/ServiceInformation/Providers/UpdateProvider.php

@@ -0,0 +1,143 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Providers;
+
+use MGProvision\Proxmox\v2\models\Kvm;
+use MGProvision\Proxmox\v2\models\Lxc;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\HostingService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\isAdmin;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+
+class UpdateProvider extends BaseDataProvider implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+    use HostingService;
+
+    public function read()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        if ($vm instanceof Kvm)
+        {
+            //hostname
+            $this->data['hostname'] = $vm->config()['name'];
+            //ISO
+            if(isAdmin() || $this->configuration()->isPermissionIsoImage()){
+                $this->data['iso']            = $vm->cdrom()['isoRaw'];
+                $this->availableValues['iso'] = ["none" => sl("lang")->abtr("template", "None")];
+
+                foreach ($this->isoRepository()->fetch() as $file)
+                {
+                    if ($this->configuration()->isPermissionIsoImages() && !in_array($file->getVolid(), $this->configuration()->getPermissionIsoImages()))
+                    {
+                        continue;
+                    }
+                    $this->availableValues['iso'][$file->getVolid()] = sl("lang")->abtr("template", $file->getFriendlyName());
+                }
+            }
+            //Boot order
+            $bootOrder                           = $vm->getBootOrder();
+            $this->data['bootOrder0']            = $bootOrder[0];
+            $this->data['bootOrder1']            = $bootOrder[1];
+            $this->data['bootOrder2']            = $bootOrder[2];
+            $options                             = [
+                0   => sl("lang")->tr("None"),
+                "c" => sl("lang")->tr("Disk"),
+                "d" => sl("lang")->tr("CD-ROM"),
+                "n" => sl("lang")->tr("Network"),
+            ];
+            $this->availableValues['bootOrder0'] = $options;
+            $this->availableValues['bootOrder1'] = $options;
+            $this->availableValues['bootOrder2'] = $options;
+            //sshkeys
+            $this->data['sshkeys'] = rawurldecode($vm->config()['sshkeys']);
+        }
+        else
+        {
+            if ($vm instanceof Lxc)
+            {
+                //hostname
+                $this->data['hostname'] = $vm->config()['hostname'];
+            }
+        }
+
+    }
+
+    public function update()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vmModel = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
+        if ($vm instanceof Kvm)
+        {
+            //Hostname
+            $vmModel->name = $this->formData['hostname'];
+            $vm->updateConfig(["name" => $this->formData['hostname']]);
+            $vmModel->save();
+            //iso
+            if ($vm->cdrom())
+            {
+                $vm->updateCdrom($this->formData['iso']);
+            }
+            //Boot order
+            $bootOrder = null;
+            for ($i = 0; $i <= 2; $i++)
+            {
+                if ($this->formData['bootOrder' . $i])
+                {
+                    $bootOrder .= $this->formData['bootOrder' . $i];
+                }
+            }
+            $vm->changeBootOrder($bootOrder);
+            //sshkeys
+            if($this->configuration()->isPermissionSshkeys()){
+                if ($this->formData['sshkeys'])
+                {
+                    $vm->updateConfig(["sshkeys" => rawurlencode($this->formData['sshkeys'])]);
+                } else if($vm->config()['sshkeys'])
+                {
+                    $vm->deleteConfig('sshkeys');
+                }
+            }
+        }
+        else
+        {
+            if ($vm instanceof Lxc)
+            {
+                //Hostname
+                $vmModel->name = $this->formData['hostname'];
+                $vm->updateConfig(["hostname" => $this->formData['hostname']]);
+                $vmModel->save();
+            }
+        }
+
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('Service information has been changed')
+            ->addRefreshTargetId('serviceInformationDataTable');
+
+    }
+
+}

+ 5 - 0
app/UI/ServiceInformation/Templates/pages/serviceInformation.tpl

@@ -0,0 +1,5 @@
+<mg-component-body-{$elementId|strtolower}
+        component_id='{$elementId}'
+        component_namespace='{$namespace}'
+        component_index='{$rawObject->getIndex()}'
+></mg-component-body-{$elementId|strtolower}>

+ 66 - 0
app/UI/ServiceInformation/Templates/pages/serviceInformation_components.js

@@ -0,0 +1,66 @@
+mgJsComponentHandler.addDefaultComponent('mg-serviceInformationDataTable', {
+    template: '#t-mg-serviceInformationDataTable',
+    props: [
+        'component_id',
+        'component_namespace',
+        'component_index'
+    ],
+    data: function () {
+        return {
+            data: {
+                status: {
+                    cpu: '-',
+                    status: '-',
+                },
+                config: {
+                    name: '-',
+                },
+                created_at: '-',
+            },
+            loading_state: false,
+            passwordShow: false,
+        };
+    },
+    created: function () {
+        var self = this;
+        self.$nextTick(function () {
+            setTimeout(function(){
+                self.loadAjaxData();
+            }, 1000);
+        });
+        self.$parent.$root.$on('reloadMgData', this.updateMgData);
+    },
+    methods: {
+        loadAjaxData: function () {
+            var self = this;
+            self.loading_state = true;
+            
+            console.log(self.loading_state);
+            
+            var requestParams = {
+                loadData: self.component_id,
+                namespace: self.component_namespace,
+                index: self.component_index
+            };
+
+            var response = mgPageControler.vueLoader.vloadData(requestParams);
+            return response.done(function (data) {
+                self.data = data.data.rawData.data;
+                self.loading_state = false;
+            }).fail(function () {
+                self.loading_state = false;
+            });
+        },
+        loadModal: function (event, targetId, namespace, index, params, addSpinner) {
+            mgPageControler.vueLoader.loadModal(event, targetId,
+                typeof namespace !== 'undefined' ? namespace : getItemNamespace(targetId),
+                typeof index !== 'undefined' ? index : getItemIndex(targetId), params, addSpinner);
+        },
+        updateMgData: function(toReloadId){
+            if(this.component_id === toReloadId)
+            {
+                this.loadAjaxData();
+            }
+        }
+    }
+});

+ 46 - 0
app/UI/ServiceInformation/Templates/pages/serviceInformation_components.tpl

@@ -0,0 +1,46 @@
+<script type="text/x-template" id="t-mg-serviceInformationDataTable-{$elementId|strtolower}"
+        :component_id="component_id"
+        :component_namespace="component_namespace"
+        :component_index="component_index"
+>
+
+
+    <div class="lu-row lu-row--eq-height {$rawObject->getClasses()}" id="{$rawObject->getId()}" namespace="{$namespace}"
+         index="{$rawObject->getIndex()}" actionid="{$rawObject->getIndex()}">
+        <div class="lu-preloader-container lu-preloader-container--full-screen lu-preloader-container--overlay"
+             v-if="loading_state">
+            <div class="lu-preloader lu-preloader--sm"></div>
+        </div>
+        <div class="col-md-12">
+            <h4 v-if="data.status"><span>{literal}{{ data.config.name  }} {/literal} </span></h4>
+            <ul class="lu-list lu-list--info">
+                <li class="lu-list__item">
+                    <span class="lu-list__item-title">{$MGLANG->tr('Status')}</span>
+                    <span class="lu-list__value" v-html="data.status.status"> </span>
+                </li>
+                <li class="lu-list__item">
+                    <span class="lu-list__item-title">{$MGLANG->tr('CPU Usage')}</span>
+                    <span class="lu-list__value">{literal}  {{ data.status.cpu }} {/literal} % {$MGLANG->tr('of')} {literal} {{ data.status.cpus }} {/literal}{$MGLANG->tr('Cores')}
+                    <span v-if="data.status.cpuunit"> {$MGLANG->tr('CPU Units')}  {literal} {{ data.status.cpuunit }}{/literal}</span>
+                </span>
+                </li>
+                <li class="lu-list__item">
+                    <span class="lu-list__item-title">{$MGLANG->tr('Memory')}</span>
+                    <span class="lu-list__value" v-if="data.virtualization == 'qemu' && data.status.balloon_min">
+                        {$MGLANG->tr('Total')}: {literal}{{ data.status.maxmem }}{/literal}
+                        {$MGLANG->tr('Usage')}: {literal}{{ data.status.mem }}{/literal}
+                    </span>
+                    <span class="lu-list__value" v-else>{literal} {{data.status.mem }} / {{ data.status.maxmem }} {/literal}</span>
+                </li>
+                <li class="lu-list__item">
+                    <span class="lu-list__item-title">{$MGLANG->tr('Created At')}</span>
+                    <span class="lu-list__value">{literal}{{ data.created_at }}{/literal}</span>
+                </li>
+                <li class="lu-list__item">
+                    <span class="lu-list__item-title">{$MGLANG->translate('description')}</span>
+                    <span class="lu-list__value">{literal}{{ data.description}}{/literal}</span>
+                </li>
+            </ul>
+        </div>
+    </div>
+</script>

+ 35 - 0
app/UI/Snapshot/Buttons/CreateButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals\CreateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+
+class CreateButton extends ButtonCreate implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createSnapshotButton');
+        $this->initLoadModalAction(new CreateModal());
+    }
+
+}

+ 35 - 0
app/UI/Snapshot/Buttons/CreateJobButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals\CreateJobModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+
+class CreateJobButton extends ButtonCreate implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createJobButton');
+        $this->initLoadModalAction(new CreateJobModal());
+    }
+
+}

+ 36 - 0
app/UI/Snapshot/Buttons/DeleteButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class DeleteButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteButton');
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteModal());
+    }
+
+}

+ 36 - 0
app/UI/Snapshot/Buttons/DeleteJobButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals\DeleteJobModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class DeleteJobButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteJobButton');
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteJobModal());
+    }
+
+}

+ 36 - 0
app/UI/Snapshot/Buttons/DeleteJobMassButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals\DeleteJobMassModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonMassAction;
+
+class DeleteJobMassButton extends ButtonMassAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteJobMassButton');
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteJobMassModal());
+    }
+
+}

+ 36 - 0
app/UI/Snapshot/Buttons/DeleteMassButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals\DeleteMassModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonMassAction;
+
+class DeleteMassButton extends ButtonMassAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteMassButton');
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteMassModal());
+    }
+
+}

+ 36 - 0
app/UI/Snapshot/Buttons/RollbackButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals\RollbackModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class RollbackButton extends ButtonDataTableModalAction implements ClientArea
+{
+    protected $icon = 'lu-zmdi lu-zmdi-time-restore-setting';
+
+    public function initContent()
+    {
+        $this->initIds('rollbackButton ');
+        $this->initLoadModalAction(new RollbackModal());
+    }
+
+}

+ 35 - 0
app/UI/Snapshot/Buttons/UpdateButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals\UpdateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class UpdateButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateButton');
+        $this->initLoadModalAction(new UpdateModal());
+    }
+
+}

+ 35 - 0
app/UI/Snapshot/Buttons/UpdateJobButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals\UpdateJobModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class UpdateJobButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateJobButton');
+        $this->initLoadModalAction(new UpdateJobModal());
+    }
+
+}

+ 74 - 0
app/UI/Snapshot/Forms/CreateForm.php

@@ -0,0 +1,74 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms;
+
+use MGProvision\Proxmox\v2\models\Kvm;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers\SnapshotProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\SnapshotValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Helpers\AlertTypesConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+
+
+class CreateForm extends BaseForm implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('createSnapshotForm');
+        $this->setFormType('create');
+        $this->setProvider(new SnapshotProvider());
+        $this->setInternalAlertMessage('confirmCreate');
+        $this->setInternalAlertMessageType(AlertTypesConstants::INFO);
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+
+    private function initFields()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        //name
+        $field = new Text('name');
+        $field->notEmpty();
+        $field->addValidator(new SnapshotValidator(true));
+        $this->addField($field);
+        if ($vm instanceof Kvm)
+        {
+            //vmstate
+            $field = new Switcher("vmstate");
+            $this->addField($field);
+        }
+        //description
+        $field = new Textarea("description");
+        $this->addField($field);
+    }
+}

+ 50 - 0
app/UI/Snapshot/Forms/CreateJobForm.php

@@ -0,0 +1,50 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers\JobProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+
+
+class CreateJobForm extends BaseForm implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+    use JobForm;
+
+    public function initContent()
+    {
+        $this->initIds('createJobForm');
+        $this->setFormType('create');
+        $this->setProvider(new JobProvider());
+        $this->setJobConfirmMessage();
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+
+}

+ 50 - 0
app/UI/Snapshot/Forms/DeleteForm.php

@@ -0,0 +1,50 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers\SnapshotProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class DeleteForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteSnapshotForm');
+        $this->setFormType('delete');
+        $this->setProvider(new SnapshotProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDelete');
+        $this->addField(new Hidden("name"));
+    }
+
+}

+ 51 - 0
app/UI/Snapshot/Forms/DeleteJobForm.php

@@ -0,0 +1,51 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers\JobProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class DeleteJobForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteJobForm');
+        $this->setFormType('delete');
+        $this->setProvider(new JobProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('conforimJobDelete',["name"=> null]);
+        $this->addField(new Hidden("id"));
+        $this->addField(new Hidden("name"));
+    }
+
+}

+ 49 - 0
app/UI/Snapshot/Forms/DeleteJobMassForm.php

@@ -0,0 +1,49 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers\BackupProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers\JobProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+
+
+class DeleteJobMassForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteJobMassForm');
+        $this->setFormType('deleteMass');
+        $this->setProvider(new JobProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['deleteMass'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDeleteJobMass');
+    }
+
+}

+ 49 - 0
app/UI/Snapshot/Forms/DeleteMassForm.php

@@ -0,0 +1,49 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers\BackupProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers\SnapshotProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+
+
+class DeleteMassForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteMassForm');
+        $this->setFormType('deleteMass');
+        $this->setProvider(new SnapshotProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['deleteMass'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDeleteMass');
+    }
+
+}

+ 103 - 0
app/UI/Snapshot/Forms/JobForm.php

@@ -0,0 +1,103 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms;
+
+use MGProvision\Proxmox\v2\models\Kvm;
+use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Enum\JobPeriod;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\SnapshotValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\StartTimeValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Number;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+trait JobForm
+{
+
+    public function setJobConfirmMessage(){
+        $limit = $this->getWhmcsConfigOption(ConfigurableOption::SNAPSHOTS, $this->configuration()->getSnapshotMaxFiles());
+        if ($limit && $limit != "-1")
+        {
+            sl("lang")->addReplacementConstant("snapshotFilesLimit" , $limit);
+            $this->setInternalAlertMessage( sl("lang")->tr('Your snapshot limit is :snapshotFilesLimit:. When you exceed this limit, the last snapshot will be replaced with a new one.'));
+            $this->setInternalAlertMessageRaw(true);
+        }
+    }
+
+    protected function initFields()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $formData = $this->getRequestValue("formData");
+        //id
+        $id = false;
+        if(is_numeric($this->getRequestValue("actionElementId"))){
+            $id = $this->getRequestValue("actionElementId");
+        }
+        if ($formData && $formData['id']){
+            $id =  $formData['id'];
+        }
+        //hourly
+        $isHourly = true;
+        if($formData &&  $formData['period'] ){
+            $isHourly = $formData['period'] == JobPeriod::HOURLY;
+        } elseif (!$formData && $id){
+            $this->loadProvider();
+            $this->dataProvider->read();
+            $isHourly = $this->dataProvider->getValueById('period') == JobPeriod::HOURLY ;
+        }elseif (!$formData && !$id){
+            $period = $this->configuration()->getPermissionSnapshotJobPeriod();
+            if($period && in_array(JobPeriod::HOURLY, $period)){
+                $isHourly = true;
+            }elseif ($period ){
+                $isHourly = false;
+            }
+        }
+        //id
+        if(is_numeric($this->getRequestValue("actionElementId"))){
+            $this->addField(new Hidden("id"));
+        }
+        //period
+        $field = new Select('period');
+        $field->addHtmlAttribute('bi-event-change', "reloadVueModal");
+        $this->addField($field);
+        //run_every
+        if($isHourly){
+            $field = new Number('run_every',1,48);
+            $field->setPlaceholder("1");
+            $this->addField($field);
+        }
+        //days
+        if(!$isHourly){
+            $field = new Select('days');
+            $field->enableMultiple();
+            $this->addField($field);
+        }
+        //start_time
+        if(!$isHourly){
+            $field = new Text('start_time');
+            $field->setPlaceholder("00:00");
+            $field->addValidator(new StartTimeValidator(false));
+            $this->addField($field);
+        }
+        //name
+        $field = new Text('name');
+        $field->notEmpty();
+        $field->addValidator(new SnapshotValidator(true));
+        $this->addField($field);
+        //vmstate
+        if ($vm instanceof Kvm)
+        {
+            $field = new Switcher("vmstate");
+            $this->addField($field);
+        }
+        //description
+        $field = new Textarea("description");
+        $this->addField($field);
+
+    }
+}

+ 49 - 0
app/UI/Snapshot/Forms/RollbackForm.php

@@ -0,0 +1,49 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers\SnapshotProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class RollbackForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('rollbackForm');
+        $this->setFormType('rollback');
+        $this->setProvider(new SnapshotProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['rollback'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmRestore');
+        $this->addField(new Hidden("name"));
+    }
+}

+ 54 - 0
app/UI/Snapshot/Forms/UpdateForm.php

@@ -0,0 +1,54 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers\SnapshotProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+
+
+class UpdateForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('updateSnapshotForm');
+        $this->setFormType('update');
+        $this->setProvider(new SnapshotProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['update'];
+    }
+
+    private function initFields()
+    {
+        //name
+        $field = new Hidden('name');
+        $this->addField($field);
+        //description
+        $field = new Textarea("description");
+        $this->addField($field);
+    }
+}

+ 50 - 0
app/UI/Snapshot/Forms/UpdateJobForm.php

@@ -0,0 +1,50 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers\JobProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+
+
+class UpdateJobForm extends BaseForm implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+    use JobForm;
+
+    public function initContent()
+    {
+        $this->initIds('updateJobForm');
+        $this->setFormType('update');
+        $this->setProvider(new JobProvider());
+        $this->setJobConfirmMessage();
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['update'];
+    }
+
+}

+ 35 - 0
app/UI/Snapshot/Modals/CreateJobModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms\CreateJobForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class CreateJobModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createJobModal');
+        $this->addForm(new CreateJobForm());
+    }
+
+}

+ 35 - 0
app/UI/Snapshot/Modals/CreateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms\CreateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class CreateModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createSnapshotModal');
+        $this->addForm(new CreateForm());
+    }
+
+}

+ 35 - 0
app/UI/Snapshot/Modals/DeleteJobMassModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms\DeleteJobMassForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteJobMassModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteJobMassModal');
+        $this->addForm(new DeleteJobMassForm());
+    }
+
+}

+ 35 - 0
app/UI/Snapshot/Modals/DeleteJobModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms\DeleteJobForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteJobModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteJobModal');
+        $this->addForm(new DeleteJobForm());
+    }
+
+}

+ 35 - 0
app/UI/Snapshot/Modals/DeleteMassModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms\DeleteMassForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteMassModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteMassModal');
+        $this->addForm(new DeleteMassForm());
+    }
+
+}

+ 35 - 0
app/UI/Snapshot/Modals/DeleteModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteSnapshotModal');
+        $this->addForm(new DeleteForm());
+    }
+
+}

+ 35 - 0
app/UI/Snapshot/Modals/RollbackModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms\RollbackForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class RollbackModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('rollbackSnapshotModal');
+        $this->addForm(new RollbackForm());
+    }
+
+}

+ 35 - 0
app/UI/Snapshot/Modals/UpdateJobModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms\UpdateJobForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class UpdateJobModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateJobModal');
+        $this->addForm(new UpdateJobForm());
+    }
+
+}

+ 35 - 0
app/UI/Snapshot/Modals/UpdateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Forms\UpdateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class UpdateModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateSnapshotModal');
+        $this->addForm(new UpdateForm());
+    }
+
+}

+ 128 - 0
app/UI/Snapshot/Pages/JobRawDataTable.php

@@ -0,0 +1,128 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Pages;
+use MGProvision\Proxmox\v2\models\Kvm;
+use ModulesGarden\ProxmoxAddon\App\Models\SnapshotJob;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Enum\JobPeriod;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons\CreateJobButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons\DeleteJobButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons\DeleteJobMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons\UpdateJobButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\QueryDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\RawDataTable\RawDataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class JobRawDataTable extends RawDataTable implements ClientArea, AdminArea
+{
+    use ApiService;
+    use ProductService;
+
+    protected $id = 'jobDataTable';
+    protected $title = 'jobDataTable';
+
+    public function initContent()
+    {
+        //Create
+        $createButton = new CreateJobButton();
+        $createButton->addClass("pmCreateJobButton");
+        if (!$this->resourceGuard()->hasSnapshotJobLimit())
+        {
+            $createButton->addClass("hidden");
+        }
+        $this->addButton($createButton);
+        //Update
+        $this->addActionButton(new UpdateJobButton());
+        //Delete
+        $this->addActionButton(new DeleteJobButton());
+        //Mass delete
+        $this->addMassActionButton(new DeleteJobMassButton());
+    }
+
+    protected function loadHtml()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $this->addColumn((new Column('name'))->setSearchable(true, "string")->setOrderable());
+        if ($vm instanceof Kvm)
+        {
+            $this->addColumn((new Column('vmstate'))->setSearchable(true)->setOrderable());
+        }
+        $this->addColumn((new Column('description'))->setSearchable(true)->setOrderable());
+        $this->addColumn((new Column('days'))->setSearchable(true))
+             ->addColumn((new Column('created_at'))->setSearchable(true, "date")->setOrderable('DESC'));
+
+    }
+
+
+    public function replaceFieldVmstate($key, $row)
+    {
+        if ($row->vmstate == "1")
+        {
+            return '<span class="lu-label lu-label--success lu-label--status">' . sl('lang')->tr("Yes") . '</span>';
+        }
+        return '<span class="lu-label lu-label--danger lu-label--status">' . sl('lang')->tr("No") . '</span>';
+    }
+
+    public function replaceFieldDescription($key, $row)
+    {
+        if ($row->description)
+        {
+            return $row->description;
+        }
+        return '-';
+    }
+
+    public function replaceFieldDays($key, $row)
+    {
+
+        if($row->period == JobPeriod::DAILY && $row->days){
+            $row = json_decode($row->days, true);
+            foreach ($row as &$day){
+                $day = sl("lang")->tr($day);
+            }
+            return implode(", ", $row);
+        }elseif ($row->period == JobPeriod::HOURLY && $row->run_every &&  $row->run_every == 1){
+            sl('lang')->addReplacementConstant('run_every', $row->run_every);
+            return sl("lang")->tr("Every :run_every: hour");
+        }elseif ($row->period == JobPeriod::HOURLY && $row->run_every &&  $row->run_every > 1){
+            sl('lang')->addReplacementConstant('run_every', $row->run_every);
+            return sl("lang")->tr("Every :run_every: hours");
+        }
+        return '-';
+    }
+
+    protected function loadData()
+    {
+        $query    = (new SnapshotJob())
+            ->query()
+            ->getQuery()
+            ->select('id','name','description','vmstate','period', 'run_every','days','start_time','updated_at','created_at')
+            ->where("hosting_id", $this->getWhmcsParamByKey('serviceid'));
+        $dataProv = new QueryDataProvider();
+        $dataProv->setData($query);
+        $dataProv->setDefaultSorting("created_at", 'DESC');
+        $this->setDataProvider($dataProv);
+    }
+
+}

+ 34 - 0
app/UI/Snapshot/Pages/SnapshotDataTable.php

@@ -0,0 +1,34 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Pages;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons\MailtoSwitchButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+
+class SnapshotDataTable extends DataTable implements ClientArea
+{
+    protected $id ='snapshotDataTable';
+    protected $name ='snapshotDataTable';
+    protected $title ='snapshotDataTableTitle';
+
+    use SnapshotTrait;
+
+}

+ 19 - 0
app/UI/Snapshot/Pages/SnapshotRawDataTable.php

@@ -0,0 +1,19 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Pages;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\RawDataTable\RawDataTable;
+
+class SnapshotRawDataTable extends RawDataTable implements ClientArea, AdminArea
+{
+    use SnapshotTrait;
+
+    protected $id = 'snapshotDataTable';
+    protected $title = 'snapshotDataTable';
+
+
+}

+ 39 - 0
app/UI/Snapshot/Pages/SnapshotTab.php

@@ -0,0 +1,39 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Pages;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\TabsWidget\TabsWidget;
+
+class SnapshotTab extends TabsWidget implements ClientArea, AdminArea
+{
+    protected $id = 'snapshotTab';
+    protected $name = 'snapshotTab';
+    protected $vueComponent = true;
+
+    public function initContent()
+    {
+        $this->addElement(new SnapshotRawDataTable());
+        $this->addElement(new JobRawDataTable());
+
+    }
+}

+ 120 - 0
app/UI/Snapshot/Pages/SnapshotTrait.php

@@ -0,0 +1,120 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Pages;
+
+
+use MGProvision\Proxmox\v2\models\Kvm;
+use MGProvision\Proxmox\v2\repository\SnapshotRepository;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons\CreateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons\RollbackButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Buttons\UpdateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+trait SnapshotTrait
+{
+    use ApiService;
+    use ProductService;
+
+    /**
+     * @var SnapshotRepository
+     */
+    private $snapshotRepository;
+
+    public function initContent()
+    {
+        //Create
+        $createButton = new CreateButton();
+        $createButton->addClass("pmCreateSnapshotButton");
+        if (!$this->resourceGuard()->hasSnapshotLimit())
+        {
+            $createButton->addClass("hidden");
+        }
+        $this->unsetShowTitle();
+
+        $this->addButton($createButton);
+        //rollback
+        $this->addActionButton(new RollbackButton());
+        //Update
+        $this->addActionButton(new UpdateButton());
+        //Delete
+        $this->addActionButton(new DeleteButton());
+        //Mass delete
+        $this->addMassActionButton(new DeleteMassButton());
+        $this->snapshotRepository = new SnapshotRepository();
+    }
+
+    protected function loadHtml()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $this->addColumn((new Column('name'))->setSearchable(true, "string")->setOrderable())
+            ->addColumn((new Column('status'))->setSearchable(true, "string")->setOrderable());
+        if ($vm instanceof Kvm)
+        {
+            $this->addColumn((new Column('vmstate'))->setSearchable(true)->setOrderable());
+        }
+        $this->addColumn((new Column('snaptime'))->setSearchable(true, "date")->setOrderable('DESC'))
+            ->addColumn((new Column('description'))->setSearchable(true)->setOrderable());
+    }
+
+
+    public function replaceFieldStatus($key, $row)
+    {
+        //current
+        if ($this->snapshotRepository->getCurrent()->getParent() == $row['name'])
+        {
+            return '<span class="lu-label lu-label--success lu-label--status">' . sl('lang')->tr("Active") . '</span>';
+        }
+        return '<span class="lu-label lu-label--danger lu-label--status">' . sl('lang')->tr("Disabled") . '</span>';
+
+
+    }
+
+    public function replaceFieldVmstate($key, $row)
+    {
+        if ($row['vmstate'] == "1")
+        {
+            return '<span class="lu-label lu-label--success lu-label--status">' . sl('lang')->tr("Yes") . '</span>';
+        }
+        return '<span class="lu-label lu-label--danger lu-label--status">' . sl('lang')->tr("No") . '</span>';
+    }
+
+    public function replaceFieldSnaptime($key, $row)
+    {
+        return date('Y-m-d H:i:s', $row[$key]);
+    }
+
+    public function replaceFieldDescription($key, $row)
+    {
+        if ($row['description'])
+        {
+            return $row['description'];
+        }
+        return '-';
+    }
+
+    protected function loadData()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $this->snapshotRepository->setApi($this->api());
+        $this->snapshotRepository->findByVm($vm);
+        $this->snapshotRepository->ignoreCurrent(true);
+        $data = [];
+        foreach ($this->snapshotRepository->fetch() as $entity)
+        {
+            $row    = $entity->getAttributes();
+            $data[] = array_merge(['id' => base64_encode(json_encode($row))], $row);
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setDefaultSorting("snaptime", 'DESC');
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+}

+ 121 - 0
app/UI/Snapshot/Providers/JobProvider.php

@@ -0,0 +1,121 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers;
+
+
+use ModulesGarden\ProxmoxAddon\App\Models\SnapshotJob;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Enum\JobPeriod;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseModelDataProvider;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class JobProvider  extends BaseModelDataProvider implements ClientArea
+{
+    use ProductService;
+
+    public function __construct()
+    {
+        parent::__construct(SnapshotJob::class);
+    }
+
+    protected function isModelProper($model)
+    {
+        if (in_array(get_parent_class($model), [
+            'ModulesGarden\Servers\ProxmoxCloudVps\Core\Models\ExtendedEloquentModel',
+            'ModulesGarden\ProxmoxAddon\Core\Models\ExtendedEloquentModel',
+            'Illuminate\Database\Eloquent\Model'
+        ]))
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    public function read()
+    {
+        //period
+        $period = $this->configuration()->getPermissionSnapshotJobPeriod();
+        if($period && in_array(JobPeriod::HOURLY, $period)){
+            $this->availableValues['period'][JobPeriod::HOURLY] = sl("lang")->tr(JobPeriod::HOURLY );
+        }
+        if($period && in_array(JobPeriod::DAILY, $period)){
+            $this->availableValues['period'][JobPeriod::DAILY] = sl("lang")->tr(JobPeriod::DAILY);
+        }
+        if(!$period){
+            $this->availableValues['period'] = [
+                JobPeriod::HOURLY => sl("lang")->tr(JobPeriod::HOURLY ),
+                JobPeriod::DAILY => sl("lang")->tr(JobPeriod::DAILY )
+            ];
+        }
+         //days
+        $this->availableValues['days'] = [];
+        foreach (JobPeriod::DAYS_OF_WEEK as $day){
+            $this->availableValues['days'][$day] =  sl("lang")->tr($day);
+        }
+        if($this->formData){
+            $this->data = $this->formData;
+            return;
+        }
+        parent::read();
+        $vmstate = $this->data['vmstate']==1 ? "on":"off" ;
+        $this->data['vmstate']= $vmstate;
+        //start_time
+        if($this->data['start_time']){
+            $this->data['start_time'] = substr($this->data['start_time'], 0,-3);
+        }
+    }
+
+    public function create()
+    {
+        //vmstate
+        if(isset($this->formData['vmstate'])){
+            $vmstate = $this->formData['vmstate']=="on" ? 1:0;
+            $this->formData['vmstate']= $vmstate ;
+        }
+        //hosting_id
+        $this->formData['hosting_id']= $this->getWhmcsParamByKey('serviceid');
+        //fill from data
+        $this->model->fill($this->formData)->save();
+        sl('lang')->addReplacementConstant('name', $this->formData['name']);
+        return (new HtmlDataJsonResponse())->setMessageAndTranslate('Snapshot Job :name: has been created successfully')
+            ->addData('createJobButtonStatus', $this->resourceGuard()->hasSnapshotJobLimit())
+            ->setCallBackFunction('pmToggleCreateJobButton');
+    }
+
+    public function update(){
+
+        //vmstate
+        if(isset($this->formData['vmstate'])){
+            $vmstate = $this->formData['vmstate']=="on" ? 1:0;
+            $this->formData['vmstate']= $vmstate ;
+        }
+        parent::update();
+        sl('lang')->addReplacementConstant('name', $this->formData['name']);
+        return (new HtmlDataJsonResponse())->setMessageAndTranslate('Snapshot Job :name: has updated successfully');
+    }
+
+    public function deleteMass()
+    {
+        foreach ($this->getRequestValue('massActions') as $id)
+        {
+            $this->model->where('id', $id)->delete();
+        }
+        return (new HtmlDataJsonResponse())->setMessageAndTranslate('The selected snapshot jobs have been deleted successfully')
+            ->addData('createJobButtonStatus', $this->resourceGuard()->hasSnapshotJobLimit())
+            ->setCallBackFunction('pmToggleCreateJobButton');
+    }
+
+
+    public function delete()
+    {
+        parent::delete();
+        sl('lang')->addReplacementConstant('name', $this->formData['name']);
+        return (new HtmlDataJsonResponse())->setMessageAndTranslate('Snapshot Job :name: has been deleted successfully')
+            ->addData('createJobButtonStatus', $this->resourceGuard()->hasSnapshotJobLimit())
+            ->setCallBackFunction('pmToggleCreateJobButton');
+    }
+}

+ 142 - 0
app/UI/Snapshot/Providers/SnapshotProvider.php

@@ -0,0 +1,142 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Providers;
+
+use MGProvision\Proxmox\v2\models\Snapshot;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+
+class SnapshotProvider extends BaseDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function read()
+    {
+        if ($this->actionElementId)
+        {
+            $this->data = json_decode(base64_decode($this->actionElementId), true);
+        }
+    }
+
+    public function create()
+    {
+
+        $this->acl()->snapshot();
+        $this->resourceGuard()->snapshotLimit();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $snapshot = new Snapshot();
+        $snapshot->setApi($this->api());
+        $snapshot->setPath($vm->getPath() . "/snapshot");
+        $snapshot->setAttributes([
+            "name"        => $this->formData['name'],
+            "description" => $this->formData['description'],
+        ]);
+        if ($this->formData['vmstate'])
+        {
+            $snapshot->setVmstate($this->formData['vmstate'] == "on" ? 1 : 0);
+        }
+        $taskId =  $snapshot->create();
+        sleep(1);
+        $task = $vm->node()->task($taskId);
+         if($task->isFalied()){
+             return (new HtmlDataJsonResponse())
+                 ->setStatusError()
+                 ->setMessageAndTranslate($task->getExitstatus());
+         }
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The snapshot has been created successfully')
+            ->addData('createButtonStatus', $this->resourceGuard()->hasSnapshotLimit())
+            ->setCallBackFunction('pmToggleSnapshotButton');
+    }
+
+    public function update()
+    {
+        $this->acl()->snapshot();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $snapshot = new Snapshot();
+        $snapshot->setApi($this->api());
+        $snapshot->setPath($vm->getPath() . "/snapshot/" . $this->formData['name']);
+        $snapshot->setAttributes([
+            "name"        => $this->formData['name'],
+            "description" => $this->formData['description'],
+        ]);
+        $snapshot->update();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The snapshot has been updated successfully');
+    }
+
+    public function delete()
+    {
+        $this->acl()->snapshot();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $snapshot = new Snapshot();
+        $snapshot->setApi($this->api());
+        $snapshot->setPath($vm->getPath() . "/snapshot/" . $this->formData['name']);
+        $snapshot->delete();
+        sleep(1);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The snapshot has been deleted successfully')
+            ->addData('createButtonStatus', $this->resourceGuard()->hasSnapshotLimit())
+            ->setCallBackFunction('pmToggleSnapshotButton');
+    }
+
+    public function deleteMass()
+    {
+        $this->acl()->snapshot();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $snapshot = new Snapshot();
+        $snapshot->setApi($this->api());
+        foreach ($this->request->get('massActions') as $id)
+        {
+            $data = json_decode(base64_decode($id), true);
+            $name = $data['name'];
+            $snapshot->setPath($vm->getPath() . "/snapshot/" . $name);
+            $snapshot->delete();
+            sleep(1);
+        }
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The snapshots have been deleted successfully')
+            ->addData('createButtonStatus', $this->resourceGuard()->hasSnapshotLimit())
+            ->setCallBackFunction('pmToggleSnapshotButton');
+    }
+
+    public function rollback()
+    {
+        $this->acl()->snapshot();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $snapshot = new Snapshot();
+        $snapshot->setApi($this->api());
+        $snapshot->setPath($vm->getPath() . "/snapshot/" . $this->formData['name']);
+        $snapshot->rollback();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The snapshot has been rolled back successfully');
+    }
+
+}

+ 37 - 0
app/UI/TaskHistory/Buttons/InfoButton.php

@@ -0,0 +1,37 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\TaskHistory\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\TaskHistory\Modals\InfoModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class InfoButton extends ButtonDataTableModalAction implements ClientArea
+{
+    protected $icon = 'lu-zmdi lu-zmdi-info-outline';
+
+    public function initContent()
+    {
+        $this->initIds('infoButton ');
+        $this->initLoadModalAction(new InfoModal());
+        $this->setDisableByColumnValue("satusRaw", "OK");
+    }
+
+}

+ 50 - 0
app/UI/TaskHistory/Forms/InfoForm.php

@@ -0,0 +1,50 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\TaskHistory\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\TaskHistory\Providers\TaskHistoryProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class InfoForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('infoForm');
+        $this->setFormType('info');
+        $this->setProvider(new TaskHistoryProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['info'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage("error: :status:");
+        $this->addField(new Hidden("status"));
+        $this->addLocalLangReplacements(["status" => null]);
+    }
+}

+ 45 - 0
app/UI/TaskHistory/Modals/InfoModal.php

@@ -0,0 +1,45 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\TaskHistory\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\TaskHistory\Forms\InfoForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ModalActionButtons\BaseCancelButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class InfoModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('infoTaskHistoryModal');
+        $this->addForm(new InfoForm());
+    }
+
+    protected function initActionButtons()
+    {
+        if (!empty($this->actionButtons))
+        {
+            return $this;
+        }
+        $this->addActionButton(new BaseCancelButton());
+        return $this;
+    }
+}

+ 119 - 0
app/UI/TaskHistory/Pages/TaskHistoryDataTable.php

@@ -0,0 +1,119 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\TaskHistory\Pages;
+
+use MGProvision\Proxmox\v2\repository\TaskRepository;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\TaskHistory\Buttons\InfoButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class TaskHistoryDataTable extends DataTable implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+    protected $id = 'taskHistory';
+    protected $name = 'taskHistory';
+    protected $title = 'taskHistoryTitle';
+
+    public function initContent()
+    {
+        $this->unsetShowTitle();
+
+        //Info
+        $this->addActionButton(new InfoButton());
+    }
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('starttime'))->setSearchable(true, "int")->setOrderable('DESC'))
+            ->addColumn((new Column('endtime'))->setSearchable(true, "int")->setOrderable())
+            ->addColumn((new Column('type'))->setSearchable(true))
+            ->addColumn((new Column('status'))->setSearchable(true));
+    }
+
+    public function formatRowStarttime($key, $row)
+    {
+        return date('Y-m-d H:i:s', $row[$key]);
+    }
+
+    public function formatRowEndtime($key, $row)
+    {
+        return date('Y-m-d H:i:s', $row[$key]);
+    }
+
+    public function formatRowStatus($key,$row)
+    {
+        if ($row['status'] == "OK")
+        {
+            return '<span class="lu-label lu-label--success lu-label--status">' . sl('lang')->tr("OK") . '</span>';
+        }
+        return '<span class="lu-label lu-label--danger lu-label--status">' . sl('lang')->tr("Error") . '</span>';
+    }
+
+    public function formatRowSnaptime($key, $row)
+    {
+        return date('Y-m-d H:i:s', $row['snaptime']);
+    }
+
+    public function formatRowType($key,$row)
+    {
+        if ($row['type'])
+        {
+            return sl('lang')->tr($row['type']);
+        }
+        return '-';
+    }
+
+    protected function loadData()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $repository = new TaskRepository();
+        $repository->setApi($this->api());
+        $repository->findByVm($vm)
+            ->fromStartTime($this->getWhmcsParamByKey('model')->registrationDate->getTimestamp());
+        $repository->limit(3000);
+        $data = [];
+        foreach ($repository->fetch() as $entity)
+        {
+            $row             = $entity->getAttributes();
+            $row['entityId'] = $row['id'];
+            $row['satusRaw'] = $row['status'];
+            $row['id'] =  base64_encode(json_encode($row));
+            foreach($row as  $k => &$entery){
+                $method = 'formatRow'.ucfirst($k) ;
+                if(method_exists($this, $method)){
+                    $entery = $this->$method($k,$row);
+                }
+            }
+            $data[] = $row;
+        }
+        $dataProv = new ArrayDataProvider();
+        $dataProv->setDefaultSorting("snaptime", 'DESC');
+        $dataProv->setData($data);
+        $this->setDataProvider($dataProv);
+    }
+
+
+}

+ 45 - 0
app/UI/TaskHistory/Providers/TaskHistoryProvider.php

@@ -0,0 +1,45 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\TaskHistory\Providers;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+
+class TaskHistoryProvider extends BaseDataProvider implements ClientArea
+{
+    use ApiService;
+
+    public function read()
+    {
+        if ($this->actionElementId)
+        {
+            $this->data = json_decode(base64_decode($this->actionElementId), true);
+        }
+    }
+
+    public function update()
+    {
+
+    }
+
+
+}

+ 76 - 0
app/UI/Validators/CidrValidator.php

@@ -0,0 +1,76 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators;
+
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class CidrValidator extends BaseValidator
+{
+    protected $required = false;
+
+    public function __construct($required = true)
+    {
+        $this->required = $required;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        else
+        {
+            if ($this->required && empty($data))
+            {
+                $this->addValidationError('PleaseProvideANumericValue');
+                return false;
+            }
+        }
+        $min = 1;
+        $max = 32;
+        //ipv6 range
+        if ($additionalData && $additionalData->get('formData')['ip'] && preg_match('/\:/', $additionalData->get('formData')['ip']))
+        {
+            $max = 128;
+        }
+        else
+        {
+            if ($additionalData && $additionalData->get('formData')['ipPool'] && preg_match('/\:/', $additionalData->get('formData')['ipPool']))
+            {
+                $max = 128;
+            }
+        }
+        if (!is_numeric($data) || (int)$data < $min || (int)$data > $max)
+        {
+            $this->addValidationError('PleaseProvideANumericValueBetween', false, ['minValue' => $min, 'maxValue' => $max]);
+            return false;
+        }
+        return true;
+    }
+}

+ 89 - 0
app/UI/Validators/CpulimitValidator.php

@@ -0,0 +1,89 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class CpulimitValidator extends BaseValidator
+{
+    protected $minValue = 0;
+    protected $maxValue = 0;
+    protected $required = false;
+
+    public function __construct($min = 0, $max = 0, $required = false)
+    {
+        $this->minValue = $min;
+        $this->maxValue = $max;
+        $this->required = $required;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        if (is_numeric($data) && $this->minValue === 0 && $this->maxValue === 0)
+        {
+            return true;
+        }
+        //Min & Max
+        if (is_numeric($data) && $this->minValue <= ($data) && ($data) <= $this->maxValue)
+        {
+            return true;
+        }
+        //Min
+        else
+        {
+            if (is_numeric($data) && !is_numeric($this->maxValue) && $this->minValue <= ($data))
+            {
+                return true;
+            }
+        }
+
+        if ($this->minValue == $this->maxValue)
+        {
+            $this->addValidationError('PleaseProvideANumericValue');
+
+            return false;
+        }
+        if (is_numeric($this->minValue) && is_numeric($this->maxValue))
+        {
+            $this->addValidationError('PleaseProvideANumericValueBetween', false, ['minValue' => $this->minValue, 'maxValue' => $this->maxValue]);
+        }
+        else
+        {
+            if (is_numeric($this->minValue) && !is_numeric($this->maxValue))
+            {
+                $this->addValidationError('PleaseProvideANumericValueFrom', false, ['minValue' => $this->minValue]);
+            }
+        }
+
+
+        return false;
+    }
+}

+ 53 - 0
app/UI/Validators/HostnameValidator.php

@@ -0,0 +1,53 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class HostnameValidator extends BaseValidator
+{
+    protected $required = false;
+
+    public function __construct($required = true)
+    {
+        $this->required = $required;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        if (!preg_match('/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/', $data))
+        {
+            $this->addValidationError('PleaseProvideAhostname');
+            return false;
+        }
+        return true;
+    }
+}

+ 66 - 0
app/UI/Validators/IpAddressValidator.php

@@ -0,0 +1,66 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class IpAddressValidator extends BaseValidator
+{
+    protected $required = false;
+    protected $public = true;
+
+    public function __construct($required = false , $public = true)
+    {
+        $this->required = $required;
+        $this->public = $public;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        if (!filter_var($data, FILTER_VALIDATE_IP))
+        {
+            $this->addValidationError('IP Address is not valid', false);
+            return false;
+        }
+        if (!$this->public && filter_var($data, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE))
+        {
+            $this->addValidationError('The IP Address is not private', false);
+            return false;
+        }
+        if ($this->required && VmIpAddress::ofIp($data)->count())
+        {
+            $this->addValidationError('IP Address already exist', false);
+            return false;
+        }
+        return true;
+    }
+}

+ 94 - 0
app/UI/Validators/NumberValidator.php

@@ -0,0 +1,94 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class NumberValidator extends BaseValidator
+{
+    protected $minValue = 0;
+    protected $maxValue = 0;
+    protected $required = false;
+
+    public function __construct($min = 0, $max = 0, $required = false)
+    {
+        $this->minValue = (int)$min;
+        $this->maxValue = $max;
+        $this->required = $required;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        if(preg_match("/\./", $data)){
+            $this->addValidationError('PleaseProvideANumericValueBetween', false, ['minValue' => $this->minValue, 'maxValue' => $this->maxValue]);
+            return false;
+        }
+        if (is_numeric($data) && $this->minValue === 0 && $this->maxValue === 0)
+        {
+            return true;
+        }
+        //Min & Max
+        if (is_numeric($data) && $this->minValue <= ((int)$data) && ((int)$data) <= $this->maxValue)
+        {
+            return true;
+        }
+        //Min
+        else
+        {
+            if (is_numeric($data) && !is_numeric($this->maxValue) && $this->minValue <= ((int)$data))
+            {
+                return true;
+            }
+        }
+
+        if ($this->minValue === $this->maxValue)
+        {
+            $this->addValidationError('PleaseProvideANumericValue');
+
+            return false;
+        }
+
+        if (is_numeric($this->minValue) && is_numeric($this->maxValue))
+        {
+            $this->addValidationError('PleaseProvideANumericValueBetween', false, ['minValue' => $this->minValue, 'maxValue' => $this->maxValue]);
+        }
+        else
+        {
+            if (is_numeric($this->minValue) && !is_numeric($this->maxValue))
+            {
+                $this->addValidationError('PleaseProvideANumericValueFrom', false, ['minValue' => $this->minValue]);
+            }
+        }
+
+
+        return false;
+    }
+}

+ 59 - 0
app/UI/Validators/PasswordValidator.php

@@ -0,0 +1,59 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class PasswordValidator extends BaseValidator
+{
+    protected $required = false;
+    protected $length;
+
+    public function __construct($required = true, $length = 5)
+    {
+        $this->required = $required;
+        $this->length   = $length;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        else
+        {
+            if (is_numeric($this->length) && strlen($data) < $this->length)
+            {
+                $this->addValidationError('The password is too short');
+                return false;
+            }
+        }
+
+        return true;
+    }
+}

+ 90 - 0
app/UI/Validators/PortValidator.php

@@ -0,0 +1,90 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class PortValidator extends BaseValidator
+{
+    protected $minValue = 1;
+    protected $maxValue = 65535;
+    protected $required = false;
+
+    public function __construct($required = false)
+    {
+        $this->required = $required;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        if (is_numeric($data) && $this->minValue === 0 && $this->maxValue === 0)
+        {
+            return true;
+        }
+        if($data && preg_match("/\:/",$data)){
+            return  true;
+        }
+        //Min & Max
+        if (is_numeric($data) && $this->minValue <= ((int)$data) && ((int)$data) <= $this->maxValue)
+        {
+            return true;
+        }
+        //Min
+        else
+        {
+            if (is_numeric($data) && !is_numeric($this->maxValue) && $this->minValue <= ((int)$data))
+            {
+                return true;
+            }
+        }
+
+        if ($this->minValue === $this->maxValue)
+        {
+            $this->addValidationError('PleaseProvideANumericValue');
+
+            return false;
+        }
+
+        if (is_numeric($this->minValue) && is_numeric($this->maxValue))
+        {
+            $this->addValidationError('PleaseProvideANumericValueBetween', false, ['minValue' => $this->minValue, 'maxValue' => $this->maxValue]);
+        }
+        else
+        {
+            if (is_numeric($this->minValue) && !is_numeric($this->maxValue))
+            {
+                $this->addValidationError('PleaseProvideANumericValueFrom', false, ['minValue' => $this->minValue]);
+            }
+        }
+
+
+        return false;
+    }
+}

+ 57 - 0
app/UI/Validators/SnapshotValidator.php

@@ -0,0 +1,57 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class SnapshotValidator extends BaseValidator
+{
+    protected $required = false;
+
+    public function __construct($required = true)
+    {
+        $this->required = $required;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        else if (preg_match('/\s/', $data)) {
+            $this->addValidationError('PleaseProvideASnapshotValue');
+            return false;
+        }
+        else if (!preg_match('/^[A-Za-z]{1}[A-Za-z0-9_]{1}[A-Za-z0-9]/', $data)) {
+            $this->addValidationError('PleaseProvideASnapshotValue');
+            return false;
+        }
+
+        return true;
+    }
+}

+ 57 - 0
app/UI/Validators/SshPublicKeyValidator.php

@@ -0,0 +1,57 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class SshPublicKeyValidator extends BaseValidator
+{
+    protected $required = false;
+
+    public function __construct($required = true)
+    {
+        $this->required = $required;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        else
+        {
+            if (!preg_match('/ssh\-/', $data))
+            {
+                $this->addValidationError('PleaseProvideASshPublicKey');
+                return false;
+            }
+        }
+
+        return true;
+    }
+}

+ 57 - 0
app/UI/Validators/StartTimeValidator.php

@@ -0,0 +1,57 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class StartTimeValidator extends BaseValidator
+{
+    protected $required = false;
+
+    public function __construct($required = true)
+    {
+        $this->required = $required;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        else
+        {
+            if (!preg_match('/[0-9]{2}\:[0-9]{2}/', $data))
+            {
+                $this->addValidationError('PleaseProvideAStartTimeValue');
+                return false;
+            }
+        }
+
+        return true;
+    }
+}

+ 66 - 0
app/UI/Validators/VirtualIpAddressValidator.php

@@ -0,0 +1,66 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class VirtualIpAddressValidator extends BaseValidator
+{
+    protected $required = false;
+    protected $public = true;
+
+    public function __construct($required = false , $public = true)
+    {
+        $this->required = $required;
+        $this->public = $public;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        if (!filter_var($data, FILTER_VALIDATE_IP))
+        {
+            $this->addValidationError('IP Address is not valid', false);
+            return false;
+        }
+        if (!$this->public && filter_var($data, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE))
+        {
+            $this->addValidationError('The IP Address is not private', false);
+            return false;
+        }
+        //@todo
+//        if ($this->required && VmIpAddress::ofIp($data)->count())
+//        {
+//            $this->addValidationError('IP Address already exist', false);
+//            return false;
+//        }
+        return true;
+    }
+}

+ 35 - 0
app/UI/VirtualInterface/Buttons/CreateButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Modals\CreateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+
+class CreateButton extends ButtonCreate implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createVirtualInterfaceButton');
+        $this->initLoadModalAction(new CreateModal());
+    }
+
+}

+ 40 - 0
app/UI/VirtualInterface/Buttons/DeleteButton.php

@@ -0,0 +1,40 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Buttons;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class DeleteButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('virtualInterfaceDeleteButton');
+        $this->switchToRemoveBtn();
+        $this->setDisableByColumnValue("bridge", $this->configuration()->getBridge());
+        $this->initLoadModalAction(new DeleteModal());
+    }
+
+}

+ 49 - 0
app/UI/VirtualInterface/Fields/IpSelect.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Fields;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
+use ModulesGarden\ProxmoxAddon\App\Services\Ip\Ipv4Range;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\AjaxFields\Select;
+
+class IpSelect extends Select implements ClientArea
+{
+
+
+    protected $id   = 'ipSelect';
+    protected $name = 'ip';
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        $vnId = $this->getRequestValue('formData')['vn_id'];
+        if(!$vnId || $vnId=='public'){
+            foreach (VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))->ofVmIdNull()->get() as $ip)
+            {
+                if(!$this->getValue()){
+                    $this->setSelectedValue($ip->ip);
+                }
+                $this->availableValues[]=['key' =>  $ip->ip, 'value' => $ip->ip];
+            }
+            return;
+        }
+        /**
+         * @var VirtualNetwork $virtualNetwork
+         */
+        $virtualNetwork = VirtualNetwork::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                                       ->ofId($vnId)
+                                       ->firstOrFail();
+        $ipRange = new Ipv4Range($virtualNetwork->pool, $virtualNetwork->cidr);
+        $ipRange->setLimit(200);
+        $ipRange->disableIpAddresses( $virtualNetwork ->virtualInterfaces->pluck('ip')->toArray());
+        foreach (  $ipRange->get() as $ip ){
+            if(!$this->getValue()){
+                $this->setSelectedValue($ip);
+            }
+            $this->availableValues[]=['key' =>  $ip, 'value' => $ip];
+        }
+  ;
+    }
+}

+ 37 - 0
app/UI/VirtualInterface/Fields/NetworkSelect.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Fields;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
+use ModulesGarden\ProxmoxAddon\App\Services\Ip\Ipv4Range;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\AjaxFields\Select;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class NetworkSelect extends Select implements ClientArea
+{
+    protected $id   = 'networkSelect';
+    protected $name = 'network';
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        $this->availableValues[]    = [
+            'key' => 'public',
+            'value' => sl('lang')->abtr('Public')
+        ];
+        foreach (VirtualNetwork::ofHostingId($this->getWhmcsParamByKey('serviceid'))->select('id', 'name')->get() as $vn)
+        {
+            $this->availableValues[]    = [
+                'key' => $vn->id,
+                'value' => $vn->name
+            ];
+        }
+
+        if($this->availableValues)
+        {
+            $this->value    = $this->availableValues[0]['key'];
+        }
+    }
+}

+ 62 - 0
app/UI/VirtualInterface/Forms/CreateForm.php

@@ -0,0 +1,62 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Fields\IpSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Providers\VirtualInterfaceProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Fields\NetworkSelect;
+
+
+
+class CreateForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('createForm');
+        $this->setFormType('create');
+        $this->setProvider(new VirtualInterfaceProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+
+    private function initFields()
+    {
+        //vn_id
+        $field = new NetworkSelect('vn_id');
+        $field->setId('vn_id');
+        $field->setMainContainer($this->mainContainer);
+        $field->notEmpty();
+        $this->addField($field);
+        //ip
+        $field = new IpSelect('ip');
+        $field->setMainContainer($this->mainContainer);
+        $field->notEmpty();
+        $field->addReloadOnChangeField('vn_id');
+        $this->addField($field);
+
+    }
+}

+ 51 - 0
app/UI/VirtualInterface/Forms/DeleteForm.php

@@ -0,0 +1,51 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Providers\VirtualInterfaceProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class DeleteForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteForm');
+        $this->setFormType('delete');
+        $this->setProvider(new VirtualInterfaceProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDelete');
+        $this->addField(new Hidden("name"));
+        $this->addField(new Hidden("id"));
+    }
+
+}

+ 35 - 0
app/UI/VirtualInterface/Modals/CreateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Forms\CreateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmSuccess;
+
+class CreateModal extends ModalConfirmSuccess implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createVirtualInterfaceModal');
+        $this->addForm(new CreateForm());
+    }
+
+}

+ 35 - 0
app/UI/VirtualInterface/Modals/DeleteModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deletevirtualInterfaceModal');
+        $this->addForm(new DeleteForm());
+    }
+
+}

+ 98 - 0
app/UI/VirtualInterface/Pages/VirtualInterfaceDataTable.php

@@ -0,0 +1,98 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualInterface;
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Buttons\CreateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Buttons\InfoButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Buttons\MailtoSwitchButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Buttons\RestoreButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Buttons\UpdateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\QueryDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class VirtualInterfaceDataTable extends DataTable implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    protected $id = 'virtualInterfaceDataTable';
+    protected $title = 'virtualInterfaceDataTable';
+
+    public function initContent()
+    {
+        $createButton = new CreateButton();
+        $createButton->addClass("pmVnCreateButton");
+        /**
+         * @todo validate limit
+         */
+        if (!$this->configuration()->isPermissionVirtualNetwork())
+        {
+            $createButton->addClass("hidden");
+        }
+        $this->unsetShowTitle();
+
+        //Create
+        $this->addButton($createButton);
+        //Delete
+        $this->addActionButton(new DeleteButton());
+    }
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('name'))->setSearchable(true)->setOrderable()->setOrderable('ASC'))
+            ->addColumn((new Column('ip'))->setSearchable(true)->setOrderable());
+    }
+
+
+    public function replaceFieldName($key, $row)
+    {
+        if ($row->vn_id==0)
+        {
+            return sl('lang')->abtr("Public");
+        }
+        return $row->name;
+
+    }
+    protected function loadData()
+    {
+        $vmId = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        $vn = (new VirtualNetwork())->getTable();
+        $vi = (new VirtualInterface())->getTable();
+        $query    = VirtualInterface::select( "{$vn}.name","{$vi}.vn_id", "{$vi}.ip", "{$vi}.id")
+                           ->leftJoin($vn, "{$vn}.id", "=" ,"{$vi}.vn_id")
+                           ->where("{$vi}.vm_id", $vmId)
+                           ->getQuery();
+        $dataProv = new QueryDataProvider();
+        $dataProv->setDefaultSorting("name", 'ASC');
+        $dataProv->setData($query);
+        $this->setDataProvider($dataProv);
+    }
+
+
+}

+ 165 - 0
app/UI/VirtualInterface/Providers/VirtualInterfaceProvider.php

@@ -0,0 +1,165 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Providers;
+
+use MGProvision\Proxmox\v2\Api;
+use MGProvision\Proxmox\v2\models\Kvm;
+use MGProvision\Proxmox\v2\ProxmoxApiException;
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualInterface;
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\IpSetIpFilterService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\VirtualInterfaceConverter;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseModelDataProvider;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+use Illuminate\Database\Capsule\Manager as DB;
+
+class VirtualInterfaceProvider extends BaseModelDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    /**
+     * @var NetworkService
+     */
+    private $networkService;
+
+    /**
+     * VmUpdateProvider constructor.
+     */
+    public function __construct()
+    {
+        $this->model = new VirtualInterface();
+        $this->networkService = new NetworkService();
+    }
+
+    public function read()
+    {
+        $this->availableValues['vn_id']['public'] = sl('lang')->abtr('Public');
+        foreach (VirtualNetwork::ofHostingId($this->getWhmcsParamByKey('serviceid'))->select('id', 'name')->get() as $vn) {
+            $this->availableValues['vn_id'][$vn->id] = $vn->name;
+        }
+        if ($this->getActionElementIdValue()) {
+            $this->data['id'] = $this->getActionElementIdValue();
+        }
+    }
+
+    public function create()
+    {
+
+        $this->model->fill($this->getFormDataValues());
+        $this->model->hosting_id = $this->getWhmcsParamByKey('serviceid');
+        $this->model->vm_id = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        $this->model->ip_long = ip2long($this->model->ip);
+        $virtualNetworkId = $this->getRequestValue('formData')['vn_id'];
+        $this->model->vn_id = $virtualNetworkId == "public" ? 0 : $virtualNetworkId;
+        try {
+            DB::beginTransaction();
+            Api::beginTransaction();
+            if($virtualNetworkId == "public" ){
+                VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                    ->ofIp($this->model->ip)
+                    ->update(['vm_id' => $this->model->vm_id]);
+            }
+            $this->model->save();
+            $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+            $conveter = new VirtualInterfaceConverter([$this->model], $vm);
+            if($vm instanceof Kvm && $vm->isRunning()){
+                $conveter->convert();
+                $cdrom = $vm->getCdRomRepository();
+                if($cdrom->hasCloudInit() ){
+                    $cloudInitDrive = $cdrom->getCloudInitDrive();
+                }
+                try {
+                    $vm->updateConfig($conveter->getNetworkDevicesAsConfig());
+                    $vm->updateConfig($conveter->getIpConfigsAsConfig());
+                    //Regenerate image
+                    if($cloudInitDrive ){
+                        $cloudInitDrive->unmount();
+                        $cloudInitDrive->mount();
+                    }
+                }catch (ProxmoxApiException $ex) {
+                    if(preg_match("/hotplug problem/", $ex->getMessage())){
+                        $vm->updateConfig($conveter->getIpConfigsAsConfig());
+                        //Regenerate image
+                        if($cloudInitDrive ){
+                            $cloudInitDrive->unmount();
+                            $cloudInitDrive->mount();
+                        }
+                    }else{
+                        throw $ex;
+                    }
+                }
+            }else{
+                //Update container
+                $vm->updateConfig($conveter->asConfig());
+            }
+            DB::commit();
+            if ($this->configuration()->isIpsetIpFilter()){
+                $ipSetFilterService =  new IpSetIpFilterService();
+                $ipSetFilterService->create();
+            }
+        } catch (\Exception $ex) {
+            DB::rollBack();
+            Api::commit();
+            throw $ex;
+        }
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Virtual interface has been created successfully')
+            ->addData('createButtonStatus', false)
+            ->addRefreshTargetId('virtualInterfaceDataTable')
+            ->addRefreshTargetId('networkDataTable')
+            ->setCallBackFunction('pmToggleButton');
+    }
+
+
+    public function update()
+    {
+
+    }
+
+    public function delete()
+    {
+        $vi = $this->model->where('id', $this->getFormDataValues()['id'])
+            ->ofHostingId($this->getWhmcsParamByKey('serviceid'))
+            ->firstOrFail();
+        $this->networkService->deleteByIpAddresses([$vi]);
+        if ($this->configuration()->isIpsetIpFilter()){
+            $ipSetFilterService =  new IpSetIpFilterService();
+            $ipSetFilterService->create();
+        }
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Virtual :name: network has been deleted successfully')
+            ->addData('createButtonStatus', true)
+            ->addRefreshTargetId('virtualInterfaceDataTable')
+            ->addRefreshTargetId('networkDataTable')
+            ->setCallBackFunction('pmToggleButton');
+
+    }
+
+
+}

+ 35 - 0
app/UI/VirtualNetwork/Buttons/CreateButton.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Modals\CreateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+
+class CreateButton extends ButtonCreate implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('createButton');
+        $this->initLoadModalAction(new CreateModal());
+    }
+
+}

+ 39 - 0
app/UI/VirtualNetwork/Buttons/DeleteButton.php

@@ -0,0 +1,39 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Buttons;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class DeleteButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('deleteButton');
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteModal());
+    }
+
+}

+ 36 - 0
app/UI/VirtualNetwork/Buttons/UpdateButton.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Buttons;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Modals\UpdateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class UpdateButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('updateButton');
+        $this->initLoadModalAction(new UpdateModal());
+    }
+
+}

+ 69 - 0
app/UI/VirtualNetwork/Forms/CreateForm.php

@@ -0,0 +1,69 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\CidrValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\VirtualIpAddressValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Providers\VirtualNetworkProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+
+class CreateForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('createForm');
+        $this->setFormType('create');
+        $this->setProvider(new VirtualNetworkProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['create'];
+    }
+
+    private function initFields()
+    {
+        //name
+        $field = new Text('name');
+        $field->notEmpty();
+        $this->addField($field);
+        //pool
+        $field = new Text('pool');
+        $field->addValidator(new VirtualIpAddressValidator(true, false));
+        $field->setPlaceholder('192.168.0.100');
+        $this->addField($field);
+        //cidr
+        $field = new Text('cidr');
+        $field->setPlaceholder('24');
+        $field->addValidator(new CidrValidator(true));
+        $this->addField($field);
+        //gateway
+        $field = new Text('gateway');
+        $field->setPlaceholder('192.168.0.1');
+        $field->addValidator(new VirtualIpAddressValidator(false, false));
+        $this->addField($field);
+
+    }
+}

+ 51 - 0
app/UI/VirtualNetwork/Forms/DeleteForm.php

@@ -0,0 +1,51 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Providers\VirtualNetworkProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class DeleteForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteForm');
+        $this->setFormType('delete');
+        $this->setProvider(new VirtualNetworkProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDelete');
+        $this->addField(new Hidden("name"));
+        $this->addField(new Hidden("id"));
+    }
+
+}

+ 55 - 0
app/UI/VirtualNetwork/Forms/UpdateForm.php

@@ -0,0 +1,55 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Providers\VirtualNetworkProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+
+class UpdateForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('updateForm');
+        $this->setFormType('update');
+        $this->setProvider(new VirtualNetworkProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['update'];
+    }
+
+    private function initFields()
+    {
+        //name
+        $field = new Text('name');
+        $field->notEmpty();
+        $this->addField($field);
+        //id
+        $this->addField(new Hidden("id"));
+    }
+
+}

+ 35 - 0
app/UI/VirtualNetwork/Modals/CreateModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Forms\CreateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmSuccess;
+
+class CreateModal extends ModalConfirmSuccess implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('virtualNetworkCreateModal');
+        $this->addForm(new CreateForm());
+    }
+
+}

+ 35 - 0
app/UI/VirtualNetwork/Modals/DeleteModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteModal extends ModalConfirmDanger implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('virtualNetworkDeleteModal');
+        $this->addForm(new DeleteForm());
+    }
+
+}

+ 41 - 0
app/UI/VirtualNetwork/Modals/UpdateModal.php

@@ -0,0 +1,41 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Modals;
+
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Forms\InfoForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Forms\UpdateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseEditModal;
+
+class UpdateModal extends  BaseEditModal implements ClientArea
+{
+
+    use ProductService;
+    use ApiService;
+
+    public function initContent()
+    {
+        $this->initIds('virtualNetworkUpdateModal');
+        $this->addForm(new UpdateForm());
+
+    }
+}

+ 92 - 0
app/UI/VirtualNetwork/Pages/VirtualNetworkDataTable.php

@@ -0,0 +1,92 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Buttons\CreateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Buttons\InfoButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Buttons\MailtoSwitchButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Buttons\RestoreButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Buttons\UpdateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\QueryDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class VirtualNetworkDataTable extends DataTable implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function initContent()
+    {
+        $this->initIds('virtualNetworkDataTable');
+        $this->addClass(' lu-text-left');
+        $createButton    = new CreateButton();
+        $resourceManager = new ResourceManager();
+        $createButton->addClass("pmCreateVirtualNetworkButton");
+        if (!$resourceManager->virtualNetworks()->hasFreeTotal())
+        {
+            $createButton->addClass("hidden");
+        }
+        //Create
+        $this->addButton($createButton);
+        //Update
+        $this->addActionButton(new UpdateButton());
+        //Delete
+        $this->addActionButton(new DeleteButton());
+    }
+
+    protected function loadHtml()
+    {
+        $this->addColumn((new Column('name'))->setSearchable(true)->setOrderable()->setOrderable('ASC'))
+            ->addColumn((new Column('pool'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('cidr'))->setSearchable(true)->setOrderable())
+            ->addColumn((new Column('gateway'))->setSearchable(true)->setOrderable());
+    }
+
+    public function replaceFieldGateway($key, $row)
+    {
+        if ($row->gateway)
+        {
+            return $row->gateway;
+        }
+        return "-";
+    }
+
+    protected function loadData()
+    {
+        $query    = VirtualNetwork::select("id", "name", "pool", "cidr", "gateway")
+            ->ofHostingId($this->getWhmcsParamByKey('serviceid'))
+            ->getQuery();
+        $dataProv = new QueryDataProvider();
+        $dataProv->setDefaultSorting("name", 'ASC');
+        $dataProv->setData($query);
+        $this->setDataProvider($dataProv);
+    }
+
+
+}

+ 119 - 0
app/UI/VirtualNetwork/Providers/VirtualNetworkProvider.php

@@ -0,0 +1,119 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualNetwork\Providers;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualInterface;
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseModelDataProvider;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\t;
+
+
+class VirtualNetworkProvider extends BaseModelDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    /**
+     * @var NetworkService
+     */
+    private $networkService;
+
+    /**
+     * VmUpdateProvider constructor.
+     */
+    public function __construct()
+    {
+        $this->model = new VirtualNetwork;
+        $this->networkService = new NetworkService();
+    }
+
+    public function read()
+    {
+        if(!$this->getActionElementIdValue()){
+            return;
+        }
+        $dbData = $this->model->where('id', $this->actionElementId)
+                              ->ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                              ->first();
+        if ($dbData !== null)
+        {
+            $this->data = $dbData->toArray();
+        }
+    }
+
+    public function create()
+    {
+        $resourceManager = new ResourceManager();
+        $this->model->fill($this->getFormDataValues());
+        $this->model->tag = $this->networkService->nextTag();
+        $this->model->hosting_id = $this->getWhmcsParamByKey('serviceid');
+        $this->model->save();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Virtual :name: network has been created successfully')
+            ->addData('createButtonStatus', $resourceManager->virtualNetworks()->hasFreeTotal())
+            ->setCallBackFunction('pmToggleVirtualNetworkButton');
+    }
+
+
+
+    public function update()
+    {
+        $resourceManager = new ResourceManager();
+        $dbData = $this->model->where('id',  $this->getFormDataValues()['id'])
+            ->ofHostingId($this->getWhmcsParamByKey('serviceid'))
+            ->firstOrFail();
+        $dbData->fill($this->formData)->save();
+        t()->addReplacementConstant('name',$dbData->name);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Virtual :name: network has been updated successfully')
+            ->addData('createButtonStatus', $resourceManager->virtualNetworks()->hasFreeTotal())
+            ->setCallBackFunction('pmToggleVirtualNetworkButton');
+    }
+
+    public function delete()
+    {
+        if(VirtualInterface::ofHostingId($this->getWhmcsParamByKey('serviceid'))->ofVnId($this->getFormDataValues()['id'])->count()){
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('cannotDeleteTheVirtualNetwork');
+        }
+        $resourceManager = new ResourceManager();
+        $this->model->where('id', $this->getFormDataValues()['id'])
+                    ->ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                     ->delete();
+
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Virtual :name: network has been deleted successfully')
+            ->addData('createButtonStatus', $resourceManager->virtualNetworks()->hasFreeTotal())
+            ->setCallBackFunction('pmToggleVirtualNetworkButton');
+    }
+
+
+}

+ 30 - 0
app/UI/Vm/Pages/BackupTab.php

@@ -0,0 +1,30 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vm\Pages;
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Pages\BackupDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Pages\BackupRawDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Pages\BackupJobDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\TabsWidget\TabsWidget;
+
+class BackupTab extends TabsWidget implements ClientArea
+{
+    use ProductService;
+
+    protected $id   = 'backupTab';
+    protected $name = 'backupTabName';
+    protected $title = 'backupTabTitle';
+
+
+    public function initContent()
+    {
+        $this->unsetShowTitle();
+        $this->addElement(new BackupDataTable());
+        $this->addElement(new BackupJobDataTable);
+
+    }
+}

+ 23 - 0
app/UI/Vm/Pages/DetailTab.php

@@ -0,0 +1,23 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vm\Pages;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\IpAddress\Pages\IpAddressDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\ServiceInformation\Pages\ServiceInformation;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Forms\VmUpdateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Builder\BaseContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+
+class DetailTab extends BaseContainer implements ClientArea
+{
+    protected $name ='detailTab';
+    protected $title ='detailTabName';
+
+    public function initContent()
+    {
+        $this->unsetShowTitle();
+        $this->addElement(new VmUpdateForm());
+    }
+}

+ 31 - 0
app/UI/Vm/Pages/FirewallTab.php

@@ -0,0 +1,31 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vm\Pages;
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Pages\BackupRawDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Pages\FirewallDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\FirewallOption\Pages\FirewallOption;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\TabsWidget\TabsWidget;
+
+class FirewallTab extends TabsWidget implements ClientArea
+{
+    use ProductService;
+
+    protected $id   = 'firewallTab';
+    protected $name = 'firewallTab';
+    protected $title = 'firewallTabTitle';
+
+
+    public function initContent()
+    {
+        $this->unsetShowTitle();
+
+        $this->addElement(new FirewallOption());
+        $this->addElement(new FirewallDataTable());
+
+    }
+}

+ 96 - 0
app/UI/Vm/Pages/VmTabs.php

@@ -0,0 +1,96 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vm\Pages;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Pages\BackupDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Disk\Pages\DiskDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\MountPoint\Pages\MountPointDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Pages\NetworkLxcDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Pages\NetworkQemuDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages\GraphsTab;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages\IsoDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages\ReinstallTab;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages\TemplateDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Pages\SnapshotDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\TaskHistory\Pages\TaskHistoryDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Pages\VirtualInterfaceDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\TabsWidget\TabsWidget;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Network\Pages\NetworkTab;
+
+class VmTabs extends TabsWidget implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->addElement(new DetailTab);
+        if(!$this->configuration()->isDetailsCombinedView()){
+            //disk
+            if ($this->configuration()->isQemu() && $this->configuration()->isPermissionDisk())
+            {
+                $this->addElement(new DiskDataTable());
+            }
+            //mount point
+            if ($this->configuration()->isLxc() && $this->configuration()->isPermissionDisk())
+            {
+                $this->addElement(new MountPointDataTable());
+            }
+            //network
+            if (($this->configuration()->isQemu() && $this->configuration()->isPermissionNetwork()) || ($this->configuration()->isLxc() && $this->configuration()->isPermissionNetwork()))
+            {
+                $this->addElement(new NetworkTab());
+            }
+        }
+        //snapshot
+        if ($this->configuration()->isPermissionSnapshot())
+        {
+            $this->addElement(new SnapshotDataTable());
+        }
+        //backup
+        if ($this->configuration()->isPermissionBackupJob())
+        {
+            $this->addElement(new BackupTab());
+        }
+        elseif ($this->configuration()->isPermissionBackup())
+        {
+            $this->addElement(new BackupDataTable());
+        }
+        if ($this->configuration()->isPermissionFirewallOption() && $this->configuration()->isPermissionFirewall())
+        {
+            $this->addElement(new FirewallTab());
+        }
+        //task history
+        if ($this->configuration()->isPermissionTaskHistory())
+        {
+            $this->addElement(new TaskHistoryDataTable());
+        }
+        /**
+         * Graphs
+         */
+        if($this->configuration()->isPermissionGraph()){
+            $this->addElement(new GraphsTab());
+        }
+        /**
+         * Reinstall
+         */
+        if ($this->configuration()->isQemu() && $this->configuration()->isPermissionOsTemplate() && $this->configuration()->isPermissionIsoImage())
+        {
+            $this->addElement(ReinstallTab::class);
+        }
+        elseif ($this->configuration()->isQemu() && $this->configuration()->isPermissionOsTemplate())
+        {
+            $this->addElement(TemplateDataTable::class);
+        }
+        elseif ($this->configuration()->isQemu() && $this->configuration()->isPermissionIsoImage())
+        {
+            $this->addElement(IsoDataTable::class);
+            //lxc
+        }
+        elseif ($this->configuration()->isLxc())
+        {
+            $this->addElement(TemplateDataTable::class);
+        }
+    }
+}

+ 3 - 0
app/UI/Vm/Templates/pages/detailTab.tpl

@@ -0,0 +1,3 @@
+{foreach from=$elements key=nameElement item=dataElement}
+    {$dataElement->getHtml()}
+{/foreach}

+ 50 - 0
app/UI/VmCreate/Fields/IsoImageSelect.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields;
+
+use MGProvision\Proxmox\v2\repository\FileRepository;
+use MGProvision\Proxmox\v2\repository\StorageRepository;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\AjaxFields\Select;
+
+class IsoImageSelect extends Select implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        //default node
+        if($this->getRequestValue('location')){
+            $defaultNode = $this->getRequestValue('location');
+        }else{
+            $defaultNode = $this->getNode()->getNode();
+        }
+        $storageRepository = new StorageRepository();
+        $storageRepository->findByNodes([$defaultNode])
+            ->findEnabed();
+        $storages            = $storageRepository->fetchAsArray();
+        $isoRepository = new FileRepository();
+        $isoRepository->findByNodes([$defaultNode])
+            ->findByStorages($storages);
+        $isoRepository->findIso();
+
+        foreach ($isoRepository->fetch() as $entity)
+        {
+            if ($this->configuration()->isPermissionIsoImages() && !in_array($entity->getVolid(), $this->configuration()->getPermissionIsoImages()))
+            {
+                continue;
+            }
+
+            $this->availableValues[]=[
+                "key" => $entity->getVolid(),
+                "value"     => $entity->getFriendlyName(),
+            ];
+        }
+    }
+
+
+}

+ 125 - 0
app/UI/VmCreate/Fields/OsTemplateSelect.php

@@ -0,0 +1,125 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields;
+
+use MGProvision\Proxmox\v2\repository\ClusterResourcesRepository;
+use MGProvision\Proxmox\v2\repository\FileRepository;
+use MGProvision\Proxmox\v2\repository\StorageRepository;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\Core\Helper\AdvancedUserHelper;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\AjaxFields\Select;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class OsTemplateSelect extends Select implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        $advancedUser = new AdvancedUserHelper($this->getWhmcsParamByKey('userid'));
+        if ($this->configuration()->isQemu())
+        {
+            $this->loadQemuTemplates();
+
+            if ($advancedUser->isAdvanced() || $this->configuration()->isPermissionIsoImage())
+            {
+                $this->availableValues[] = [
+                    "key"   => 'installationFromIso',
+                    "value" => sl('lang')->abtr('Installation From ISO'),
+                ];
+            }
+            if($this->availableValues[0]['key']=="installationFromIso"){
+                $this->callBackFunction = 'pcOsTemplateLoadShowIsoFields';
+            }
+        }
+        if ($this->configuration()->isLxc())
+        {
+            $this->loadLxcTemplates();
+        }
+        if($this->availableValues[0]['key']){
+            $this->value = $this->availableValues[0]['key'];
+        }
+
+        $this->data['additionalData']['showItemDescription']  = true;
+    }
+
+    private function defaultNode()
+    {
+        if ($this->getRequestValue('location'))
+        {
+            return $this->getRequestValue('location');
+        }
+        else
+        {
+            return $this->getNode()->getNode();
+        }
+    }
+
+    private function loadQemuTemplates()
+    {
+        $clusterResurces = new ClusterResourcesRepository();
+        $clusterResurces->findKvmTemplate();
+        //default node
+        $defaultNode = $this->defaultNode();
+        //search templates on specific node
+        if (!$this->configuration()->isOsTemplatesInAllNodes())
+        {
+            $clusterResurces->findByNodes($defaultNode);
+        }
+        foreach ($clusterResurces->fetchWithUniqueNames($defaultNode) as $entity)
+        {
+            if ($entity->isCustom() && !$entity->matchName($this->getWhmcsParamByKey("serviceid")))
+            {
+                continue;
+            }
+            if ($this->configuration()->isPermissionOsTemplates() && !in_array($entity->getName(), $this->configuration()->getPermissionOsTemplates()))
+            {
+                continue;
+            }
+            $id     = "{$entity->getNode()}/{$entity->getVmid()}";
+            $name   = sl('lang')->abtr('template', $entity->getName());
+            $description = $entity->getVm()->config()['description'];
+            if(!$description){
+                $description = $entity->getName();
+            }
+            $desc   = sl('lang')->abtr('template_desc',$description );
+
+            $this->availableValues[] = [
+                "key"   => $id,
+                "value" => $name,
+                'description' => $name != $desc ? $desc : null,
+            ];
+
+        }
+    }
+
+    private function loadLxcTemplates()
+    {
+        $defaultNode       = $this->defaultNode();
+        $storageRepository = new StorageRepository();
+        $storageRepository->findByNodes([$defaultNode])
+            ->findEnabed();
+        $fileRepository = new FileRepository();
+        $fileRepository->setApi($this->api());
+        $fileRepository->findLxcTemplates();
+        $fileRepository->findByNodes([$defaultNode]);
+        $fileRepository->findByStorages($storageRepository->fetchAsArray());
+        foreach ($fileRepository->fetch() as $file)
+        {
+            if ($this->configuration()->isPermissionOsTemplates() && !in_array($file->getVolid(), $this->configuration()->getPermissionOsTemplates()))
+            {
+                continue;
+            }
+            $this->availableValues[] = [
+                "key"   => $file->getVolid(),
+                "value" => sl('lang')->abtr('template', $file->getFriendlyName()),
+            ];
+        }
+    }
+
+
+}

+ 50 - 0
app/UI/VmCreate/Fields/SecondaryIsoImageSelect.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields;
+
+use MGProvision\Proxmox\v2\repository\FileRepository;
+use MGProvision\Proxmox\v2\repository\StorageRepository;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\AjaxFields\Select;
+
+class SecondaryIsoImageSelect extends Select implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function prepareAjaxData()
+    {
+        session_write_close();
+        //default node
+        if($this->getRequestValue('location')){
+            $defaultNode = $this->getRequestValue('location');
+        }else{
+            $defaultNode = $this->getNode()->getNode();
+        }
+        $storageRepository = new StorageRepository();
+        $storageRepository->findByNodes([$defaultNode])
+            ->findEnabed();
+        $storages            = $storageRepository->fetchAsArray();
+        $isoRepository = new FileRepository();
+        $isoRepository->findByNodes([$defaultNode])
+            ->findByStorages($storages);
+        $isoRepository->findIso();
+
+        foreach ($isoRepository->fetch() as $entity)
+        {
+            if ($this->configuration()->isPermissionSecondaryIsoImages() && !in_array($entity->getVolid(), $this->configuration()->getPermissionSecondaryIsoImages()))
+            {
+                continue;
+            }
+
+            $this->availableValues[]=[
+                "key" => $entity->getVolid(),
+                "value"     => $entity->getFriendlyName(),
+            ];
+        }
+    }
+
+
+}

+ 53 - 0
app/UI/VmCreate/Forms/VmCreateForm.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Providers\VmCreateProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\AdditionalDiskSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\Lxc;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\Qemu;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\TopSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\VirtualNetworkSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseStandaloneFormExtSections;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\RawSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BaseSection;
+
+class VmCreateForm extends BaseStandaloneFormExtSections implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->setFormType('create');
+        $this->setProvider(new VmCreateProvider());
+
+        $this->addSection(new TopSection());
+
+        if ($this->configuration()->isQemu())
+        {
+            $this->addSection((new Qemu\GeneralSection())->setMainContainer($this->mainContainer));
+        }
+        if ($this->configuration()->isLxc())
+        {
+            $this->addSection((new Lxc\GeneralSection())->setMainContainer($this->mainContainer));
+        }
+
+        $networks = (new VirtualNetworkSection())->setMainContainer($this->mainContainer);
+        $disks  = (new AdditionalDiskSection())->setMainContainer($this->mainContainer);
+
+        $netdisk = new HalfPageSection('netdisk');
+        $netdisk->setMainContainer($this->mainContainer);
+        $netdisk->addSection($networks);
+        $netdisk->addSection($disks);
+        $this->addSection($netdisk);
+
+        $this->loadDataToForm();
+    }
+
+
+}

+ 343 - 0
app/UI/VmCreate/Providers/VmCreateProvider.php

@@ -0,0 +1,343 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Providers;
+
+
+use MGProvision\Proxmox\v2\models\Kvm;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CloneQemuJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateLxcJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateQemuJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateSnippet;
+use ModulesGarden\ProxmoxAddon\App\Libs\Format;
+use ModulesGarden\ProxmoxAddon\App\Models\CloudInitScript;
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualInterface;
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\ProxmoxAddon\App\Services\Ip\Ipv4Range;
+use ModulesGarden\ProxmoxAddon\App\Services\Utility;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\BuildUrl;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\UrlServiceHelper;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\FileReader\Reader\Json;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ModuleConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseModelDataProvider;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\queue;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class VmCreateProvider extends BaseModelDataProvider implements ClientArea
+{
+    use ApiService;
+    use ProductService;
+
+
+    /**
+     * @var VmModel
+     */
+    protected $vmModel;
+    protected $vmTemplate;
+    /**
+     * VmUpdateProvider constructor.
+     */
+    public function __construct()
+    {
+        $this->model = VmModel::class;
+    }
+
+
+    public function read()
+    {
+         parent::read();
+        /**
+         * virtual network ip addresses
+         * @deprecated
+        foreach (VirtualNetwork::ofHostingId($this->getWhmcsParamByKey('serviceid'))->get() as $vn){
+            $ipRange = new Ipv4Range($vn->pool, $vn->cidr);
+            $ipRange->setLimit(10);
+            $ipRange->disableIpAddresses( $vn->virtualInterfaces->pluck('ip')->toArray());
+            $this->availableValues[sprintf("ip[%s]", $vn->id)] [0] = sl('lang')->abtr('None');
+            foreach (  $ipRange->get() as $ip ){
+                $this->availableValues[sprintf("ip[%s]", $vn->id)] [$ip] = $ip;
+            }
+        }
+         */
+        //location
+        foreach ($this->configuration()->getLocations() as $location){
+            $this->availableValues['location'] [$location] = sl('lang')->abtr('location', $location);
+        }
+        //ostype
+        $osTypes = $this->configuration()->getPermissionOstype();
+        if($osTypes){
+            $ostype = new Json('ostype.json', ModuleConstants::getFullPathWhmcs('modules', 'addons', 'proxmoxAddon', 'storage', 'app'));
+            foreach ($ostype->get() as $k => $ostype)
+            {
+                if(!in_array($k, $osTypes)){
+                    continue;
+                }
+                $this->availableValues["ostype"][$k] = sl('lang')->abtr('ostype',$ostype);
+            }
+        }
+        //cloudInitScript
+        if($this->configuration()->getCloudInitScript()){
+            $this->availableValues["cloudInitScript"] = CloudInitScript::ofIds($this->configuration()->getCloudInitScript())
+                      ->orderBy('name','asc')
+                      ->pluck('name','id')
+                      ->prepend(sl('lang')->abtr('None'),0)
+                      ->toArray();
+        }
+    }
+
+    public function create()
+    {
+        //Clone KVM check disk size
+        if($this->getJobClass() == CloneQemuJob::class && !$this->isDiskSizeValid()){
+            sl("lang")->addReplacementConstant("size", Format::convertBytes($this->vmTemplate->getMasterHardDisk()->getBytes()));
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('OS Template require disk size :size:');
+        }
+        $resurceManager = new ResourceManager();
+        //disk size validation
+        $diskResource =   $resurceManager ->disk();
+        $diskResource->setTotal($diskResource ->getTotal() - $this->formData['disk']);
+        $additonalDiskSize = $this->getAdditionalDiskTotalSize();
+        if($additonalDiskSize && $additonalDiskSize > $diskResource->freeTotal() ){
+            sl("lang")->addReplacementConstant("additional_disks_size",  $additonalDiskSize);
+            sl("lang")->addReplacementConstant("size", $diskResource->freeTotal());
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('You are not able to set :additional_disks_size: GB of the additional disks size. The available size is: :size: GB');
+        }
+        //ipv4
+        if($this->configuration()->serverIpv4->min &&  $this->configuration()->serverIpv4->min > $this->countPublicIpv4() ){
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('Select the Virtual Network with IPv4 address');
+        }
+        $this->vmModel = new VmModel();
+        $this->fillVmModel();
+        if($this->vmTemplate instanceof  Kvm){
+            $this->vmModel->data = ['osTemplate'=> $this->vmTemplate->status()['name']];
+        }else{
+            $this->vmModel->data = ['osTemplate'=> $this->formData['osTemplate']];
+        }
+        $this->vmModel->setPassword($this->formData['password']);
+        $this->vmModel->hosting_id = $this->getWhmcsParamByKey('serviceid');
+        unset($this->formData['password']);
+        $this->vmModel->virtualization = $this->configuration()->getVirtualization();
+        if($this->formData['location'] && in_array($this->formData['location'], $this->configuration()->getLocations())){
+            $this->vmModel->node = $this->formData['location'];
+        }else{
+            $this->vmModel->node = $this->getNode()->getNode();
+        }
+        if($this->configuration()->isCalculateSocketsAndCores()){
+            $this->calculateSocketsAndCores();
+        };
+        //init vm
+        $this->vmModel->save();
+        \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->setVmModel($this->vmModel);
+        $this->createJob();
+        //virtual interfaces
+        for($i=1; $i<=20; $i++){
+            if(!$this->formData['virtualNetwork'.$i]){
+                continue;
+            }
+            $ip = $this->formData['virtualNetwork'.$i]['ip'];
+            $virtualNetworkId = $this->formData['virtualNetwork'.$i]['id'];
+            //lock public ip
+            if(  $virtualNetworkId == 'public'){
+                VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                    ->ofIp($ip)
+                    ->update(['vm_id' => $this->vmModel->id ]);
+            }
+            $vi = new VirtualInterface();
+            $vi->ip = $ip;
+            $vi->ip_long = ip2long($ip);
+            $vi->vm_id = $this->vmModel->id;
+            $vi->vn_id = $virtualNetworkId=="public"? 0 : $virtualNetworkId;
+            $vi->hosting_id = $this->getWhmcsParamByKey('serviceid');
+            $vi->save();
+        }
+
+        /**
+         * @deprecated
+         $networkService = new NetworkService();
+        //ip validation
+        $networkService->hasIp((int)$this->formData['ipv4'], (int)$this->formData['ipv6'], $this->vmModel->node);
+        //assign IPs
+        $networkService->addIp((int)$this->formData['ipv4'], (int)$this->formData['ipv6'], $this->vmModel->node);
+        foreach ($this->formData['ip'] as $virtualNetworkId =>  $ip){
+            if($ip == 0){
+                continue;
+            }
+            //request validation
+            if(!VirtualNetwork::where('id', $virtualNetworkId)
+                ->ofHostingId($this->getWhmcsParamByKey('serviceid'))->count()){
+                throw new \InvalidArgumentException(sprintf("Virtual Network %s cannot be found", $virtualNetworkId));
+            }
+        }
+         */
+        return (new  HtmlDataJsonResponse())
+            ->setMessageAndTranslate('The process of Virtual Machine creation is in progress')
+            ->setCallBackFunction('pcVmCreatedAjaxDone')
+            ->addData('redirectUrl' , (new UrlServiceHelper())->home());
+
+    }
+
+    private function getJobClass(){
+        if($this->getFormDataValues()['osTemplate']  && $this->formData['osTemplate'] !='installationFromIso' && $this->configuration()->isQemu()){
+            return CloneQemuJob::class;
+        }elseif (  $this->configuration()->isQemu()){
+            return CreateQemuJob::class;
+        }else{
+            return CreateLxcJob::class;
+        }
+
+    }
+
+    protected function  getJobArguments(){
+        $arguments = $this->formData;
+        $arguments['hostingId'] =$this->getWhmcsParamByKey('serviceid');
+        return $arguments;
+    }
+
+    private function createJob(){
+        $jobClass = $this->getJobClass();
+        if($jobClass == CloneQemuJob::class  && $this->getFormDataValues()['cloudInitScript']){
+            $parent = queue(
+                CreateSnippet::class,
+                $this->getJobArguments(),
+                null,
+                "hosting",
+                $this->getWhmcsParamByKey("serviceid"),
+                $this->vmModel->id
+            );
+        }
+        return queue(
+            $this->getJobClass(),
+            $this->getJobArguments(),
+            $parent->id,
+            "hosting",
+            $this->getWhmcsParamByKey("serviceid"),
+            $this->vmModel->id
+        );
+    }
+
+
+    /**
+     * @deprecated
+     */
+    protected function requestValidation(){
+        //load form data
+        $this->getFormDataValues();
+        //ipv4
+        if(!$this->configuration()->isPermissionIpv4()){
+            $this->formData['ipv4'] = $this->configuration()->serverIpv4->min;
+        }
+        //ipv6
+        if(!$this->configuration()->isPermissionIpv6){
+            $this->formData['ipv6'] = $this->configuration()->serverIpv6->min;
+        }
+    }
+
+    private function isDiskSizeValid(){
+        list($node, $vmid) = explode("/", $this->formData['osTemplate']);
+        $this->vmTemplate = new Kvm($node, $vmid);
+        $this->vmTemplate->setApi($this->api());
+        $diskSizeBytes = $this->formData['disk'];
+        Utility::unitFormat($diskSizeBytes,'gb','bytes');
+        $this->templateDiskSizeBytes = $this->vmTemplate->getMasterHardDisk()->getBytes();
+        return $diskSizeBytes > $this->templateDiskSizeBytes;
+    }
+
+    protected function fillVmModel(){
+        $this->vmModel->fill($this->getFormDataValues());
+        //sockets
+        if( !$this->configuration()->isPermissionSockets()  && !$this->configuration()->isCalculateSocketsAndCores()){
+            $this->vmModel->sockets = $this->configuration()->serverSockets->min;
+        }
+        //cores
+        if( !$this->configuration()->isPermissionCores() && !$this->configuration()->isCalculateSocketsAndCores() ){
+            $this->vmModel->cores = $this->configuration()->serverCores->min;
+        }
+        //vcpus
+        if( !$this->configuration()->isPermissionVcpus() ){
+            $this->vmModel->vcpus = $this->configuration()->serverVcpus->min;
+        }
+        if($this->configuration()->isCalculateSocketsAndCores()){
+
+        }
+        //cpulimit
+        if( !$this->configuration()->isPermissionCpuLimit() && !$this->formData['cpuPriority']){
+            $this->vmModel->cpulimit = $this->configuration()->serverCpulimit->min;
+        }
+        //cpuunits
+        if( !$this->configuration()->isPermissionCpuunits() && !$this->formData['cpuPriority']){
+            $this->vmModel->cpuunits = $this->configuration()->serverCpuunit->min;
+        }
+        //swap
+        if( !$this->configuration()->isPermissionSwap() ){
+            $this->vmModel->swap = $this->configuration()->serverSwap->min;
+        }
+        //disks
+        $disks = (int) $this->getAdditionalDiskTotalSize();
+        if($disks || $this->configuration()->isDetailsCombinedView()){
+            $this->vmModel->disks = $disks;
+        }
+        //cpu prioryty
+        if($this->formData['cpuPriority']){
+            $this->vmModel->cpulimit = $this->configuration()->get('cpulimitPriority'.$this->formData['cpuPriority']);
+            $this->vmModel->cpuunits = $this->configuration()->get('cpuunitsPriority'.$this->formData['cpuPriority']);
+        }
+    }
+
+    private function getAdditionalDiskTotalSize()
+    {
+        $size = 0;
+        for ($i = 1; $i <= 10; $i++) {
+            $size += (int)$this->formData['additionalDiskSize' . $i];
+        }
+        return $size;
+    }
+
+    protected function calculateSocketsAndCores()
+    {
+        $cores =1;
+        $socket = 1;
+        $cpus = $this->configuration()->serverCores->max;
+        while($cpus > 0)
+        {
+            if($this->vmModel->vcpus % $cpus === 0 && $this->vmModel->vcpus / $cpus <= $this->configuration()->serverSockets->max)
+            {
+                $cores = $cpus;
+                $socket = $this->vmModel->vcpus / $cpus;
+            }
+            $cpus--;
+        }
+        $this->vmModel->cores =  $cores;
+        $this->vmModel->sockets = $socket;
+    }
+
+    public function countPublicIpv4(){
+        $total=0;
+        for($i=1; $i<=20; $i++){
+            if(!$this->formData['virtualNetwork'.$i]){
+                continue;
+            }
+            $ip = $this->formData['virtualNetwork'.$i]['ip'];
+            $virtualNetworkId = $this->formData['virtualNetwork'.$i]['id'];
+            //lock public ip
+            if($ip && !preg_match("/\:/", $ip) &&  $virtualNetworkId == 'public'){
+
+                $total++;
+            }
+        }
+        return $total;
+    }
+
+}

+ 34 - 0
app/UI/VmCreate/Sections/AccountSummary.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\AccountSummary\Providers\AccountSummaryProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Providers\VmCreateProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\AdditionalDiskSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\Lxc;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\Qemu;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\VirtualNetworkSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Builder\BaseContainer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseStandaloneFormExtSections;
+
+/**
+ * Class AccountSummary
+ * @package ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Forms
+ */
+class AccountSummary extends BaseContainer implements ClientArea
+{
+    use ProductService;
+
+    /**
+     *
+     */
+    public function initContent()
+    {
+        $provider = new AccountSummaryProvider();
+
+        $this->customTplVars['bars'] = $provider->read();
+    }
+}

+ 76 - 0
app/UI/VmCreate/Sections/AdditionalDiskSection.php

@@ -0,0 +1,76 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\DiskSizeValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BaseSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class AdditionalDiskSection extends BaseSection implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+
+        $this->initIds('additionalDiskSection');
+        $this->initFields();
+    }
+
+    public function initFields()
+    {
+        //size
+        $field = new Text('additionalDiskSize');
+        $field->addValidator(new DiskSizeValidator('disk',false));
+        $field->replaceClasses(['lu-col-md-6']);
+        $this->addField($field);
+        //bus
+        if($this->configuration()->isQemu()){
+            $field = new Select('additionalDiskBus');
+            $options=[];
+            foreach( $this->configuration()->getAdditionalDiskType() as $entery){
+                $options[$entery] = sl("lang")->abtr($entery);
+            }
+            $field->setAvailableValues($options);
+            $field->replaceClasses(['lu-col-md-6']);
+            $this->addField($field);
+        }
+        //format
+        if($this->configuration()->isQemu()){
+            $field = new Select('additionalDiskFormat');
+            $options=[];
+            foreach( $this->configuration()->getAdditionalDiskFormat() as $entery){
+                $options[$entery] = sl("lang")->abtr($entery);
+            }
+            $field->setAvailableValues($options);
+            $field->replaceClasses(['lu-col-md-6']);
+            $this->addField($field);
+        }
+        if($this->configuration()->isLxc()){
+            //mp
+            $field = new Text('additionalDiskMp');
+            $field->setPlaceholder("/some/path");
+            $field->replaceClasses(['lu-col-md-6']);
+            $this->addField($field);
+        }
+        //backup
+        if ($this->configuration()->isPermissionAdditionalDiskBackup())
+        {
+            $field = new Select('additionalDiskBackup');
+            $field->setAvailableValues([
+                'on' => 'Enable',
+                'off'=>'Disable',
+            ]);
+            $field->replaceClasses(['lu-col-md-6']);
+            $this->addField($field);
+        }
+    }
+}

+ 173 - 0
app/UI/VmCreate/Sections/Lxc/GeneralSection.php

@@ -0,0 +1,173 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\Lxc;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\CpulimitValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\HostnameValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\IpAddressValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\PasswordValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\SshPublicKeyValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields\OsTemplateSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\DiskSizeValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Range;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BaseSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class GeneralSection extends BaseSection
+{
+    use ProductService;
+
+    /**
+     * @var ResourceManager
+     */
+    protected $resourceManager;
+
+    public function initContent()
+    {
+        $this->initIds('generalSection');
+        $this->resourceManager = new ResourceManager();
+        $this->initFields();
+    }
+
+    public function initFields()
+    {
+        /**
+         * @deprecated
+         *
+         *
+        //name
+        $field = new Text('name');
+        $field->addValidator(new HostnameValidator());
+        $field->setDescription('description');
+        $this->addField($field);
+        //description
+        $field = new Textarea('description');
+        $field->setDescription('tip');
+        $this->addField($field);
+        //osTemplate
+        $field = new OsTemplateSelect('osTemplate');
+        $field->notEmpty();
+        $this->addField( $field);
+        //ipv4
+        if($this->configuration()->isPermissionIpv4()){
+        $field = new Text('ipv4');
+        $field->addValidator(new NumberValidator($this->resourceManager->ipv4()->getMin(), $this->resourceManager->ipv4()->free(),false));
+        $field->setDefaultValue($this->configuration()->serverIpv4->min);
+        $field->setDescription('description');
+        $this->addField($field);
+        }
+        //ipv6
+        if($this->configuration()->isPermissionIpv6()){
+        $field = new Text('ipv6');
+        $field->addValidator(new NumberValidator($this->resourceManager->ipv6()->getMin(), $this->resourceManager->ipv6()->free(),false));
+        $field->setDefaultValue($this->configuration()->serverIpv6->min);
+        $field->setDescription('description');
+        $this->addField($field);
+        }
+         */
+        $cpuPrioryty = $this->configuration()->hasCpuPriority();
+        //location
+        if($this->configuration()->getLocations()){
+            $field = new Select('location');
+            $field->notEmpty();
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cores
+        if($this->configuration()->isPermissionCores()){
+            $field = new Text('cores');
+            $field->addValidator(new NumberValidator($this->resourceManager->cores()->getMin(), $this->resourceManager->cores()->free(),true));
+            $field->setDefaultValue($this->configuration()->serverCores->min);
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cpu priority
+        if($cpuPrioryty){
+            $field = new Range('cpuPriority', $this->resourceManager->cpuPriority()->getMin(), $this->resourceManager->cpuPriority()->free());
+            $field->addValidator(new NumberValidator($this->resourceManager->cpuPriority()->getMin(), $this->resourceManager->cpuPriority()->free(),true));
+            $field->setDefaultValue($this->resourceManager->cpuPriority()->free() >= 3 ? 3 : 1);
+            $field->addHtmlAttribute('data-label1', sl('lang')->abtr("Very Low"));
+            $field->addHtmlAttribute('data-label2', sl('lang')->abtr("Low"));
+            $field->addHtmlAttribute('data-label3', sl('lang')->abtr("Normal"));
+            $field->addHtmlAttribute('data-label4', sl('lang')->abtr("High"));
+            $field->addHtmlAttribute('data-label5', sl('lang')->abtr("Medium"));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cpulimit
+        if($this->configuration()->isPermissionCpuLimit() && !$cpuPrioryty){
+            $field = new Text('cpulimit');
+            $field->addValidator(new CpulimitValidator($this->resourceManager->cpulimit()->getMin(), $this->resourceManager->cpulimit()->free(),true));
+            $field->setDefaultValue($this->configuration()->serverCpulimit->min);
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cpuunits
+        if($this->configuration()->isPermissionCpuunits() && !$cpuPrioryty){
+            $field = new Text('cpuunits');
+            $field->addValidator(new NumberValidator($this->resourceManager->cpuunits()->getMin(), $this->resourceManager->cpuunits()->free(),true));
+            $field->setDefaultValue($this->configuration()->serverCpuunit->min);
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //memory
+        $field = new Text('memory');
+        $field->addValidator(new NumberValidator($this->resourceManager->memory()->getMin(), $this->resourceManager->memory()->free(),true));
+        $field->setDefaultValue($this->configuration()->serverMemory->min);
+        $field->setDescription('description');
+        $this->addField($field);
+        //swap lxc only
+        if($this->configuration()->isPermissionSwap()){
+            $field = new Text('swap');
+            $field->addValidator(new NumberValidator($this->resourceManager->swap()->getMin(), $this->resourceManager->swap()->free(),true));
+            $field->setDefaultValue($this->configuration()->serverSwap->min);
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //disk
+        $field = new Text('disk');
+        $field->addValidator(new DiskSizeValidator('additionalDiskSize',true));
+        $field->setDefaultValue($this->configuration()->serverDiskSize->min);
+        $field->setDescription('description');
+        $this->addField($field);
+        //password
+        if($this->configuration()->isPermissionPassword()){
+            $field = new Text('password');
+            $field->addValidator(new PasswordValidator());
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //sshkey
+        if($this->configuration()->isPermissionSshkeys() && !$this->configuration()->isSshKeyPairs()){
+            $field = new Textarea('sshkeys');
+            $field->addValidator(new SshPublicKeyValidator(false));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+         //dnsdomain
+        if($this->configuration()->isPermissionSearchdomain()){
+            $field = new Text('searchdomain');
+            $field->addValidator(new HostnameValidator(false));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        if($this->configuration()->isPermissionNameservers()){
+            //ns1
+            $field = new Text('nameserver[0]');
+            $field->addValidator(new IpAddressValidator());
+            $field->setDescription('description');
+            $this->addField($field);
+            //ns2
+            $field = new Text('nameserver[1]');
+            $field->addValidator(new IpAddressValidator());
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+    }
+}

+ 223 - 0
app/UI/VmCreate/Sections/Qemu/GeneralSection.php

@@ -0,0 +1,223 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\Qemu;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\ProxmoxAddon\Core\Helper\AdvancedUserHelper;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\CpulimitValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\HostnameValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\IpAddressValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\SshPublicKeyValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields\IsoImageSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields\OsTemplateSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields\SecondaryIsoImageSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\DiskSizeValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\IsoImageValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\NameserverValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\PasswordValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\SearchdomainValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\UserValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Range;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BaseSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class GeneralSection extends HalfPageSection
+{
+    use ProductService;
+
+    /**
+     * @var ResourceManager
+     */
+    protected $resourceManager;
+
+    public function initContent()
+    {
+        $this->initIds('generalSection');
+        $this->resourceManager = new ResourceManager();
+        $this->initFields();
+    }
+
+    public function initFields()
+    {
+        $advancedUser = new AdvancedUserHelper($this->getWhmcsParamByKey('userid'));
+        /**
+         * @deprecated
+        //name
+        $field = new Text('name');
+        $field->setDescription('description');
+        $field->addValidator(new HostnameValidator());
+        $this->addField($field);
+        //description
+        $field = new Textarea('description');
+        $field->setDescription('tip');
+        $this->addField($field);
+         //osTemplate
+        if($this->configuration()->isPermissionOsTemplate()){
+        $field =new OsTemplateSelect('osTemplate');
+        $field->notEmpty();
+        $this->addField( $field);
+        }
+         */
+        $cpuPrioryty = $this->configuration()->hasCpuPriority();
+        //location
+        if($this->configuration()->getLocations()){
+            $field = new Select('location');
+            $field->notEmpty();
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //sockets
+        if($this->configuration()->isPermissionSockets() && !$this->configuration()->isCalculateSocketsAndCores()){
+            $field = new Text('sockets');
+            $field->addValidator(new NumberValidator($this->resourceManager->sockets()->getMin(), $this->resourceManager->sockets()->free(),true));
+            $field->setDefaultValue($this->configuration()->serverSockets->min);
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cores
+        if($this->configuration()->isPermissionCores() && !$this->configuration()->isCalculateSocketsAndCores()){
+            $field = new Text('cores');
+            $field->addValidator(new NumberValidator($this->resourceManager->cores()->getMin(), $this->resourceManager->cores()->free(),true));
+            $field->setDefaultValue($this->configuration()->serverCores->min);
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //vcpus
+        if($this->configuration()->isPermissionVcpus() || $this->configuration()->isCalculateSocketsAndCores()){
+            $field = new Range('vcpus', $this->resourceManager->vcpus()->getMin(), $this->resourceManager->vcpus()->free());
+            $field->addValidator(new NumberValidator($this->resourceManager->vcpus()->getMin(), $this->resourceManager->vcpus()->free(),true));
+            $field->setDefaultValue($this->configuration()->serverVcpus->min);
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cpu priority
+        if($cpuPrioryty){
+            $field = new Range('cpuPriority', $this->resourceManager->cpuPriority()->getMin(), $this->resourceManager->cpuPriority()->free());
+            $field->addValidator(new NumberValidator($this->resourceManager->cpuPriority()->getMin(), $this->resourceManager->cpuPriority()->free(),true));
+            $field->setDefaultValue($this->resourceManager->cpuPriority()->free() >= 3 ? 3 : 1);
+            $field->addHtmlAttribute('data-label1', sl('lang')->abtr("Very Low"));
+            $field->addHtmlAttribute('data-label2', sl('lang')->abtr("Low"));
+            $field->addHtmlAttribute('data-label3', sl('lang')->abtr("Normal"));
+            $field->addHtmlAttribute('data-label4', sl('lang')->abtr("High"));
+            $field->addHtmlAttribute('data-label5', sl('lang')->abtr("Medium"));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cpulimit
+        if($this->configuration()->isPermissionCpuLimit() && !$cpuPrioryty){
+            $field = new Text('cpulimit');
+            $field->addValidator(new CpulimitValidator($this->resourceManager->cpulimit()->getMin(), $this->resourceManager->cpulimit()->free(),true));
+            $field->setDefaultValue($this->configuration()->serverCpulimit->min);
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cpuunits
+        if($this->configuration()->isPermissionCpuunits() && !$cpuPrioryty){
+            $field = new Text('cpuunits');
+            $field->addValidator(new NumberValidator($this->resourceManager->cpuunits()->getMin(), $this->resourceManager->cpuunits()->free(),true));
+            $field->setDefaultValue($this->configuration()->serverCpuunit->min);
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //memory
+        $field = new Text('memory');
+        $field->addValidator(new NumberValidator($this->resourceManager->memory()->getMin(), $this->resourceManager->memory()->free(),true));
+        $field->setDefaultValue($this->configuration()->serverMemory->min);
+        $field->setDescription('description');
+        $this->addField($field);
+        //disk
+        $field = new Text('disk');
+        $field->addValidator(new DiskSizeValidator('additionalDiskSize',true));
+        $field->setDefaultValue($this->configuration()->serverDiskSize->min);
+        $field->setDescription('description');
+        $this->addField($field);
+        //username
+        if($this->configuration()->isPermissionUsername()){
+            $field = new Text('ciuser');
+            $field->addValidator(new UserValidator());
+            $field->setDefaultValue($this->configuration()->getCiuser());
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //password
+        if($this->configuration()->isPermissionPassword()){
+            $field = new Text('password');
+            $field->addValidator( new PasswordValidator());
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //sshkey
+        if($this->configuration()->isPermissionSshkeys()){
+            $field = new Textarea('sshkeys');
+            $field->addValidator(new SshPublicKeyValidator(false));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //dnsdomain
+        if($this->configuration()->isPermissionSearchdomain()){
+             $field = new Text('searchdomain');
+             $field->addValidator(new SearchdomainValidator(false));
+             $field->setDescription('description');
+             $this->addField($field);
+        }
+        if($this->configuration()->isPermissionNameservers()){
+            //ns1
+            $field = new Text('nameserver[0]');
+            $field->addValidator(new NameserverValidator());
+            $field->setDescription('description');
+            $this->addField($field);
+            //ns2
+            $field = new Text('nameserver[1]');
+            $field->addValidator(new NameserverValidator());
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //ostype
+        if(($advancedUser->isAdvanced() || $this->configuration()->isPermissionIsoImage()) && $this->configuration()->getPermissionOstype()){
+            $field = new  Select('ostype');
+            $this->addField($field);
+        }
+        //isoImage
+        if($this->configuration()->isPermissionIsoImage() && ($advancedUser->isAdvanced() || $this->configuration()->isPermissionIsoImage())){
+            $field = new IsoImageSelect('isoImage');
+            $field->addValidator(new IsoImageValidator());
+            $this->addField($field);
+        }
+        //secondaryIsoImage
+        if($this->configuration()->isPermissionSecondaryIsoImages() && $advancedUser->isAdvanced()){
+            $this->addField(new SecondaryIsoImageSelect('secondaryIsoImage'));
+
+        }
+        //cloudInitScript
+        if($this->configuration()->getCloudInitScript()){
+            $field = new Select('cloudInitScript');
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        /**
+         * @deprecated
+        //ipv4
+        if($this->configuration()->isPermissionIpv4()){
+            $field = new Text('ipv4');
+            $field->addValidator(new NumberValidator($this->resourceManager->ipv4()->getMin(), $this->resourceManager->ipv4()->free(),false));
+            $field->setDefaultValue($this->configuration()->serverIpv4->min);
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //ipv6
+        if($this->configuration()->isPermissionIpv6()){
+            $field = new Text('ipv6');
+            $field->addValidator(new NumberValidator($this->resourceManager->ipv6()->getMin(), $this->resourceManager->ipv6()->free(),false));
+            $field->setDefaultValue($this->configuration()->serverIpv6->min);
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+         */
+    }
+}

+ 44 - 0
app/UI/VmCreate/Sections/TopSection.php

@@ -0,0 +1,44 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections;
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\AccountSummary\Providers\AccountSummaryProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\HostnameValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields\OsTemplateSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\RawSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class TopSection extends RawSection
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        //name
+        $field = new Text('name');
+        $field->addValidator(new HostnameValidator());
+        $this->addField($field);
+        //osTemplate
+        if($this->configuration()->isPermissionOsTemplate() || $this->configuration()->isLxc()){
+            $field =new OsTemplateSelect('osTemplate');
+            $field->notEmpty();
+            $this->addField( $field);
+        }
+        //description
+        $field = new Textarea('description');
+        //$field->unsetShowTitle();
+        //$field->setPlaceholder(sl('lang')->tr('Description'));
+        $field->setRows(2);
+        $field->replaceClasses(['lu-m-t-1x lu-m-b-0x']);
+        $this->addField($field);
+
+        $provider = new AccountSummaryProvider();
+        $this->customTplVars['bars'] = $provider->read();
+
+    }
+}

+ 66 - 0
app/UI/VmCreate/Sections/VirtualNetworkSection.php

@@ -0,0 +1,66 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Ip\Ipv4Range;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonBase;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BaseSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class VirtualNetworkSection extends BaseSection implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('virtualNetworkSection');
+        $this->initFields();
+    }
+
+    public function initFields()
+    {
+        //virtualNetwork
+        $this->customTplVars['virtualNetwork'] = ["public" => sl('lang')->abtr('Public')];
+        //ips
+        $this->customTplVars['ips']=[];
+        //Public
+        $this->customTplVars['ipSelected'] =null;
+        foreach (VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))->ofVmIdNull()->get() as $ip)
+        {
+            if(!$this->customTplVars['ipSelected'] ){
+                $this->customTplVars['ipSelected']  = $ip->ip;
+            }
+            $this->customTplVars['ips'][] =[
+                "networkId" => "public",
+                "ip" => $ip->ip,
+                "id" => $ip->id
+            ];
+        }
+        if(empty($this->customTplVars['ips'])){
+            unset($this->customTplVars['virtualNetwork']['public']);
+        }
+        //private
+        foreach (VirtualNetwork::ofHostingId($this->getWhmcsParamByKey('serviceid'))->get() as $vn)
+        {
+            $this->customTplVars['virtualNetwork'][$vn->id] = $vn->name;
+            $ipRange = new Ipv4Range($vn->pool, $vn->cidr);
+            $ipRange->setLimit(255);
+            $ipRange->disableIpAddresses( $vn->virtualInterfaces->pluck('ip')->toArray());
+            foreach (  $ipRange->get() as $ip ){
+                $this->customTplVars['ips'][]=[
+                    "networkId" => $vn->id,
+                    "ip" => $ip,
+                ];
+            }
+        }
+
+
+    }
+}

+ 28 - 0
app/UI/VmCreate/Templates/sections/accountSummary.tpl

@@ -0,0 +1,28 @@
+<div class="lu-row">
+    <h4>
+        <span>{$MGLANG->absoluteT('serverCA' , 'createVM' ,'createNewVm')}</span>
+    </h4>
+    <div class="lu-widget">
+        <div class="lu-widget__header">
+            <div class="lu-widget__top lu-top">
+                <div class="lu-top__title">
+                    <span>{$MGLANG->absoluteT('serverCA' , 'createVM' ,'availableResources')}</span>
+                </div>
+            </div>
+        </div>
+        <div class="lu-widget__body">
+            <div class="lu-widget__content">
+                {foreach from=$customTplVars.bars item=bar}
+                    <div class="lu-progress lu-progress--h lu-progress--s lu-progress__label">
+                        <div class="lu-progress__label">
+                            {$bar.name} ({$bar.used}/{$bar.max}{if $bar.unit} {$bar.unit}{/if})
+                        </div>
+                        <div class="lu-progress__bar progress-bar-danger">
+                            <div class="lu-progress__fill" style="width: {$bar.value}%"></div>
+                        </div>
+                    </div>
+                {/foreach}
+            </div>
+        </div>
+    </div>
+</div>

+ 70 - 0
app/UI/VmCreate/Templates/sections/additionalDiskSection.tpl

@@ -0,0 +1,70 @@
+{**********************************************************************
+* ProxmoxCloudVps product developed. (2017-10-06)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+**********************************************************************}
+
+{**
+* @author Sławomir Miśkowicz <slawomir@modulesgarden.com>
+*}
+
+<div class="lu-widget">
+    <div class="lu-widget__body">
+        {if $rawObject->isShowTitle() && (($rawObject->getRawTitle() || $rawObject->getTitle()) && $rawObject->isViewHeader())}
+            <div class="lu-widget__header">
+                <div class="lu-widget__top lu-top">
+                    <div class="lu-top__title">
+                        {if $rawObject->getIcon()}<i class="{$rawObject->getIcon()}"></i>{/if}
+                        {if $rawObject->isRawTitle()}{$rawObject->getRawTitle()}{elseif $rawObject->getTitle()}{$MGLANG->T($rawObject->getTitle())}{/if}
+                    </div>
+                    <div class="lu-top__toolbar"><a href="#" id="pm-add-disk-button" data-toggle="lu-tooltip" class="lu-btn lu-btn--primary" data-title="{$MGLANG->T('Add New Additional Disk')}">
+                            <i class="lu-zmdi lu-zmdi-plus"></i>
+                            <span class="lu-btn__text">{$MGLANG->T('Add New Additional Disk')}</span>
+                        </a>
+                    </div>
+                </div>
+            </div>
+        {/if}
+        <div class="lu-widget__content lu-p-1x">
+            <div class="lu-alert lu-alert--outline lu-alert--icon lu-alert--info lu-alert--bordered lu-m-b-0x lu-alert--dismiss mg-message ">
+                <div class="lu-alert__body">
+                    {$MGLANG->T('additional_disk_add_info')}
+                </div>
+            </div>
+            <div class="lu-widget hidden pm-disk-content-default" >
+                <div class="lu-widget__body">
+                    <div class="lu-widget__header">
+                        <div class="lu-widget__top lu-top">
+                            <div class="lu-top__title">
+                                {$MGLANG->T('Additional Disk')}
+                            </div>
+                            <div class="lu-top__toolbar">
+                                <a href="#"
+                                        class="lu-btn lu-btn--xs lu-btn--default lu-btn--icon lu-btn--link lu-btn--plain pm-delete-disk-button">
+                                    <i class="lu-btn__icon lu-zmdi lu-zmdi-close"></i>
+                                </a>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="lu-widget__content lu-row">
+                        {foreach from=$rawObject->getFields() item=field }
+                            {$field->getHtml()}
+                        {/foreach}
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

+ 43 - 0
app/UI/VmCreate/Templates/sections/lxc/generalSection.tpl

@@ -0,0 +1,43 @@
+{**********************************************************************
+* ProxmoxCloudVps product developed. (2017-10-06)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+**********************************************************************}
+
+{**
+* @author Sławomir Miśkowicz <slawomir@modulesgarden.com>
+*}
+<div class="lu-col-md-6">
+<div class="lu-widget">
+    <div class="lu-widget__body">
+        {if $rawObject->isShowTitle() && (($rawObject->getRawTitle() || $rawObject->getTitle()) && $rawObject->isViewHeader())}
+            <div class="lu-widget__header">
+                <div class="lu-widget__top lu-top">
+                    <div class="lu-top__title">
+                        {if $rawObject->getIcon()}<i class="{$rawObject->getIcon()}"></i>{/if}
+                        {if $rawObject->isRawTitle()}{$rawObject->getRawTitle()}{elseif $rawObject->getTitle()}{$MGLANG->T($rawObject->getTitle())}{/if}
+                    </div>
+                </div>
+            </div>
+        {/if}
+        <div class="lu-widget__content">
+            {foreach from=$rawObject->getFields() item=field }
+                {$field->getHtml()}
+            {/foreach}
+        </div>
+
+    </div>
+</div>
+</div>

+ 43 - 0
app/UI/VmCreate/Templates/sections/qemu/generalSection.tpl

@@ -0,0 +1,43 @@
+{**********************************************************************
+* ProxmoxCloudVps product developed. (2017-10-06)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+**********************************************************************}
+
+{**
+* @author Sławomir Miśkowicz <slawomir@modulesgarden.com>
+*}
+<div class="lu-col-md-6">
+<div class="lu-widget">
+    <div class="lu-widget__body">
+        {if $rawObject->isShowTitle() && (($rawObject->getRawTitle() || $rawObject->getTitle()) && $rawObject->isViewHeader())}
+            <div class="lu-widget__header">
+                <div class="lu-widget__top lu-top">
+                    <div class="lu-top__title">
+                        {if $rawObject->getIcon()}<i class="{$rawObject->getIcon()}"></i>{/if}
+                        {if $rawObject->isRawTitle()}{$rawObject->getRawTitle()}{elseif $rawObject->getTitle()}{$MGLANG->T($rawObject->getTitle())}{/if}
+                    </div>
+                </div>
+            </div>
+        {/if}
+        <div class="lu-widget__content">
+            {foreach from=$rawObject->getFields() item=field }
+                {$field->getHtml()}
+            {/foreach}
+        </div>
+
+    </div>
+</div>
+</div>

+ 58 - 0
app/UI/VmCreate/Templates/sections/topSection.tpl

@@ -0,0 +1,58 @@
+<div class="lu-col-md-12">
+    <h3>{$MGLANG->tr('Create New Virtual Machine')}</h3>
+</div>
+
+<div class="lu-col-md-6">
+    <div class="lu-widget">
+        <div class="lu-widget__header">
+            <div class="lu-widget__top lu-top">
+                <div class="lu-top__title">
+                    <span>{$MGLANG->tr('virtualMachineSettings')}</span>
+                </div>
+            </div>
+        </div>
+        <div class="lu-widget__body">
+            <div class="lu-widget__content">
+                {*name*}
+                {$rawObject->getField('name')}
+                {*type*}
+                {$rawObject->getField('osTemplate')}
+                {*description*}
+                {$rawObject->getField('description')}
+            </div>
+        </div>
+    </div>
+</div>
+
+<div class="lu-col-md-6">
+    <div class="lu-widget">
+        <div class="lu-widget__header">
+            <div class="lu-widget__top lu-top">
+                <div class="lu-top__title">
+                    <span>{$MGLANG->tr('availableResources')}</span>
+                </div>
+            </div>
+        </div>
+        <div class="lu-widget__body">
+            <div class="lu-widget__content">
+                {foreach from=$customTplVars.bars item=bar}
+                    <div class="lu-progress lu-progress--h lu-progress--s lu-progress__label">
+                        <div class="lu-progress__label">
+                            {$bar.name}
+                            <i data-title="{$bar.used}/{$bar.max}{if $bar.unit} {$bar.unit}{/if}" data-toggle="lu-tooltip" class="lu-i-c-2x lu-zmdi lu-zmdi-help-outline lu-form-tooltip-helper lu-tooltip "></i>
+                        </div>
+                        <div class="lu-progress__bar progress-bar-danger">
+                            <div class="lu-progress__fill" style="width: {$bar.value}%"></div>
+                        </div>
+                    </div>
+                {/foreach}
+            </div>
+        </div>
+    </div>
+</div>
+
+
+
+<div class="lu-col-md-12">
+    <hr class="lu-m-b-2x lu-m-t-1x"/>
+</div>

+ 81 - 0
app/UI/VmCreate/Templates/sections/virtualNetworkSection.tpl

@@ -0,0 +1,81 @@
+{**********************************************************************
+* ProxmoxCloudVps product developed. (2017-10-06)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+**********************************************************************}
+
+{**
+* @author Sławomir Miśkowicz <slawomir@modulesgarden.com>
+*}
+<div class="lu-widget">
+    <div class="lu-widget__body">
+        {if $rawObject->isShowTitle() && (($rawObject->getRawTitle() || $rawObject->getTitle()) && $rawObject->isViewHeader())}
+            <div class="lu-widget__header">
+                <div class="lu-widget__top lu-top">
+                    <div class="lu-top__title">
+                        {if $rawObject->getIcon()}<i class="{$rawObject->getIcon()}"></i>{/if}
+                        {if $rawObject->isRawTitle()}{$rawObject->getRawTitle()}{elseif $rawObject->getTitle()}{$MGLANG->T($rawObject->getTitle())}{/if}
+                    </div>
+                <div class="lu-top__toolbar"><a href="#" id="pm-add-new-virtual-network-button" data-toggle="lu-tooltip" class="lu-btn lu-btn--primary" data-title="{$MGLANG->T('Add New Virtual Network')}">
+                        <i class="lu-zmdi lu-zmdi-plus"></i>
+                        <span class="lu-btn__text">{$MGLANG->T('Add New Virtual Network')}</span>
+                    </a></div>
+                </div>
+            </div>
+        {/if}
+        <div class="lu-widget__content lu-p-1x">
+            <div class="lu-alert lu-alert--outline lu-alert--icon lu-alert--info lu-alert--bordered lu-m-b-0x lu-alert--dismiss mg-message">
+                <div class="lu-alert__body">
+                    {$MGLANG->T('additional_ip_add_info')}
+                </div>
+            </div>
+            <div class="lu-widget hidden pm-virtual-network-content-default" >
+                <div class="lu-widget__body">
+                    <div class="lu-widget__header">
+                        <div class="lu-widget__top lu-top">
+                            <div class="lu-top__title">
+                                {$MGLANG->T('Virtual Network')}
+                            </div>
+                            <div class="lu-top__toolbar">
+                                <a href="#"
+                                        class="lu-btn lu-btn--xs lu-btn--default lu-btn--icon lu-btn--link lu-btn--plain pm-delete-virtual-network-button">
+                                    <i class="lu-btn__icon lu-zmdi lu-zmdi-close"></i>
+                                </a>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="lu-widget__content lu-row">
+                        <div class="lu-form-group lu-col-md-6">
+                            <label class="lu-form-label">{$MGLANG->T('Select Virtual Network')}</label>
+                            <select name="virtualNetwork[id]" class="lu-form-control pm-vn-select">
+                                {foreach from=$customTplVars.virtualNetwork key=opValue item=option}
+                                    <option value="{$opValue}">{$option}</option>
+                                {/foreach}
+                            </select>
+                        </div>
+                        <div class="lu-form-group lu-col-md-6">
+                            <label class="lu-form-label">{$MGLANG->T('Select IP Address')}</label>
+                            <select name="virtualNetwork[ip]" class="lu-form-control  pm-vn-ip-select">
+                                {foreach from=$customTplVars.ips key=opValue item=option}
+                                    <option class="vn-ip-{$option.networkId}" {if $option.networkId!="public"}style="display: none;"{/if}  {if $option.ip == $customTplVars.ipSelected}selected{/if}  value="{$option.ip}">{$option.ip}</option>
+                                {/foreach}
+                            </select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

+ 84 - 0
app/UI/VmCreate/Validators/DiskSizeValidator.php

@@ -0,0 +1,84 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators;
+
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+class DiskSizeValidator extends BaseValidator
+{
+    protected $additionalField;
+    protected $minValue = 0;
+    protected $maxValue = 0;
+    protected $required = true;
+
+    public function __construct( $additionalField, $required = true)
+    {
+        $this->additionalField = $additionalField;
+        $this->required = $required;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        $resurceManager = new ResourceManager();
+        $additionalSize = 0;
+        if($additionalData->get('formData')[$this->additionalField] ){
+            $additionalSize = (int) $additionalData->get('formData')[$this->additionalField];
+        }
+        $diskResource =    $resurceManager ->disk();
+        $diskResource->setTotal($diskResource->getTotal()-$additionalSize);
+        $this->maxValue = $diskResource->free();
+        $this->minValue =  $diskResource->getMin();
+
+        if(preg_match("/\./", $data)){
+            $this->addValidationError('PleaseProvideANumericValueBetween', false, ['minValue' => $this->minValue, 'maxValue' => $this->maxValue]);
+            return false;
+        }
+        if (is_numeric($data) && $this->minValue === 0 && $this->maxValue === 0)
+        {
+            return true;
+        }
+        //Min & Max
+        if (is_numeric($data) && $this->minValue <= ((int)$data) && ((int)$data) <= $this->maxValue)
+        {
+            return true;
+        }
+        //Min
+        else
+        {
+            if (is_numeric($data) && !is_numeric($this->maxValue) && $this->minValue <= ((int)$data))
+            {
+                return true;
+            }
+        }
+
+        if ($this->minValue === $this->maxValue)
+        {
+            $this->addValidationError('PleaseProvideANumericValue');
+
+            return false;
+        }
+
+        if (is_numeric($this->minValue) && is_numeric($this->maxValue))
+        {
+            $this->addValidationError('PleaseProvideANumericValueBetween', false, ['minValue' => $this->minValue, 'maxValue' => $this->maxValue]);
+        }
+        else
+        {
+            if (is_numeric($this->minValue) && !is_numeric($this->maxValue))
+            {
+                $this->addValidationError('PleaseProvideANumericValueFrom', false, ['minValue' => $this->minValue]);
+            }
+        }
+
+
+        return false;
+    }
+
+}

+ 31 - 0
app/UI/VmCreate/Validators/IsoImageValidator.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+class IsoImageValidator extends BaseValidator
+{
+
+    protected function validate($data, $additionalData = null)
+    {
+        if($additionalData->get('formData')['osTemplate'] && $additionalData->get('formData')['osTemplate']!='installationFromIso' ){
+            return true;
+        }
+
+        if (is_array($data) && count($data) > 0)
+        {
+            return true;
+        }
+
+        if ((is_string($data) && strlen(trim($data)) > 0) || is_numeric($data))
+        {
+            return true;
+        }
+
+        $this->addValidationError('thisFieldCannotBeEmpty');
+
+        return false;
+    }
+
+}

+ 42 - 0
app/UI/VmCreate/Validators/NameserverValidator.php

@@ -0,0 +1,42 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+class NameserverValidator extends BaseValidator
+{
+    protected $required = false;
+    protected $public = true;
+
+    public function __construct($required = false , $public = true)
+    {
+        $this->required = $required;
+        $this->public = $public;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if($additionalData->get('formData')['osTemplate'] && $additionalData->get('formData')['osTemplate']=='installationFromIso' ){
+            return true;
+        }
+
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        if (!filter_var($data, FILTER_VALIDATE_IP))
+        {
+            $this->addValidationError('IP Address is not valid', false);
+            return false;
+        }
+        if (!$this->public && filter_var($data, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE))
+        {
+            $this->addValidationError('The IP Address is not private', false);
+            return false;
+        }
+        return true;
+    }
+}

+ 62 - 0
app/UI/VmCreate/Validators/PasswordValidator.php

@@ -0,0 +1,62 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class PasswordValidator extends BaseValidator
+{
+    protected $required = false;
+    protected $length;
+
+    public function __construct($required = true, $length = 5)
+    {
+        $this->required = $required;
+        $this->length   = $length;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if($additionalData->get('formData')['osTemplate'] && $additionalData->get('formData')['osTemplate']=='installationFromIso' ){
+            return true;
+        }
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        else
+        {
+            if (is_numeric($this->length) && strlen($data) < $this->length)
+            {
+                $this->addValidationError('The password is too short');
+                return false;
+            }
+        }
+
+        return true;
+    }
+}

+ 28 - 0
app/UI/VmCreate/Validators/SearchdomainValidator.php

@@ -0,0 +1,28 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+class SearchdomainValidator extends BaseValidator
+{
+
+    protected function validate($data, $additionalData = null)
+    {
+        if($additionalData->get('formData')['osTemplate'] && $additionalData->get('formData')['osTemplate']=='installationFromIso' ){
+            return true;
+        }
+        if (empty($data))
+        {
+            return true;
+        }
+        if (!preg_match('/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/', $data))
+        {
+            $this->addValidationError('PleaseProvideASearchdomain');
+            return false;
+        }
+        return true;
+    }
+}

+ 60 - 0
app/UI/VmCreate/Validators/SshPublicKeyValidator.php

@@ -0,0 +1,60 @@
+<?php
+
+/* * ********************************************************************
+ * ProxmoxAddon product developed. (Aug 23, 2018)
+ * *
+ *
+ *  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+ *  CONTACT                        ->       contact@modulesgarden.com
+ *
+ *
+ * This software is furnished under a license and may be used and copied
+ * only  in  accordance  with  the  terms  of such  license and with the
+ * inclusion of the above copyright notice.  This software  or any other
+ * copies thereof may not be provided or otherwise made available to any
+ * other person.  No title to and  ownership of the  software is  hereby
+ * transferred.
+ *
+ *
+ * ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+/**
+ * Description of NumberValidator
+ *
+ * @author Pawel Kopec <pawelk@modulesgardne.com>
+ */
+class SshPublicKeyValidator extends BaseValidator
+{
+    protected $required = false;
+
+    public function __construct($required = true)
+    {
+        $this->required = $required;
+    }
+
+    protected function validate($data, $additionalData = null)
+    {
+        if($additionalData->get('formData')['osTemplate'] && $additionalData->get('formData')['osTemplate']=='installationFromIso' ){
+            return true;
+        }
+        if (!$this->required && empty($data))
+        {
+            return true;
+        }
+        else
+        {
+            if (!preg_match('/ssh\-/', $data))
+            {
+                $this->addValidationError('PleaseProvideASshPublicKey');
+                return false;
+            }
+        }
+
+        return true;
+    }
+}

+ 31 - 0
app/UI/VmCreate/Validators/UserValidator.php

@@ -0,0 +1,31 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+class UserValidator extends BaseValidator
+{
+    protected function validate($data, $additionalData = null)
+    {
+        if($additionalData->get('formData')['osTemplate'] && $additionalData->get('formData')['osTemplate']=='installationFromIso' ){
+            return true;
+        }
+
+        if (is_array($data) && count($data) > 0)
+        {
+            return true;
+        }
+
+        if ((is_string($data) && strlen(trim($data)) > 0) || is_numeric($data))
+        {
+            return true;
+        }
+
+        $this->addValidationError('thisFieldCannotBeEmpty');
+
+        return false;
+    }
+}

+ 62 - 0
app/UI/VmUpdate/Forms/VmUpdateForm.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Forms;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Providers\VmUpdateProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Sections\Qemu\AdditionalDiskSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Sections\Lxc;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Sections\Qemu;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Sections\VirtualNetworkSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseStandaloneFormExtSections;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+
+class VmUpdateForm extends  BaseStandaloneFormExtSections implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->unsetShowTitle();
+        $this->title = null;
+        $this->addClass("lu-col-md-12");
+
+        $this->setFormType('update');
+        $this->setProvider(new VmUpdateProvider());
+        //standard
+        if($this->configuration()->isQemu() && !$this->configuration()->isDetailsCombinedView()){
+            $this->addSection((new Qemu\GeneralSection())->setMainContainer($this->mainContainer));
+        }
+        if($this->configuration()->isLxc() && !$this->configuration()->isDetailsCombinedView()){
+            $this->addSection((new Lxc\GeneralSection())->setMainContainer($this->mainContainer));
+        }
+        //combined
+        if($this->configuration()->isDetailsCombinedView()){
+            //rightSection
+            $rightSection = new HalfPageSection('rightSection');
+            $rightSection->setMainContainer($this->mainContainer);
+            //network
+            $rightSection->addSection((new VirtualNetworkSection())->setMainContainer($this->mainContainer));
+            //kvm
+            if($this->configuration()->isQemu()){
+                $this->addSection((new Qemu\GeneralCombinedSection())->setMainContainer($this->mainContainer));
+                //disk
+                $rightSection->addSection((new Qemu\AdditionalDiskSection())->setMainContainer($this->mainContainer));
+            }
+            //lxc
+            if($this->configuration()->isLxc()){
+                $this->addSection((new Lxc\GeneralCombinedSection())->setMainContainer($this->mainContainer));
+                //disk
+                $rightSection->addSection((new Lxc\AdditionalDiskSection())->setMainContainer($this->mainContainer));
+            }
+            $this->addSection($rightSection);
+
+
+
+        }
+        $this->loadDataToForm();
+    }
+
+
+}

+ 368 - 0
app/UI/VmUpdate/Providers/VmUpdateProvider.php

@@ -0,0 +1,368 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Providers;
+
+
+use Illuminate\Database\Capsule\Manager as DB;
+use MGProvision\Proxmox\v2\Api;
+use MGProvision\Proxmox\v2\models\Kvm;
+use MGProvision\Proxmox\v2\models\MountPoint;
+use MGProvision\Proxmox\v2\models\NetworkDeviceKvm;
+use MGProvision\Proxmox\v2\repository\FileRepository;
+use MGProvision\Proxmox\v2\repository\StorageRepository;
+use ModulesGarden\ProxmoxAddon\App\Events\Cloud\LxcUpdateEvent;
+use ModulesGarden\ProxmoxAddon\App\Events\Cloud\QemuUpdateEvent;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Agent\ChangePasswordJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Agent\ConfigureNetworkJob;
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualInterface;
+use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\AdditionalDiskService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\AdditionalMountPointService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\AgentService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\IpSetIpFilterService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\VirtualInterfaceConverter;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Providers\VmCreateProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use function ModulesGarden\ProxmoxAddon\Core\Helper\fire;
+use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class VmUpdateProvider extends VmCreateProvider
+{
+    use ApiService;
+    use ProductService;
+
+
+    /**
+     * VmUpdateProvider constructor.
+     */
+    public function __construct()
+    {
+        $this->model = VmModel::class;
+    }
+
+
+    public function read()
+    {
+        $this->vmModel = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
+        $this->data =  $this->vmModel->toArray();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $config = $vm->config();
+        $this->data['password'] = $this->vmModel->getPassword();
+        $this->data['description'] = html_entity_decode($config['description']);
+        $this->data['searchdomain'] = $config['searchdomain'];
+        $ns = explode(" ",$config['nameserver']);
+        $this->data['nameserver[0]'] = $ns[0];
+        $this->data['nameserver[1]'] = $ns[1];
+        /**
+         * @deprecated
+        $this->data['ipv4'] = $this->vmModel->ipv4Addresses->count();
+        $this->data['ipv6'] = $this->vmModel->ipv6Addresses->count();
+         */
+        //Boot order
+        if($vm instanceof Kvm){
+            $bootOrder                           = $vm->getBootOrder();
+            $this->data['bootOrder0']            = $bootOrder[0];
+            $this->data['bootOrder1']            = $bootOrder[1];
+            $this->data['bootOrder2']            = $bootOrder[2];
+            $options                             = [
+                0   => sl("lang")->tr("None"),
+                "c" => sl("lang")->tr("Disk"),
+                "d" => sl("lang")->tr("CD-ROM"),
+                "n" => sl("lang")->tr("Network"),
+            ];
+            if(version_compare($this->api()->getVersion(), "6.3", '>=')
+            && !in_array("c", (array) $bootOrder )){
+                $cdrom = $vm->cdrom();
+                $nd = $vm->getNetworkDevices();
+                $options                             = [
+                    0   => sl("lang")->tr("None"),
+                    $vm->getMasterHardDisk()->getId() => sl("lang")->tr("Disk"),
+                ];
+                if($cdrom['bus']){
+                    $options[$cdrom['bus']] = sl("lang")->tr("CD-ROM");
+                }
+                if($nd[0] instanceof  NetworkDeviceKvm){
+                    $options[$nd[0]->getId()] = sl("lang")->tr("Network");
+                }
+            }
+            $this->availableValues['bootOrder0'] = $options;
+            $this->availableValues['bootOrder1'] = $options;
+            $this->availableValues['bootOrder2'] = $options;
+        }
+        //sshkeys
+        $this->data['sshkeys'] = rawurldecode($vm->config()['sshkeys']);
+        //cpu Priority
+        if($this->configuration()->hasCpuPriority()){
+            for($i=1; $i<=5; $i++){
+                $cpuunits = $this->configuration()->get('cpuunitsPriority'.$i);
+                $cpulimit = $this->configuration()->get('cpulimitPriority'.$i);
+                if($this->vmModel->cpulimit >= $cpulimit){
+                    $this->data['cpuPriority'] = $i;
+                }
+                if($this->vmModel->cpuunits >= $cpuunits){
+                    $this->data['cpuPriority'] = $i;
+                }
+            }
+        }
+        //iso
+        if ($this->configuration()->isQemu() && $this->configuration()->isPermissionIsoImage()) {
+            $this->availableValues['iso'] = ["none" => sl('lang')->abtr("None")];
+            $storageRepository = new StorageRepository();
+            $storageRepository->findByNodes([$vm->getNode()])
+                ->findEnabed();
+            $storages = $storageRepository->fetchAsArray();
+            $isoRepository = new FileRepository();
+            $isoRepository->findByNodes([$vm->getNode()])
+                ->findByStorages($storages);
+            $isoRepository->findIso();
+            foreach ($isoRepository->fetch() as $entity) {
+                if ($this->configuration()->isPermissionIsoImages() && !in_array($entity->getVolid(), $this->configuration()->getPermissionIsoImages())) {
+                    continue;
+                }
+                $this->availableValues['iso'][$entity->getVolid()] = $entity->getFriendlyName();
+            }
+            if( $vm->getCdRomRepository()->first()){
+                $this->data['iso']= $vm->getCdRomRepository()->first()->getLocation();
+            }
+        }
+
+
+
+    }
+
+    public function update()
+    {
+        $this->vmModel = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $this->networkService = new NetworkService();
+        $networkService = new NetworkService();
+        /**
+         * @deprecated
+         * $ipv4 = (int) $this->formData['ipv4'] - (int)  $this->vmModel->ipv4Addresses->count();
+         * $ipv6  = (int) $this->formData['ipv6'] - (int)  $this->vmModel->ipv6Addresses->count();
+         * $networkService->hasIp($ipv4, $ipv6, $this->vmModel->node);
+         * $networkService->addIp($ipv4, $ipv6, $this->vmModel->node);
+         * $networkService->unassignIpAddressesAndDeleteNetwork($ipv4, $ipv6);
+         */
+
+        //load data
+        $this->getFormDataValues();
+        if ($vm instanceof Kvm)
+        {
+            //iso
+            if ($vm->cdrom())
+            {
+                $vm->updateCdrom($this->formData['iso']);
+            }
+            //Boot order
+            $bootOrder = null;
+            $order = [];
+            for ($i = 0; $i <= 2; $i++)
+            {
+                if ($this->formData['bootOrder' . $i])
+                {
+                    $bootOrder .= $this->formData['bootOrder' . $i];
+                    if(!in_array($this->formData['bootOrder' . $i],["c","d","n"])){
+                        $order[] = $this->formData['bootOrder' . $i];
+                    }
+                }
+            }
+            if(version_compare($this->api()->getVersion(), "6.3", '>=') && !empty($order)){
+                //order=scsi0;ide0;ide1;net0
+                $vm->updateConfig(['boot' => "order=".implode(";", $order)]);
+            }else{
+                $vm->changeBootOrder($bootOrder);
+            }
+            //sshkeys
+            if($this->configuration()->isPermissionSshkeys()){
+                if ($this->formData['sshkeys'])
+                {
+                    $vm->updateConfig(["sshkeys" => rawurlencode($this->formData['sshkeys'])]);
+                } else if($vm->config()['sshkeys'])
+                {
+                    $vm->deleteConfig('sshkeys');
+                }
+            }
+        }
+        try{
+            Api::beginTransaction();
+            DB::beginTransaction();
+            $this->fillVmModel();
+            if($this->getFormDataValues()['password']){
+                $this->vmModel->setPassword($this->getFormDataValues()['password']);
+            }
+            if($this->configuration()->isCalculateSocketsAndCores()){
+                $this->calculateSocketsAndCores();
+            }
+            $this->vmModel->save();
+            if($this->configuration()->isQemu()){
+                fire(new QemuUpdateEvent($this->vmModel, $this->formData));
+            }
+            if($this->configuration()->isLxc()){
+                fire(new LxcUpdateEvent($this->vmModel, $this->formData));
+            }
+            if ($this->configuration()->isDetailsCombinedView()) {
+                //virtual interfaces
+                $this->virtualNetworkUpdate();
+                //IP Set
+                if ($this->configuration()->isIpsetIpFilter()){
+                    $ipSetFilterService =  new IpSetIpFilterService();
+                    $ipSetFilterService->create();
+                }
+                //disks
+                $this->disksUpdate();
+
+            }
+            $agentEnabled = (new AgentService())->isEnabled();
+            if($agentEnabled && $this->configuration()->isAgentConfigureNetwork()){
+                queue(ConfigureNetworkJob::class,
+                    ['hostingId' => $this->getWhmcsParamByKey('serviceid')],
+                    null,
+                    "hosting",
+                    $this->getWhmcsParamByKey("serviceid"),
+                    $this->vmModel->id
+                );
+            }
+            if($agentEnabled && $this->configuration()->isAgentPassword()){
+                queue(ChangePasswordJob::class,
+                    ['hostingId' => $this->getWhmcsParamByKey('serviceid')],
+                    null,
+                    "hosting",
+                    $this->getWhmcsParamByKey("serviceid"),
+                    $this->vmModel->id
+                );
+            }
+            DB::commit();
+            return (new  HtmlDataJsonResponse())
+                ->setMessageAndTranslate('Server has been updated')
+                ->setCallBackFunction('pcVmUpdatedAjaxDone')
+                ->addRefreshTargetId('serviceInformationDataTable')
+                ->setCallBackFunction('mgLocationReload');
+        }catch (\Exception $ex){
+            DB::rollBack();
+            Api::commit();
+            return (new  HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate($ex->getMessage());
+        }
+
+    }
+
+    private function virtualNetworkUpdate()
+    {
+        try {
+
+            $viIds = [];
+            //delete
+            for ($i = 0; $i <= 20; $i++) {
+                if ($this->formData['virtualInterface' . $i]) {
+                    $viIds[] = $this->formData['virtualInterface' . $i]['id'];
+                }
+            }
+            $virtualInterfaces = VirtualInterface::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                ->ofVmId($this->vmModel->id);
+            if ($viIds) {
+                $virtualInterfaces->notId($viIds);
+            }
+            $this->networkService->deleteByIpAddresses($virtualInterfaces->get());
+            DB::commit();
+            DB::beginTransaction();
+            //create
+            $newVi = [];
+            for ($i = 1; $i <= 20; $i++) {
+                if (!$this->formData['virtualNetwork' . $i]) {
+                    continue;
+                }
+                $ip = $this->formData['virtualNetwork' . $i]['ip'];
+                $virtualNetworkId = $this->formData['virtualNetwork' . $i]['id'];
+                //lock public ip
+                if ($virtualNetworkId == 'public') {
+                    VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                        ->ofIp($ip)
+                        ->update(['vm_id' => $this->vmModel->id]);
+                }
+                $vi = new VirtualInterface();
+                $vi->ip = $ip;
+                $vi->ip_long = ip2long($ip);
+                $vi->vm_id = $this->vmModel->id;
+                $vi->vn_id = $virtualNetworkId == "public" ? 0 : $virtualNetworkId;
+                $vi->hosting_id = $this->getWhmcsParamByKey('serviceid');
+                $vi->save();
+                $newVi[] = $vi;
+                $viIds[] = $vi->id;
+            }
+            if ($newVi) {
+                $config = (new VirtualInterfaceConverter($newVi, \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm()))->asConfig();
+                \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm()->updateConfig($config);
+            }
+            DB::commit();
+        } catch (\Exception $ex) {
+            DB::rollBack();
+            Api::commit();
+            throw $ex;
+        }
+    }
+
+    private function disksUpdate()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vmModel  = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
+        $additonalDiskService = $this->configuration()->isQemu() ? new AdditionalDiskService() : new AdditionalMountPointService();
+        //Update
+        $diskIds=[];
+        $resizeTask = null;
+        for ($i = 0; $i <= 20; $i++) {
+            if ($this->formData['disks' . $i]) {
+                $id = $this->formData['disks' . $i]['id'];
+                $size = $this->formData['disks' . $i]['size'];
+                $backup = $this->formData['disks' . $i]['backup'] == "on" ? null : 0;
+                $mp =  $this->formData['disks' . $i]['mp'];
+                $hdd = $vm->getHardDiskRepostiory()->findById($id);
+                if($resizeTask && $this->configuration()->isLxc()){
+                    for($i=0;  $i<=15; $i++){
+                        if($vm->node()->task($resizeTask)->isDone()){
+                            $resizeTask = null;
+                            break;
+                        }
+                        sleep(1);
+                    }
+                }
+                //Backup
+                $hdd->setBackup($backup);
+                //mp
+                if($hdd instanceof MountPoint){
+                    $hdd->setBackup($this->formData['disks' . $i]['backup'] == "on" ? 1 : null);
+                    $hdd->setMp($mp);
+                }
+                $hdd->update();
+                //resize
+                if ((int)$hdd->getGb() < (int)$size)
+                {
+                    $size = "+" . abs((int)$size - (int)$hdd->getGb()) . "G";
+                    $resizeTask = $hdd->resize($size);
+                }
+                $diskIds[] = $id;
+            }
+        }
+        //delete
+        foreach ($vm->getHardDiskRepostiory()->fetch() as $disk){
+            if(!$disk->isMaster() && !in_array($disk->getId() ,$diskIds)){
+                $disk->delete();
+            }
+        }
+        $vm->getHardDiskRepostiory()->deleteUnused();
+        //Create
+        $additonalDiskService->create($this->formData);
+        //Update disk size
+        $vmModel->disks = $vm->getHardDiskRepostiory()->reset()->additionalSize();
+        $vmModel->save();
+
+    }
+
+
+}

+ 95 - 0
app/UI/VmUpdate/Sections/Lxc/AdditionalDiskSection.php

@@ -0,0 +1,95 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Sections\Lxc;
+
+use MGProvision\Proxmox\v2\models\MountPoint;
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\DiskSizeValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BaseSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class AdditionalDiskSection extends BaseSection implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+
+        $this->initIds('additionalDiskSection');
+        $this->initFields();
+        $this->loadAdditionalDisks();
+    }
+
+    public function initFields()
+    {
+        //size
+        $field = new Text('additionalDiskSize');
+        $field->addValidator(new DiskSizeValidator('disk',false));
+        $field->replaceClasses(['lu-col-md-6']);
+        $this->addField($field);
+        //bus
+        if($this->configuration()->isQemu()){
+            $field = new Select('additionalDiskBus');
+            $options=[];
+            foreach( $this->configuration()->getAdditionalDiskType() as $entery){
+                $options[$entery] = sl("lang")->abtr($entery);
+            }
+            $field->setAvailableValues($options);
+            $field->replaceClasses(['lu-col-md-6']);
+            $this->addField($field);
+        }
+        //format
+        if($this->configuration()->isQemu()){
+            $field = new Select('additionalDiskFormat');
+            $options=[];
+            foreach( $this->configuration()->getAdditionalDiskFormat() as $entery){
+                $options[$entery] = sl("lang")->abtr($entery);
+            }
+            $field->setAvailableValues($options);
+            $field->replaceClasses(['lu-col-md-6']);
+            $this->addField($field);
+        }
+        if($this->configuration()->isLxc()){
+            //mp
+            $field = new Text('additionalDiskMp');
+            $field->setPlaceholder("/some/path");
+            $field->replaceClasses(['lu-col-md-6']);
+            $this->addField($field);
+        }
+        //backup
+        if ($this->configuration()->isPermissionMountPointBackup())
+        {
+            $field = new Select('additionalDiskBackup');
+            $field->setAvailableValues([
+                'on' => 'Enable',
+                'off'=>'Disable',
+            ]);
+            $field->replaceClasses(['lu-col-md-6']);
+            $this->addField($field);
+        }
+    }
+
+    protected function loadAdditionalDisks(){
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $this->customTplVars['additionalDisks']=[];
+        foreach ($vm->getHardDiskRepostiory()->fetch() as $disk){
+            if($disk->isMaster()){
+                continue;
+            }
+            $this->customTplVars['additionalDisks'][]=
+                [   'id' => $disk->getId() ,
+                    'size' => (int) $disk->getGb(),
+                    'backup'=> $disk->isBackup() ? "on" : "off",
+                    'mp' => $disk instanceof  MountPoint ? $disk->getMp() : null
+                ];
+        }
+
+    }
+}

+ 23 - 0
app/UI/VmUpdate/Sections/Lxc/GeneralCombinedSection.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Sections\Lxc;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\CpulimitValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\HostnameValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\IpAddressValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\PasswordValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Fields\IsoImageSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Fields\OsTemplateSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Range;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BaseSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class GeneralCombinedSection extends GeneralSection
+{
+
+}

+ 150 - 0
app/UI/VmUpdate/Sections/Lxc/GeneralSection.php

@@ -0,0 +1,150 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Sections\Lxc;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\CpulimitValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\HostnameValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\IpAddressValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\PasswordValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Fields\IsoImageSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Fields\OsTemplateSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Range;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BaseSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class GeneralSection extends BaseSection
+{
+    use ProductService;
+
+    /**
+     * @var ResourceManager
+     */
+    protected $resourceManager;
+
+    public function initContent()
+    {
+        $this->initIds('generalSection');
+        $this->unsetShowTitle();
+        $this->resourceManager = new ResourceManager();
+        $this->resourceManager->notVmIds([\ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id]);
+        $this->initFields();
+    }
+
+    public function initFields()
+    {
+        /**
+         * @deprecated
+        //ipv4
+        if($this->configuration()->isPermissionIpv4()){
+        $field = new Text('ipv4');
+        $field->addValidator(new NumberValidator($this->resourceManager->ipv4()->getMin(), $this->resourceManager->ipv4()->free(),false));
+        $field->setDescription('description');
+        $this->addField($field);
+        }
+        //ipv6
+        if($this->configuration()->isPermissionIpv6()){
+        $field = new Text('ipv6');
+        $field->addValidator(new NumberValidator($this->resourceManager->ipv6()->getMin(), $this->resourceManager->ipv6()->free(),false));
+        $field->setDescription('description');
+        $this->addField($field);
+        }
+         */
+        $cpuPrioryty = $this->configuration()->hasCpuPriority();
+        //name
+        $field = new Text('name');
+        $field->addValidator(new HostnameValidator());
+        $field->setDescription('description');
+        $this->addField($field);
+        //description
+        $field = new Textarea('description');
+        $field->setDescription('description');
+        $this->addField($field);
+        //password
+        if($this->configuration()->isPermissionPassword()){
+            $field = new Text('password');
+            $field->addValidator(new PasswordValidator());
+            $field->setDescription('description');
+            if($this->configuration()->isLxc()){
+                $field->addHtmlAttribute('readonly', "");
+                $field->addClass('disabled');
+            }
+            $this->addField($field);
+        }
+        //cores
+        if($this->configuration()->isPermissionCores()){
+            $field = new Text('cores');
+            $field->addValidator(new NumberValidator($this->resourceManager->cores()->getMin(), $this->resourceManager->cores()->free(),true));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cpu priority
+        if($cpuPrioryty){
+            $field = new Range('cpuPriority', $this->resourceManager->cpuPriority()->getMin(), $this->resourceManager->cpuPriority()->free());
+            $field->addValidator(new NumberValidator($this->resourceManager->cpuPriority()->getMin(), $this->resourceManager->cpuPriority()->free(),true));
+            $field->setDescription('description');
+            $field->addHtmlAttribute('data-label1', sl('lang')->abtr("Very Low"));
+            $field->addHtmlAttribute('data-label2', sl('lang')->abtr("Low"));
+            $field->addHtmlAttribute('data-label3', sl('lang')->abtr("Normal"));
+            $field->addHtmlAttribute('data-label4', sl('lang')->abtr("High"));
+            $field->addHtmlAttribute('data-label5', sl('lang')->abtr("Medium"));
+            $this->addField($field);
+        }
+        //cpulimit
+        if($this->configuration()->isPermissionCpuLimit() && !$cpuPrioryty){
+            $field = new Text('cpulimit');
+            $field->addValidator(new CpulimitValidator($this->resourceManager->cpulimit()->getMin(), $this->resourceManager->cpulimit()->free(),true));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cpuunits
+        if($this->configuration()->isPermissionCpuunits() && !$cpuPrioryty){
+            $field = new Text('cpuunits');
+            $field->addValidator(new NumberValidator($this->resourceManager->cpuunits()->getMin(), $this->resourceManager->cpuunits()->free(),true));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //memory
+        $field = new Text('memory');
+        $field->addValidator(new NumberValidator($this->resourceManager->memory()->getMin(), $this->resourceManager->memory()->free(),true));
+        $field->setDescription('description');
+        $this->addField($field);
+        //swap lxc only
+        if($this->configuration()->isPermissionSwap()){
+            $field = new Text('swap');
+            $field->addValidator(new NumberValidator($this->resourceManager->swap()->getMin(), $this->resourceManager->swap()->free(),true));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        if($this->configuration()->isDetailsCombinedView()){
+            //disk
+            $field = new Text('disk');
+            $field->addValidator(new NumberValidator($this->resourceManager->disk()->getMin(), $this->resourceManager->disk()->free(),true));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+         //dnsdomain
+        if($this->configuration()->isPermissionSearchdomain()){
+            $field = new Text('searchdomain');
+            $field->addValidator(new HostnameValidator(false));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        if($this->configuration()->isPermissionNameservers()){
+            //ns1
+            $field = new Text('nameserver[0]');
+            $field->addValidator(new IpAddressValidator());
+            $field->setDescription('description');
+            $this->addField($field);
+            //ns2
+            $field = new Text('nameserver[1]');
+            $field->addValidator(new IpAddressValidator());
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+    }
+}

+ 95 - 0
app/UI/VmUpdate/Sections/Qemu/AdditionalDiskSection.php

@@ -0,0 +1,95 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Sections\Qemu;
+
+use MGProvision\Proxmox\v2\models\MountPoint;
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\DiskSizeValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BaseSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class AdditionalDiskSection extends BaseSection implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+
+        $this->initIds('additionalDiskSection');
+        $this->initFields();
+        $this->loadAdditionalDisks();
+    }
+
+    public function initFields()
+    {
+        //size
+        $field = new Text('additionalDiskSize');
+        $field->addValidator(new DiskSizeValidator('disk',false));
+        $field->replaceClasses(['lu-col-md-6']);
+        $this->addField($field);
+        //bus
+        if($this->configuration()->isQemu()){
+            $field = new Select('additionalDiskBus');
+            $options=[];
+            foreach( $this->configuration()->getAdditionalDiskType() as $entery){
+                $options[$entery] = sl("lang")->abtr($entery);
+            }
+            $field->setAvailableValues($options);
+            $field->replaceClasses(['lu-col-md-6']);
+            $this->addField($field);
+        }
+        //format
+        if($this->configuration()->isQemu()){
+            $field = new Select('additionalDiskFormat');
+            $options=[];
+            foreach( $this->configuration()->getAdditionalDiskFormat() as $entery){
+                $options[$entery] = sl("lang")->abtr($entery);
+            }
+            $field->setAvailableValues($options);
+            $field->replaceClasses(['lu-col-md-6']);
+            $this->addField($field);
+        }
+        if($this->configuration()->isLxc()){
+            //mp
+            $field = new Text('additionalDiskMp');
+            $field->setPlaceholder("/some/path");
+            $field->replaceClasses(['lu-col-md-6']);
+            $this->addField($field);
+        }
+        //backup
+        if ($this->configuration()->isPermissionAdditionalDiskBackup())
+        {
+            $field = new Select('additionalDiskBackup');
+            $field->setAvailableValues([
+                'on' => 'Enable',
+                'off'=>'Disable',
+            ]);
+            $field->replaceClasses(['lu-col-md-6']);
+            $this->addField($field);
+        }
+    }
+
+    protected function loadAdditionalDisks(){
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $this->customTplVars['additionalDisks']=[];
+        foreach ($vm->getHardDiskRepostiory()->fetch() as $disk){
+            if($disk->isMaster()){
+                continue;
+            }
+            $this->customTplVars['additionalDisks'][]=
+                [   'id' => $disk->getId() ,
+                    'size' => (int) $disk->getGb(),
+                    'backup'=> $disk->isBackup() ? "on" : "off",
+                    'mp' => $disk instanceof  MountPoint ? $disk->getMp() : null
+                ];
+        }
+
+    }
+}

+ 27 - 0
app/UI/VmUpdate/Sections/Qemu/GeneralCombinedSection.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Sections\Qemu;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\CpulimitValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\HostnameValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\IpAddressValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\SshPublicKeyValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\PasswordValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Fields\IsoImageSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Fields\OsTemplateSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Fields\SecondaryIsoImageSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Range;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BaseSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\isAdmin;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class GeneralCombinedSection extends GeneralSection
+{
+
+}

+ 181 - 0
app/UI/VmUpdate/Sections/Qemu/GeneralSection.php

@@ -0,0 +1,181 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Sections\Qemu;
+
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\CpulimitValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\HostnameValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\IpAddressValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\SshPublicKeyValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\PasswordValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Range;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BaseSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\isAdmin;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class GeneralSection extends BaseSection
+{
+    use ProductService;
+
+    /**
+     * @var ResourceManager
+     */
+    protected $resourceManager;
+
+    public function initContent()
+    {
+        $this->initIds('generalSection');
+        $this->unsetShowTitle();
+        $this->resourceManager = new ResourceManager();
+        $this->resourceManager->notVmIds([\ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id]);
+        $this->initFields();
+
+
+    }
+
+    public function initFields()
+    {
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $cpuPrioryty = $this->configuration()->hasCpuPriority();
+        //name
+        $field = new Text('name');
+        $field->addValidator(new HostnameValidator());
+        $field->setDescription('description');
+        $this->addField($field);
+        //description
+        $field = new Textarea('description');
+        $field->setDescription('description');
+        $this->addField($field);
+        if(isAdmin() || $this->configuration()->isPermissionIsoImage() && $vm->getCdRom()->count()){
+            $field = new Select("iso");
+            $field->notEmpty();
+            $this->addField($field);
+        }
+        //password
+        if($this->configuration()->isPermissionPassword()){
+            $field = new Text('password');
+            $field->addValidator( new PasswordValidator());
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //sshkeys
+        if($this->configuration()->isPermissionSshkeys()){
+            $field = new Textarea("sshkeys");
+            $field->addValidator(new SshPublicKeyValidator(false));
+            $this->addField($field);
+        }
+        //sockets
+        if($this->configuration()->isPermissionSockets() && !$this->configuration()->isCalculateSocketsAndCores()){
+            $field = new Text('sockets');
+            $field->addValidator(new NumberValidator($this->resourceManager->sockets()->getMin(), $this->resourceManager->sockets()->free(),true));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cores
+        if($this->configuration()->isPermissionCores() && !$this->configuration()->isCalculateSocketsAndCores()){
+            $field = new Text('cores');
+            $field->addValidator(new NumberValidator($this->resourceManager->cores()->getMin(), $this->resourceManager->cores()->free(),true));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //vcpus
+        if($this->configuration()->isPermissionVcpus() || $this->configuration()->isCalculateSocketsAndCores()){
+            $field = new Range('vcpus',$this->resourceManager->vcpus()->getMin(), $this->resourceManager->vcpus()->free());
+            $field->addValidator(new NumberValidator($this->resourceManager->vcpus()->getMin(), $this->resourceManager->vcpus()->free(),true));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cpu priority
+        if($cpuPrioryty){
+            $field = new Range('cpuPriority', $this->resourceManager->cpuPriority()->getMin(), $this->resourceManager->cpuPriority()->free());
+            $field->addValidator(new NumberValidator($this->resourceManager->cpuPriority()->getMin(), $this->resourceManager->cpuPriority()->free(),true));
+            $field->setDescription('description');
+            $field->addHtmlAttribute('data-label1', sl('lang')->abtr("Very Low"));
+            $field->addHtmlAttribute('data-label2', sl('lang')->abtr("Low"));
+            $field->addHtmlAttribute('data-label3', sl('lang')->abtr("Normal"));
+            $field->addHtmlAttribute('data-label4', sl('lang')->abtr("High"));
+            $field->addHtmlAttribute('data-label5', sl('lang')->abtr("Medium"));
+            $this->addField($field);
+        }
+        //cpulimit
+        if($this->configuration()->isPermissionCpuLimit() && !$cpuPrioryty){
+            $field = new Text('cpulimit');
+            $field->addValidator(new CpulimitValidator($this->resourceManager->cpulimit()->getMin(), $this->resourceManager->cpulimit()->free(),true));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //cpuunits
+        if($this->configuration()->isPermissionCpuunits( ) && !$cpuPrioryty){
+            $field = new Text('cpuunits');
+            $field->addValidator(new NumberValidator($this->resourceManager->cpuunits()->getMin(), $this->resourceManager->cpuunits()->free(),true));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //memory
+        $field = new Text('memory');
+        $field->addValidator(new NumberValidator($this->resourceManager->memory()->getMin(), $this->resourceManager->memory()->free(),true));
+        $field->setDescription('description');
+        $this->addField($field);
+        if($this->configuration()->isDetailsCombinedView()){
+            //disk
+            $field = new Text('disk');
+            $field->addValidator(new NumberValidator($this->resourceManager->disk()->getMin(), $this->resourceManager->disk()->free(),true));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        /**
+         * @deprecated
+        //ipv4
+        if($this->configuration()->isPermissionIpv4()){
+            $field = new Text('ipv4');
+            $field->addValidator(new NumberValidator($this->resourceManager->ipv4()->getMin(), $this->resourceManager->ipv4()->free(),false));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //ipv6
+        if($this->configuration()->isPermissionIpv6()){
+            $field = new Text('ipv6');
+            $field->addValidator(new NumberValidator($this->resourceManager->ipv6()->getMin(), $this->resourceManager->ipv6()->free(),false));
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+         *
+         */
+        //dnsdomain
+        if($this->configuration()->isPermissionSearchdomain()){
+             $field = new Text('searchdomain');
+             $field->addValidator(new HostnameValidator(false));
+             $field->setDescription('description');
+             $this->addField($field);
+        }
+        if($this->configuration()->isPermissionNameservers()){
+            //ns1
+            $field = new Text('nameserver[0]');
+            $field->addValidator(new IpAddressValidator());
+            $field->setDescription('description');
+            $this->addField($field);
+            //ns2
+            $field = new Text('nameserver[1]');
+            $field->addValidator(new IpAddressValidator());
+            $field->setDescription('description');
+            $this->addField($field);
+        }
+        //boot device 1
+        $field = new Select("bootOrder0");
+        $field->notEmpty();
+        $this->addField($field);
+        //boot device 2
+        $field = new Select("bootOrder1");
+        $field->notEmpty();
+        $this->addField($field);
+        //boot device 3
+        $field = new Select("bootOrder2");
+        $field->notEmpty();
+        $this->addField($field);
+    }
+}

+ 75 - 0
app/UI/VmUpdate/Sections/VirtualNetworkSection.php

@@ -0,0 +1,75 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmUpdate\Sections;
+
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualInterface;
+use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
+use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Ip\Ipv4Range;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonBase;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BaseSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class VirtualNetworkSection extends BaseSection implements ClientArea
+{
+    use ProductService;
+
+    public function initContent()
+    {
+        $this->initIds('virtualNetworkSection');
+        $this->initFields();
+        $this->loadVirtualInterfaces();
+    }
+
+    public function initFields()
+    {
+        //virtualNetwork
+        $this->customTplVars['virtualNetwork'] = ["public" => sl('lang')->abtr('Public')];
+        //ips
+        $this->customTplVars['ips']=[];
+        //Public
+        $this->customTplVars['ipSelected'] =null;
+        foreach (VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))->ofVmIdNull()->get() as $ip)
+        {
+            if(!$this->customTplVars['ipSelected'] ){
+                $this->customTplVars['ipSelected']  = $ip->ip;
+            }
+            $this->customTplVars['ips'][] =[
+                "networkId" => "public",
+                "ip" => $ip->ip,
+                "id" => $ip->id
+            ];
+        }
+        //private
+        foreach (VirtualNetwork::ofHostingId($this->getWhmcsParamByKey('serviceid'))->get() as $vn)
+        {
+            $this->customTplVars['virtualNetwork'][$vn->id] = $vn->name;
+            $ipRange = new Ipv4Range($vn->pool, $vn->cidr);
+            $ipRange->setLimit(255);
+            $ipRange->disableIpAddresses( $vn->virtualInterfaces->pluck('ip')->toArray());
+            foreach (  $ipRange->get() as $ip ){
+                $this->customTplVars['ips'][]=[
+                    "networkId" => $vn->id,
+                    "ip" => $ip,
+                ];
+            }
+        }
+
+    }
+
+    protected function loadVirtualInterfaces(){
+
+        $vmId = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        $this->customTplVars['virtualInterfaces'] = VirtualInterface::select('id','vn_id','ip')
+            ->ofHostingId($this->getWhmcsParamByKey('serviceid'))
+            ->ofVmId($vmId)
+            ->get()
+            ->toArray();
+    }
+
+}

+ 123 - 0
app/UI/VmUpdate/Templates/sections/lxc/additionalDiskSection.tpl

@@ -0,0 +1,123 @@
+{**********************************************************************
+* ProxmoxCloudVps product developed. (2017-10-06)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+**********************************************************************}
+
+{**
+* @author Sławomir Miśkowicz <slawomir@modulesgarden.com>
+*}
+
+<div class="lu-widget">
+    <div class="lu-widget__body">
+        {if $rawObject->isShowTitle() && (($rawObject->getRawTitle() || $rawObject->getTitle()) && $rawObject->isViewHeader())}
+            <div class="lu-widget__header">
+                <div class="lu-widget__top lu-top">
+                    <div class="lu-top__title">
+                        {if $rawObject->getIcon()}<i class="{$rawObject->getIcon()}"></i>{/if}
+                        {if $rawObject->isRawTitle()}{$rawObject->getRawTitle()}{elseif $rawObject->getTitle()}{$MGLANG->T($rawObject->getTitle())}{/if}
+                    </div>
+                    <div class="lu-top__toolbar"><a href="#" id="pm-add-disk-button" data-toggle="lu-tooltip"
+                                                    class="lu-btn lu-btn--primary"
+                                                    data-title="{$MGLANG->T('Add New Additional Disk')}">
+                            <i class="lu-zmdi lu-zmdi-plus"></i>
+                            <span class="lu-btn__text">{$MGLANG->T('Add New Additional Disk')}</span>
+                        </a>
+                    </div>
+                </div>
+            </div>
+        {/if}
+        <div class="lu-widget__content lu-p-1x">
+            {if !$customTplVars.additionalDisks}
+                <div class="lu-alert lu-alert--outline lu-alert--icon lu-alert--info lu-alert--bordered lu-m-b-0x lu-alert--dismiss mg-message ">
+                    <div class="lu-alert__body">
+                        {$MGLANG->T('additional_disk_add_info')}
+                    </div>
+                </div>
+            {/if}
+            <div class="lu-widget hidden pm-disk-content-default">
+                <div class="lu-widget__body">
+                    <div class="lu-widget__header">
+                        <div class="lu-widget__top lu-top">
+                            <div class="lu-top__title">
+                                {$MGLANG->T('Additional Disk')}
+                            </div>
+                            <div class="lu-top__toolbar">
+                                <a href="#"
+                                   class="lu-btn lu-btn--xs lu-btn--default lu-btn--icon lu-btn--link lu-btn--plain pm-delete-disk-button">
+                                    <i class="lu-btn__icon lu-zmdi lu-zmdi-close"></i>
+                                </a>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="lu-widget__content lu-row">
+                        {foreach from=$rawObject->getFields() item=field }
+                            {$field->getHtml()}
+                        {/foreach}
+                    </div>
+                </div>
+            </div>
+            {foreach from=$customTplVars.additionalDisks key=keyIndex item=additionalDisk}
+                <div class="lu-widget">
+                    <div class="lu-widget__body">
+                        <div class="lu-widget__header">
+                            <div class="lu-widget__top lu-top">
+                                <div class="lu-top__title">
+                                    {$MGLANG->T('Additional Disk')}
+                                </div>
+                                <div class="lu-top__toolbar">
+                                    <a href="#"
+                                       class="lu-btn lu-btn--xs lu-btn--default lu-btn--icon lu-btn--link lu-btn--plain pm-delete-disk-button">
+                                        <i class="lu-btn__icon lu-zmdi lu-zmdi-close"></i>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="lu-widget__content lu-row pm-disk-row">
+                            <div class="lu-form-group lu-col-md-6">
+                                <label class="lu-form-label">{$MGLANG->T('Size [GB]')}</label>
+                                <input type="hidden" name="disks{$keyIndex}[id]"  value="{$additionalDisk.id}">
+                                <input type="text" placeholder="" name="disks{$keyIndex}[size]"
+                                       value="{$additionalDisk.size}"
+                                       class="lu-form-control">
+                                <div hidden="hidden" class="lu-form-feedback lu-form-feedback--icon"></div>
+                            </div>
+                            <div class="lu-form-group lu-col-md-6">
+                                <label class="lu-form-label">
+                                    {$MGLANG->T('Path')}                 </label>
+                                <input type="text"
+                                       placeholder="/some/path"
+                                       name="disks{$keyIndex}[mp]"
+                                       value="{$additionalDisk.mp}"
+                                       class="lu-form-control">
+                                <div hidden="hidden" class="lu-form-feedback lu-form-feedback--icon"></div>
+                            </div>
+                            <div class="lu-form-group lu-col-md-6">
+                                <label class="lu-form-label">{$MGLANG->T('Backup')}</label>
+                                <select name="disks{$keyIndex}[backup]" class="lu-form-control ">
+                                    <option value="on"
+                                            {if $additionalDisk.backup =='on'}selected{/if}>{$MGLANG->abtr('Enable')}</option>
+                                    <option value="off"
+                                            {if $additionalDisk.backup =='off'}selected{/if}>{$MGLANG->abtr('Disable')}</option>
+                                </select>
+                                <div hidden="hidden" class="lu-form-feedback lu-form-feedback--icon"></div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            {/foreach}
+        </div>
+    </div>
+</div>

+ 43 - 0
app/UI/VmUpdate/Templates/sections/lxc/generalCombinedSection.tpl

@@ -0,0 +1,43 @@
+{**********************************************************************
+* ProxmoxCloudVps product developed. (2017-10-06)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+**********************************************************************}
+
+{**
+* @author Sławomir Miśkowicz <slawomir@modulesgarden.com>
+*}
+<div class="lu-col-md-6">
+<div class="lu-widget">
+    <div class="lu-widget__body">
+        {if $rawObject->isShowTitle() && (($rawObject->getRawTitle() || $rawObject->getTitle()) && $rawObject->isViewHeader())}
+            <div class="lu-widget__header">
+                <div class="lu-widget__top lu-top">
+                    <div class="lu-top__title">
+                        {if $rawObject->getIcon()}<i class="{$rawObject->getIcon()}"></i>{/if}
+                        {if $rawObject->isRawTitle()}{$rawObject->getRawTitle()}{elseif $rawObject->getTitle()}{$MGLANG->T($rawObject->getTitle())}{/if}
+                    </div>
+                </div>
+            </div>
+        {/if}
+        <div class="lu-widget__content">
+            {foreach from=$rawObject->getFields() item=field }
+                {$field->getHtml()}
+            {/foreach}
+        </div>
+
+    </div>
+</div>
+</div>

+ 107 - 0
app/UI/VmUpdate/Templates/sections/qemu/additionalDiskSection.tpl

@@ -0,0 +1,107 @@
+{**********************************************************************
+* ProxmoxCloudVps product developed. (2017-10-06)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+**********************************************************************}
+
+{**
+* @author Sławomir Miśkowicz <slawomir@modulesgarden.com>
+*}
+
+<div class="lu-widget  lu-p-1x">
+    <div class="lu-widget__body">
+        {if $rawObject->isShowTitle() && (($rawObject->getRawTitle() || $rawObject->getTitle()) && $rawObject->isViewHeader())}
+            <div class="lu-widget__header">
+                <div class="lu-widget__top lu-top">
+                    <div class="lu-top__title">
+                        {if $rawObject->getIcon()}<i class="{$rawObject->getIcon()}"></i>{/if}
+                        {if $rawObject->isRawTitle()}{$rawObject->getRawTitle()}{elseif $rawObject->getTitle()}{$MGLANG->T($rawObject->getTitle())}{/if}
+                    </div>
+                    <div class="lu-top__toolbar"><a href="#" id="pm-add-disk-button" data-toggle="lu-tooltip" class="lu-btn lu-btn--primary" data-title="{$MGLANG->T('Add New Additional Disk')}">
+                            <i class="lu-zmdi lu-zmdi-plus"></i>
+                            <span class="lu-btn__text">{$MGLANG->T('Add New Additional Disk')}</span>
+                        </a>
+                    </div>
+                </div>
+            </div>
+        {/if}
+        <div class="lu-widget__content lu-p-1x">
+            {if !$customTplVars.additionalDisks}
+            <div class="lu-alert lu-alert--outline lu-alert--icon lu-alert--info lu-alert--bordered lu-m-b-0x lu-alert--dismiss mg-message ">
+                <div class="lu-alert__body">
+                    {$MGLANG->T('additional_disk_add_info')}
+                </div>
+            </div>
+            {/if}
+            <div class="lu-widget hidden pm-disk-content-default" >
+                <div class="lu-widget__body">
+                    <div class="lu-widget__header">
+                        <div class="lu-widget__top lu-top">
+                            <div class="lu-top__title">
+                                {$MGLANG->T('Additional Disk')}
+                            </div>
+                            <div class="lu-top__toolbar">
+                                <a href="#"
+                                        class="lu-btn lu-btn--xs lu-btn--default lu-btn--icon lu-btn--link lu-btn--plain pm-delete-disk-button">
+                                    <i class="lu-btn__icon lu-zmdi lu-zmdi-close"></i>
+                                </a>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="lu-widget__content lu-row">
+                        {foreach from=$rawObject->getFields() item=field }
+                            {$field->getHtml()}
+                        {/foreach}
+                    </div>
+                </div>
+            </div>
+            {foreach from=$customTplVars.additionalDisks key=keyIndex item=additionalDisk}
+                <div class="lu-widget" >
+                    <div class="lu-widget__body">
+                        <div class="lu-widget__header">
+                            <div class="lu-widget__top lu-top">
+                                <div class="lu-top__title">
+                                    {$MGLANG->T('Additional Disk')}
+                                </div>
+                                <div class="lu-top__toolbar">
+                                    <a href="#"
+                                       class="lu-btn lu-btn--xs lu-btn--default lu-btn--icon lu-btn--link lu-btn--plain pm-delete-disk-button">
+                                        <i class="lu-btn__icon lu-zmdi lu-zmdi-close"></i>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="lu-widget__content lu-row pm-disk-row">
+                            <div class="lu-form-group lu-col-md-6">
+                                <label class="lu-form-label">{$MGLANG->T('Size [GB]')}</label>
+                                <input type="hidden" name="disks{$keyIndex}[id]" value="{$additionalDisk.id}">
+                                <input type="text" placeholder="" name="disks{$keyIndex}[size]" value="{$additionalDisk.size}"
+                                       class="lu-form-control">
+                                <div hidden="hidden" class="lu-form-feedback lu-form-feedback--icon"></div>
+                            </div>
+                            <div class="lu-form-group lu-col-md-6">
+                                <label class="lu-form-label">{$MGLANG->T('Backup')}</label>
+                                <select name="disks{$keyIndex}[backup]" class="lu-form-control ">
+                                    <option value="on" {if $additionalDisk.backup =='on'}selected{/if}>{$MGLANG->abtr('Enable')}</option>
+                                    <option value="off" {if $additionalDisk.backup =='off'}selected{/if}>{$MGLANG->abtr('Disable')}</option></select>
+                                <div hidden="hidden" class="lu-form-feedback lu-form-feedback--icon"></div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            {/foreach}
+        </div>
+    </div>
+</div>

+ 44 - 0
app/UI/VmUpdate/Templates/sections/qemu/generalCombinedSection.tpl

@@ -0,0 +1,44 @@
+{**********************************************************************
+* ProxmoxCloudVps product developed. (2017-10-06)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+**********************************************************************}
+
+{**
+* @author Sławomir Miśkowicz <slawomir@modulesgarden.com>
+*}
+
+<div class="lu-col-md-6">
+<div class="lu-widget">
+    <div class="lu-widget__body">
+        {if $rawObject->isShowTitle() && (($rawObject->getRawTitle() || $rawObject->getTitle()) && $rawObject->isViewHeader())}
+            <div class="lu-widget__header">
+                <div class="lu-widget__top lu-top">
+                    <div class="lu-top__title">
+                        {if $rawObject->getIcon()}<i class="{$rawObject->getIcon()}"></i>{/if}
+                        {if $rawObject->isRawTitle()}{$rawObject->getRawTitle()}{elseif $rawObject->getTitle()}{$MGLANG->T($rawObject->getTitle())}{/if}
+                    </div>
+                </div>
+            </div>
+        {/if}
+        <div class="lu-widget__content">
+            {foreach from=$rawObject->getFields() item=field }
+                {$field->getHtml()}
+            {/foreach}
+        </div>
+
+    </div>
+</div>
+</div>

+ 122 - 0
app/UI/VmUpdate/Templates/sections/virtualNetworkSection.tpl

@@ -0,0 +1,122 @@
+{**********************************************************************
+* ProxmoxCloudVps product developed. (2017-10-06)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+**********************************************************************}
+
+{**
+* @author Sławomir Miśkowicz <slawomir@modulesgarden.com>
+*}
+<div class="lu-widget  lu-p-1x">
+    <div class="lu-widget__body">
+        {if $rawObject->isShowTitle() && (($rawObject->getRawTitle() || $rawObject->getTitle()) && $rawObject->isViewHeader())}
+            <div class="lu-widget__header">
+                <div class="lu-widget__top lu-top">
+                    <div class="lu-top__title">
+                        {if $rawObject->getIcon()}<i class="{$rawObject->getIcon()}"></i>{/if}
+                        {if $rawObject->isRawTitle()}{$rawObject->getRawTitle()}{elseif $rawObject->getTitle()}{$MGLANG->T($rawObject->getTitle())}{/if}
+                    </div>
+                <div class="lu-top__toolbar"><a href="#" id="pm-add-new-virtual-network-button" data-toggle="lu-tooltip" class="lu-btn lu-btn--primary" data-title="{$MGLANG->T('Add New Virtual Network')}">
+                        <i class="lu-zmdi lu-zmdi-plus"></i>
+                        <span class="lu-btn__text">{$MGLANG->T('Add New Virtual Network')}</span>
+                    </a></div>
+                </div>
+            </div>
+        {/if}
+        <div class="lu-widget__content lu-p-1x">
+            {if !$customTplVars.virtualInterfaces}
+            <div class="lu-alert lu-alert--outline lu-alert--icon lu-alert--info lu-alert--bordered lu-m-b-0x lu-alert--dismiss mg-message">
+                <div class="lu-alert__body">
+                    {$MGLANG->T('additional_ip_add_info')}
+                </div>
+            </div>
+            {/if}
+            <div class="lu-widget hidden pm-virtual-network-content-default" >
+                <div class="lu-widget__body">
+                    <div class="lu-widget__header">
+                        <div class="lu-widget__top lu-top">
+                            <div class="lu-top__title">
+                                {$MGLANG->T('Virtual Network')}
+                            </div>
+                            <div class="lu-top__toolbar">
+                                <a href="#"
+                                        class="lu-btn lu-btn--xs lu-btn--default lu-btn--icon lu-btn--link lu-btn--plain pm-delete-virtual-network-button">
+                                    <i class="lu-btn__icon lu-zmdi lu-zmdi-close"></i>
+                                </a>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="lu-widget__content lu-row">
+                        <div class="lu-form-group lu-col-md-6">
+                            <label class="lu-form-label">{$MGLANG->T('Select Virtual Network')}</label>
+                            <select name="virtualNetwork[id]" class="lu-form-control pm-vn-select">
+                                {foreach from=$customTplVars.virtualNetwork key=opValue item=option}
+                                    <option value="{$opValue}">{$option}</option>
+                                {/foreach}
+                            </select>
+                        </div>
+                        <div class="lu-form-group lu-col-md-6">
+                            <label class="lu-form-label">{$MGLANG->T('Select IP Address')}</label>
+                            <select name="virtualNetwork[ip]" class="lu-form-control  pm-vn-ip-select">
+                                {foreach from=$customTplVars.ips key=opValue item=option}
+                                    <option class="vn-ip-{$option.networkId}" {if $option.networkId!="public"}style="display: none;"{/if}  {if $option.ip == $customTplVars.ipSelected}selected{/if}  value="{$option.ip}">{$option.ip}</option>
+                                {/foreach}
+                            </select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            {foreach from=$customTplVars.virtualInterfaces key=keyIndex item=virtualInterface}
+                <div class="lu-widget" >
+                    <div class="lu-widget__body">
+                        <div class="lu-widget__header">
+                            <div class="lu-widget__top lu-top">
+                                <div class="lu-top__title">
+                                    {$MGLANG->T('Virtual Network')}
+                                </div>
+                                <div class="lu-top__toolbar">
+                                    <a href="#"
+                                       class="lu-btn lu-btn--xs lu-btn--default lu-btn--icon lu-btn--link lu-btn--plain pm-delete-virtual-network-button">
+                                        <i class="lu-btn__icon lu-zmdi lu-zmdi-close"></i>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="lu-widget__content lu-row">
+                            <div class="lu-form-group lu-col-md-6">
+                                <label class="lu-form-label">{$MGLANG->T('Select Virtual Network')}</label>
+                                <input type="hidden" name="virtualInterface{$keyIndex}[id]" value="{$virtualInterface.id}">
+                                <select name="virtualInterface{$keyIndex}[vn_id]" class="lu-form-control pm-vn-select">
+                                    {foreach from=$customTplVars.virtualNetwork key=opValue item=option}
+                                        {if $virtualInterface.vn_id==$opValue }
+                                            <option value="{$opValue}" selected>{$option}</option>
+                                        {/if}
+                                    {/foreach}
+                                </select>
+                            </div>
+                            <div class="lu-form-group lu-col-md-6">
+                                <label class="lu-form-label">{$MGLANG->T('Select IP Address')}</label>
+                                <select name="virtualInterface{$keyIndex}[ip]" class="lu-form-control  pm-vn-ip-select">
+                                    <option class="vn-ip-{$virtualInterface.vn_id}"
+                                            {if $option.ip == $customTplVars.ipSelected}selected{/if}  value="{$virtualInterface.ip}">{$virtualInterface.ip}</option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            {/foreach}
+        </div>
+    </div>
+</div>

+ 40 - 0
app/UI/Vms/Buttons/DeleteButton.php

@@ -0,0 +1,40 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\isAdmin;
+
+class DeleteButton extends ButtonDataTableModalAction implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteButton');
+        if(!isAdmin()){
+            $this->setDisableByColumnValue("vmid", 0);
+        }
+        $this->switchToRemoveBtn();
+        $this->initLoadModalAction(new DeleteModal());
+    }
+
+}

+ 107 - 0
app/UI/Vms/Buttons/EditButton.php

@@ -0,0 +1,107 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Modals\MigrateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\BuildUrl;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class EditButton extends ButtonDataTableModalAction implements ClientArea
+{
+    protected $icon           = 'lu-zmdi lu-zmdi-edit';
+
+    public function initContent()
+    {
+        $this->initIds('redirectButton');
+        $this->setDisableByColumnValue("vmid", 0);
+        $url ="clientarea.php?action=productdetails&id={$this->getWhmcsParamByKey('serviceid')}&modop=custom&a=management&mg-page=vm";
+        $this->setRawUrl($url)
+            ->setRedirectParams(['vm' => ':id']);
+    }
+
+    public function afterInitContent()
+    {
+        $this->htmlAttributes['@click.middle'] = 'redirect($event, ' . $this->parseCustomParams() . ', true)';
+        $this->htmlAttributes['@click'] = 'redirect($event, ' . $this->parseCustomParams() . ')';
+    }
+
+    public function setRawUrl($url)
+    {
+        $this->rawUrl = $url;
+
+        return $this;
+    }
+
+    protected function parseCustomParams()
+    {
+        if (count($this->redirectParams) === 0 && $this->rawUrl === null)
+        {
+            return '{}';
+        }
+
+        return $this->parseListTOJsString($this->redirectParams);
+    }
+
+    protected function parseListTOJsString($params)
+    {
+        $jsString = '{';
+
+        if ($this->rawUrl !== null)
+        {
+            $params['rawUrl'] = $this->rawUrl;
+        }
+
+        foreach ($params as $key => $value)
+        {
+            $jsString .= ' ' . str_replace('-', '__', $key) . ': ' . (is_array($value) ? ($this->parseListTOJsString($value) . ',') : ("'" . (string) $value) . "',");
+        }
+
+        $jsString = trim($jsString, ',') . ' } ';
+
+        return $jsString;
+    }
+
+    public function setRedirectParams($paramsList)
+    {
+        $this->redirectParams = $paramsList;
+
+        $this->updateHtmlAttributesByRedirectParams();
+
+        return $this;
+    }
+
+    protected function updateHtmlAttributesByRedirectParams()
+    {
+        foreach ($this->redirectParams as $key => $value)
+        {
+            $this->updateHtmlAttribute($key, $value);
+        }
+    }
+
+    protected function updateHtmlAttribute($key, $value)
+    {
+        if (strpos($value, ':') === 0)
+        {
+            $this->addHtmlAttribute(':data-' . $key , 'dataRow.' . trim($value, ':'));
+        }
+    }
+}

+ 38 - 0
app/UI/Vms/Buttons/ImportButton.php

@@ -0,0 +1,38 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Modals\DeleteModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Modals\ImportModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class ImportButton extends ButtonCreate implements AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('importButton');
+        $this->initLoadModalAction(new ImportModal());
+    }
+
+}

+ 38 - 0
app/UI/Vms/Buttons/MigrateButton.php

@@ -0,0 +1,38 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Modals\MigrateModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\BuildUrl;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class MigrateButton extends ButtonDataTableModalAction implements AdminArea
+{
+    protected $icon           = 'lu-btn__icon lu-zmdi lu-zmdi-refresh-sync-alert';
+    public function initContent()
+    {
+        $this->initIds('migrateButton');
+        $this->setDisableByColumnValue("vmid", 0);
+        $this->initLoadModalAction(new MigrateModal());
+    }
+
+
+}

+ 53 - 0
app/UI/Vms/Forms/DeleteForm.php

@@ -0,0 +1,53 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers\DeleteVmProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers\DiskProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers\FirewallOptionProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+
+
+class DeleteForm extends BaseForm implements ClientArea
+{
+    public function initContent()
+    {
+        $this->initIds('deleteForm');
+        $this->setFormType('delete');
+        $this->setProvider(new DeleteVmProvider());
+        $this->initFields();
+        $this->loadDataToForm();;
+    }
+
+    public function getAllowedActions()
+    {
+        return ['delete'];
+    }
+
+    private function initFields()
+    {
+        $this->setConfirmMessage('confirmDelete', ["name" => null]);
+        $this->addField(new Hidden("id"));
+        $this->addField(new Hidden("name"));
+    }
+
+}

+ 61 - 0
app/UI/Vms/Forms/ImportForm.php

@@ -0,0 +1,61 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers\DeleteVmProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers\DiskProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers\FirewallOptionProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers\ImportVmProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+
+class ImportForm extends BaseForm implements AdminArea
+{
+    public function initContent()
+    {
+        $this->initIds('importForm');
+        $this->setFormType('import');
+        $this->setProvider(new ImportVmProvider());
+        $this->initFields();
+        $this->loadDataToForm();;
+    }
+
+    public function getAllowedActions()
+    {
+        return ['import'];
+    }
+
+    private function initFields()
+    {
+        //vmid
+        $field = new Select("vmid");
+        $field->notEmpty();
+        $this->addField($field);
+        //password
+        $field = new Text("password");
+        $this->addField($field );
+    }
+
+}

+ 59 - 0
app/UI/Vms/Forms/MigrateForm.php

@@ -0,0 +1,59 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Forms;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers\MigrateProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Helpers\AlertTypesConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
+
+class MigrateForm extends BaseForm implements AdminArea
+{
+    public function initContent()
+    {
+        $this->initIds('migrateForm');
+        $this->setFormType('update');
+        $this->setProvider(new MigrateProvider());
+        $this->setInternalAlertMessage('confirmMigrate');
+        $this->setInternalAlertMessageType(AlertTypesConstants::DANGER);
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['update'];
+    }
+
+    private function initFields()
+    {
+        //id
+        $this->addField(new Hidden('vmId'));
+        //target
+        $field = new Select('target');
+        $field->notEmpty();
+        $this->addField($field);
+        //online
+        $this->addField((new Switcher('online'))->setDescription('tip'));
+    }
+}

+ 35 - 0
app/UI/Vms/Modals/DeleteModal.php

@@ -0,0 +1,35 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class DeleteModal extends ModalConfirmDanger implements AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('deleteVmModal');
+        $this->addForm(new DeleteForm());
+    }
+
+}

+ 37 - 0
app/UI/Vms/Modals/ImportModal.php

@@ -0,0 +1,37 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Forms\DeleteForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Forms\ImportForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\BaseModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class ImportModal extends BaseModal implements AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('importModal');
+        $this->addForm(new ImportForm());
+    }
+
+}

+ 36 - 0
app/UI/Vms/Modals/MigrateModal.php

@@ -0,0 +1,36 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Forms\MigrateForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Modals\ModalConfirmDanger;
+
+class MigrateModal extends ModalConfirmDanger implements AdminArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('migrateModal');
+        $this->setModalSizeLarge();
+        $this->addForm(new  MigrateForm());
+    }
+
+}

+ 161 - 0
app/UI/Vms/Pages/VmsDataTable.php

@@ -0,0 +1,161 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (26.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Pages;
+
+use MGProvision\Proxmox\v2\VmFactory;
+use ModulesGarden\ProxmoxAddon\App\Decorators\OsTemplateDecorator;
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Buttons\CreateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Buttons\DeleteButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Buttons\EditButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Buttons\ImportButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Buttons\MigrateButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonRedirect;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\Column;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\QueryDataProvider;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataTable;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\isAdmin;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class VmsDataTable extends DataTable implements ClientArea, AdminArea
+{
+
+    use ApiService;
+    use ProductService;
+
+    protected $id = 'vmsDataTable';
+    protected $title = 'vmsDataTable';
+    protected $searchable = false;
+    protected $tableLength = "100";
+
+    public function initContent()
+    {
+        $this->addClass('lu-text-left');
+
+        $isAdmin = isAdmin();
+        //create
+        if(!$isAdmin){
+            $createButton = new ButtonRedirect('createVmButton');
+            $createButton->setShowTitle();
+            $url ="clientarea.php?action=productdetails&id={$this->getWhmcsParamByKey('serviceid')}&modop=custom&a=management&mg-page=vm&mg-action=create";
+            $createButton->setRawUrl($url);
+            $createButton->setIcon('lu-zmdi lu-zmdi-plus');
+            $createButton->replaceClasses(['lu-btn lu-btn--primary']);
+            $this->addTitleButton($createButton);
+        }
+        //import
+        if($isAdmin){
+            $this->addButton(new ImportButton());
+            //migrate
+            $this->addActionButton(new MigrateButton());
+        }
+
+        if(!$isAdmin){
+            //edit
+            $this->addActionButton(new EditButton());
+        }
+        //delete
+        $this->addActionButton(new DeleteButton());
+    }
+
+    protected function loadHtml()
+    {
+        if(isAdmin()){
+            $this->addColumn((new Column('vmid')));
+        }
+        $this->addColumn((new Column('name')))
+            ->addColumn((new Column('status')))
+            ->addColumn((new Column('vcpus')))
+            ->addColumn((new Column('memory')))
+            ->addColumn((new Column('disk')))
+            ->addColumn((new Column('osTemplate')));
+    }
+
+
+    public function replaceFieldStatus($key, $row)
+    {
+
+        try{
+            //current
+            if($row->vmid==0){
+                return '<span class="lu-label lu-label--danger lu-label--status">' . sl('lang')->abtr( "Build") . '</span>';
+            }
+            $vmModel = VmModel::ofId($row->id)->firstOrFail();
+            $this->api();
+            $status = (new VmFactory())->fromVmModel($vmModel)->status()['status'];
+            if ($status=='running')
+            {
+                return '<span class="lu-label lu-label--success lu-label--status">' . sl('lang')->abtr($status) . '</span>';
+            }
+            return '<span class="lu-label lu-label--danger lu-label--status">' . sl('lang')->abtr($status) . '</span>';
+        }catch (\Exception $ex){
+            return '<span class="lu-label lu-label--danger lu-label--status">' . $ex->getMessage() . '</span>';
+        }
+
+
+    }
+
+    public function replaceFieldOsTemplate($key, $row)
+    {
+        $json = \json_decode($row->data, true);
+        if(!$json['osTemplate'] || $json['osTemplate'] =='installationFromIso'){
+            return sl('lang')->abtr('template', "Installation From ISO Image");
+        }
+        $decorator = new OsTemplateDecorator($json['osTemplate']);
+        return sl('lang')->abtr('template', $decorator->toFriendlyName());
+    }
+
+    public function replaceFieldDisk($key, $row)
+    {
+        return sprintf(" %s GB", $row->disk + $row->disks);
+    }
+
+    public function replaceFieldMemory($key, $row)
+    {
+        return sprintf(" %s MB", $row->memory);
+    }
+
+    protected function loadData()
+    {
+        $query    = VmModel::select("id", "name", "vcpus", "memory", "disk","disks", "vmid","data")
+            ->ofHostingId($this->getWhmcsParamByKey('serviceid'))
+            ->notTemplate()
+            ->getQuery();
+        $dataProv = new QueryDataProvider();
+        $dataProv->setDefaultSorting("name", 'ASC');
+        $dataProv->setData($query);
+        $this->setDataProvider($dataProv);
+    }
+
+    public function isViewFooter()
+    {
+        return false;
+    }
+
+    public function isViewTopBody()
+    {
+        return isAdmin();
+    }
+
+}

+ 43 - 0
app/UI/Vms/Providers/DeleteVmProvider.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers;
+
+use MGProvision\Proxmox\v2\VmFactory;
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\ProxmoxAddon\App\Services\CloudService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+class DeleteVmProvider extends BaseDataProvider implements ClientArea
+{
+
+    public function read()
+    {
+
+        if ($this->actionElementId && $this->actionElementId != "diskDataTable")
+        {
+            $this->data['id'] = $this->actionElementId;
+            $this->data['name'] = VmModel::where("id", $this->actionElementId)->value("name");
+        }
+    }
+
+    public function update()
+    {
+    }
+
+    public function delete()
+    {
+        //init proxmox addon params
+        (new AppParams())->initFromWhmcsParams();
+        //get vm model
+        $vmModel = VmModel::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                          ->ofId($this->formData['id'])->firstOrFail();
+        //destory vm
+        (new CloudService())->delete($vmModel);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Virtual Machine has been deleted successfully');
+    }
+}

+ 89 - 0
app/UI/Vms/Providers/ImportVmProvider.php

@@ -0,0 +1,89 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers;
+
+use MGProvision\Proxmox\v2\repository\ClusterResourcesRepository;
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Hosting;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
+use ModulesGarden\ProxmoxAddon\App\Services\CloudService;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+
+class ImportVmProvider extends BaseDataProvider implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+    use UserService;
+
+    public function read()
+    {
+        $this->api();
+        $clusterResurces = new ClusterResourcesRepository();
+        $clusterResurces->findVm();
+        //qemu or lxc
+        $this->configuration()->isQemu() ? $clusterResurces->findQemu() : $clusterResurces->findLxc();
+        foreach ($clusterResurces->fetch() as $resource){
+            if($resource->getTemplate()){
+                continue;
+            }
+            if(VmModel::where("vmid", $resource->getVmid())->count()){
+                continue;
+            }
+            if(Hosting::ofCustomFielVmid($resource->getVmid())->count()){
+                continue;
+            }
+            $this->availableValues['vmid'][$resource->getVmid()] = sprintf("VMID: %s (%s)", $resource->getVmid(), $resource->getName());
+        }
+
+    }
+
+    public function update()
+    {
+    }
+
+    public function delete()
+    {
+
+    }
+
+    public function import()
+    {
+        $this->api();
+        $clusterResurces = new ClusterResourcesRepository();
+        $clusterResurces->findVm();
+        $clusterResurces->findVmid($this->getFormDataValues()['vmid']);
+        $resurce = $clusterResurces->firstOrFail();
+        $vm =   $resurce->getVm();
+        $vmModel = new VmModel();
+        $vmModel->hosting_id = $this->getWhmcsParamByKey('serviceid');
+        $vmModel->vmid = $vm->getVmid();
+        $vmModel->node = $vm->getNode();
+        $vmModel->name = $resurce->getName();
+        $vmModel->virtualization = $this->configuration()->getVirtualization();
+        $vmModel->password = encrypt($this->getFormDataValues()['password']);
+        $vmModel->cores = $vm->config()['cores'];
+        $vmModel->sockets = (int) $vm->config()['sockets'];
+        $vmModel->vcpus = (int) $vm->config()['vcpus'];
+        $vmModel->cpulimit  =  $vm->config()['cpulimit'];
+        $vmModel->cpuunits =  $vm->config()['cpuunits'];
+        $vmModel->memory =  $vm->config()['memory'];
+        $vmModel->swap  = (int)  $vm->config()['swap'];
+        $vmModel->disk   = (int)  $vm->getMasterHddSize();
+        if($this->configuration()->isQemu()){
+            $vmModel->disks  = (int)  $vm->getHardDiskRepostiory()->additionalSize();
+        }
+        if($this->configuration()->isLxc()){
+            $vmModel->disks  = (int)  $vm->getMounPoints()->additionalSize();
+        }
+        $this->userUpdatePermission([$vmModel->vmid]);
+        $vmModel->save();
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The Virtual Machine has been imported successfully');
+    }
+}

+ 99 - 0
app/UI/Vms/Providers/MigrateProvider.php

@@ -0,0 +1,99 @@
+<?php
+/* * ********************************************************************
+*  ProxmoxVPS Product developed. (27.03.19)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies thereof may not be provided or otherwise made available to any
+* other person.  No title to and  ownership of the  software is  hereby
+* transferred.
+*
+*
+* ******************************************************************** */
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers;
+
+use MGProvision\Proxmox\v2\repository\NodeRepository;
+use MGProvision\Proxmox\v2\VmFactory;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\MigrateVmJob;
+use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\Core\Queue\Models\Job;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class MigrateProvider extends BaseDataProvider implements AdminArea
+{
+    use ProductService;
+    use ApiService;
+
+    public function read()
+    {
+        if (!$this->actionElementId )
+        {
+            return;
+        }
+        $this->api();
+        $vmModel = VmModel::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+            ->ofId($this->actionElementId)
+            ->firstOrFail();
+        $this->data['vmId'] = $vmModel->id;
+        //VM
+        $vm = (new VmFactory())->fromVmModel($vmModel);
+        if ($vm->isRunning())
+        {
+            $this->data['online'] = "on";
+        }
+        $nodeRepository = new NodeRepository();
+        $nodeRepository->setApi($this->api());
+        $nodeRepository->findOnline(true);
+        foreach ($nodeRepository->fetch() as $item)
+        {
+            if ($item->getNode() == $vm->getNode())
+            {
+                continue;
+            }
+            $this->availableValues['target'][$item->getNode()] = $item->getNode();
+        }
+    }
+
+    public function update()
+    {
+        $vmModel = VmModel::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                            ->ofId($this->getFormDataValues()['vmId'])
+                            ->firstOrFail();
+        //VM
+        $vm = (new VmFactory())->fromVmModel($vmModel);
+        $attributes = [
+            "targetNode" => $this->formData['target'],
+            "online"     => $this->formData['online'] == "on" ? 1 : 0
+        ];
+        if (Job::where("job", MigrateVmJob::class. '@handle')->whereIn("status", ['waiting', "running", ""])
+                                                  ->where("rel_id", $this->getWhmcsParamByKey("serviceid"))
+                                                  ->where("rel_type", "hosting")
+                                                  ->where("custom_id", $vmModel->id)
+                                                  ->count())
+        {
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate("Task 'MigrateVm' already exist");
+        }
+        queue(MigrateVmJob::class, $attributes, null, "hosting", $this->getWhmcsParamByKey("serviceid"),$vmModel->id);
+        sl("lang")-> addReplacementConstant("vmid",$vm->getVmid())-> addReplacementConstant("node", $this->formData['target']);
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate("Starting migration of VM :vmid: to :node:");
+    }
+
+
+}

+ 20 - 0
commands/commands.php

@@ -0,0 +1,20 @@
+<?php
+
+define('DS', DIRECTORY_SEPARATOR);
+$modulePath = dirname(__DIR__);
+$whmcsPath  = dirname(dirname(dirname($modulePath)));
+
+require_once $whmcsPath . DS . 'init.php';
+require_once $modulePath . DS . 'core' . DS . 'Bootstrap.php';
+
+//cause WHMCS
+ini_set('max_execution_time', 0);
+
+$argList = $argv ? $argv : $_SERVER['argv'];
+if (count($argList) === 0)
+{
+    $argList = [__FILE__];
+}
+
+(new \ModulesGarden\Servers\ProxmoxCloudVps\Core\CommandLine\Application())
+    ->run();

+ 41 - 0
composer.json

@@ -0,0 +1,41 @@
+{
+    "name": "ModulesGarden/ProxmoxCloudVps",
+    "description": "",
+    "version": "2.1.0",
+    "type": "project",
+    "license": "EULA",
+    "homepage": "http://www.modulesgarden.com",
+    "config": {
+        "platform": {
+            "php": "7.1.0"
+        }
+    },
+    "support":
+            {
+                "email": "contact@modulesgarden.com",
+                "issues": "http://www.modulesgarden.com/customers/support",
+                "forum": "http://www.forum.modulesgarden.com/"
+            },
+    "authors": [],
+    "require":
+            {
+                "php": ">=5.5.9",
+                "piwik/ini": "^1.0",
+                "mso/idna-convert" : "1.*",
+                "adbario/php-dot-notation" : "2.*",
+                "rappasoft/laravel-helpers": "^1.0"
+            },
+    "autoload": {
+        "psr-4": {
+            "ModulesGarden\\Servers\\ProxmoxCloudVps\\Core\\": "./core",
+            "ModulesGarden\\Servers\\ProxmoxCloudVps\\App\\": "./app",
+            "ModulesGarden\\Servers\\ProxmoxCloudVps\\Packages\\": "./packages",
+            "MGProvision\\Proxmox\\": "../../../includes/Proxmox",
+            "ModulesGarden\\ProxmoxAddon\\Core\\": "../../addons/proxmoxAddon/core",
+            "ModulesGarden\\ProxmoxAddon\\App\\": "../../addons/proxmoxAddon/app"
+        },
+        "files": [
+            "./core/Helper/Functions.php"
+        ]
+    }
+}

+ 25 - 0
core/Api/AbstractApi.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\Api;
+
+use \ModulesGarden\Servers\ProxmoxCloudVps\Core\Api\AbstractApi\Curl\Request;
+use \ModulesGarden\Servers\ProxmoxCloudVps\Core\DependencyInjection;
+
+/**
+ * Description of AbstractApi
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+class AbstractApi
+{
+    protected $token;
+    protected $code;
+
+    /**
+     * @return Request
+     */
+    protected function getNewRequest()
+    {
+        return DependencyInjection::create(Request::class);
+    }
+}

+ 158 - 0
core/Api/AbstractApi/Curl.php

@@ -0,0 +1,158 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\Api\AbstractApi;
+
+use \ModulesGarden\Servers\ProxmoxCloudVps\Core\Api\AbstractApi\Curl\Response;
+use \ModulesGarden\Servers\ProxmoxCloudVps\Core\DependencyInjection;
+use \ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\Exception;
+use \ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\ErrorCodes\ErrorCodesLib;
+
+/**
+ * Description of Curl
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+abstract class Curl
+{
+    private $curl;
+    private $options = [
+        CURLOPT_TIMEOUT        => 30,
+        CURLOPT_HEADER         => false,
+        CURLOPT_RETURNTRANSFER => true,
+        CURLINFO_HEADER_OUT    => true
+    ];
+    protected $curlParser;
+
+    public function setCurlParser($curlParser)
+    {
+        $this->curlParser = $curlParser;
+
+        return $this;
+    }
+
+    public function setOptions($options, $value)
+    {
+        $this->options[$options] = $value;
+        return $this;
+    }
+
+    protected function open()
+    {
+        $this->curl = curl_init();
+
+        return $this;
+    }
+
+    protected function close()
+    {
+        curl_close($this->curl);
+
+        return $this;
+    }
+
+    protected function unsetOptions($options)
+    {
+        if (is_array($options))
+        {
+            foreach ($options as $option)
+            {
+                if (isset($this->options[$option]))
+                {
+                    unset($this->options[$option]);
+                }
+            }
+        }
+        else
+        {
+            unset($this->options[$options]);
+        }
+
+        return $this;
+    }
+
+    /**
+     * @return Response
+     * @throws \ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\Exception
+     */
+    protected function send()
+    {
+        $this->includeOptions();
+
+        if (($head = $this->execute()) === false)
+        {
+            throw new Exception(ErrorCodesLib::CORE_CURL_000001, ['lastCurlError' => $this->getLastErrorWithCurl()]);
+        }
+
+        if ($errno = $this->getLastErrorNumber())
+        {
+            throw new Exception(ErrorCodesLib::CORE_CURL_000002, ['curlError' => $this->getLastError($errno)]);
+        }
+
+        list($header, $body) = $this->curlParser->rebuild($head, $this->getHeaderSize());
+
+        return DependencyInjection::create(Response::class)
+                        ->setRequest($this->getHeaderOut())
+                        ->setHeader($header)
+                        ->setCode($this->getHttpCode())
+                        ->setBody($body);
+    }
+
+    private function execute()
+    {
+        return curl_exec($this->curl);
+    }
+
+    private function getLastErrorNumber()
+    {
+        return curl_errno($this->curl);
+    }
+
+    /**
+     * (PHP 5 &gt;= 5.5.0, PHP 7)<br/>
+     * Return string describing the given error code
+     * @link http://php.net/manual/en/function.curl-strerror.php
+     * @param int $errornum <p>
+     * One of the cURL error codes constants.
+     * </p>
+     * @return string error description or <b>NULL</b> for invalid error code.
+     */
+    private function getLastError($errmo)
+    {
+        return curl_strerror($errmo);
+    }
+
+    /**
+     * (PHP 4 &gt;= 4.0.3, PHP 5, PHP 7)<br/>
+     * Return a string containing the last error for the current session
+     * @link http://php.net/manual/en/function.curl-error.php
+     * @param resource $ch
+     * @return string the error message or '' (the empty string) if no
+     * error occurred.
+     */
+    private function getLastErrorWithCurl()
+    {
+        return curl_error($this->curl);
+    }
+
+    private function getHeaderSize()
+    {
+        return curl_getinfo($this->curl, CURLINFO_HEADER_SIZE);
+    }
+
+    private function getHeaderOut()
+    {
+        return curl_getinfo($this->curl, CURLINFO_HEADER_OUT);
+    }
+
+    private function getHttpCode()
+    {
+        return curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
+    }
+
+    private function includeOptions()
+    {
+        curl_setopt_array($this->curl, $this->options);
+
+        return $this;
+    }
+}

+ 193 - 0
core/Api/AbstractApi/Curl/Request.php

@@ -0,0 +1,193 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\Api\AbstractApi\Curl;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Api\AbstractApi\Curl;
+
+/**
+ * Description of Request
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+class Request extends Curl
+{
+    protected $url = '';
+    
+    protected $lastResponse = [];
+    
+    protected $headers = [
+        "Content-Type: application/x-www-form-urlencoded"
+    ];
+
+    public function getLastResponse()
+    {
+        return $this->lastResponse;
+    }
+
+    public function setUrl($url = "")
+    {
+        $this->url = $url;
+
+        return $this;
+    }
+
+    public function resetHeaders()
+    {
+        $this->headers = [];
+
+        return $this;
+    }
+
+    public function setHeaders(array $headers = [])
+    {
+        $this->headers = $headers;
+
+        return $this;
+    }
+
+    public function addHeaders($headers)
+    {
+        if (is_array($headers))
+        {
+            $this->headers = $headers;
+        }
+        else
+        {
+            $this->headers[] = $headers;
+        }
+
+        return $this;
+    }
+
+    protected function send()
+    {
+        $return               = parent::send();
+        $this->close();
+        $this->lastResponse[] = $return;
+
+        return $return;
+    }
+
+    /**
+     * @param array $data
+     * @return string
+     */
+    protected function httpBuildQuery(array $data = [])
+    {
+        return empty($data) ? "" : http_build_query($data);
+    }
+
+    /**
+     * @param array $data post field
+     * @return Response
+     */
+    public function post($data = [])
+    {
+
+        $postvars = is_array($data) ? $this->httpBuildQuery($data) : $data;
+
+        $this->open()
+            ->setOptions(CURLOPT_SSL_VERIFYPEER, false)
+            ->setOptions(CURLOPT_URL, $this->url)
+            ->setOptions(CURLOPT_POSTFIELDS, $postvars)
+            ->setOptions(CURLOPT_POST, true);
+        
+        if (!empty($this->headers))
+        {
+            $this->setOptions(CURLOPT_HTTPHEADER, $this->headers)
+                    ->setOptions(CURLOPT_HEADER, true);
+        }
+
+        return $this->send();
+    }
+
+    /**
+     * @param array $data post field
+     * @return Response
+     */
+    public function put($data = [])
+    {
+
+        $postvars = is_array($data)?$this->httpBuildQuery($data):$data;
+        
+        $this->open()
+            ->setOptions(CURLOPT_SSL_VERIFYPEER, false)
+            ->setOptions(CURLOPT_URL, $this->url)
+            ->setOptions(CURLOPT_POSTFIELDS, $postvars)
+            ->setOptions(CURLOPT_CUSTOMREQUEST, "PUT");
+        
+        if (!empty($this->headers))
+        {
+            $this->setOptions(CURLOPT_HTTPHEADER, $this->headers)
+                    ->setOptions(CURLOPT_HEADER, true);
+        }
+
+        return $this->send();
+    }
+
+    /**
+     * @param array $data post field
+     * @return Response
+     */
+    public function delete($data = [])
+    {
+
+        $deletevars = is_array($data)?$this->httpBuildQuery($data):$data;
+        
+        $this->open()
+            ->setOptions(CURLOPT_SSL_VERIFYPEER, false)
+            ->setOptions(CURLOPT_URL, $this->url . $deletevars)
+            ->setOptions(CURLOPT_CUSTOMREQUEST, "DELETE");
+        
+        if (!empty($this->headers))
+        {
+            $this->setOptions(CURLOPT_HTTPHEADER, $this->headers)
+                    ->setOptions(CURLOPT_HEADER, true);
+        }
+
+        return $this->send();
+
+    }
+    
+    /**
+     * @param array $data post field
+     * @return Response
+     */
+    public function get($data = [])
+    {
+        $getvars = is_array($data)?$this->httpBuildQuery($data):$data;
+        
+        $this->open()
+            ->setOptions(CURLOPT_URL, $this->url . $getvars);
+        
+        if (!empty($this->headers))
+        {
+            $this->setOptions(CURLOPT_HTTPHEADER, $this->headers)
+                    ->setOptions(CURLOPT_HEADER, true);
+        }
+        
+        return $this->send();
+    }  
+
+    /**
+     * @param array $data post field
+     * @return Response
+     */
+    public function options($data = [])
+    {
+        $deletevars = is_array($data)?$this->httpBuildQuery($data):$data;
+        
+        $this->open()
+            ->setOptions(CURLOPT_SSL_VERIFYPEER, false)
+            ->setOptions(CURLOPT_URL, $this->url)
+            ->setOptions(CURLOPT_CUSTOMREQUEST, "OPTIONS");
+        
+        if (!empty($this->headers))
+        {
+            $this->setOptions(CURLOPT_HTTPHEADER, $this->headers)
+                    ->setOptions(CURLOPT_HEADER, true);
+        }
+
+        return $this->send();
+    }
+}

+ 92 - 0
core/Api/AbstractApi/Curl/Response.php

@@ -0,0 +1,92 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\Api\AbstractApi\Curl;
+
+/**
+ * Description of Respons
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+class Response
+{
+    protected $body;
+    protected $request;
+    protected $header;
+    protected $code;
+
+    public function setRequest($request)
+    {
+        $this->request = $request;
+
+        return $this;
+    }
+
+    public function setHeader($header)
+    {
+        $this->header = $header;
+
+        return $this;
+    }
+
+    public function setBody($body)
+    {
+        $this->body = $body;
+
+        return $this;
+    }
+
+    public function setCode($code)
+    {
+        $this->code = $code;
+
+        return $this;
+    }
+
+    /**
+     * @param bool $isJson
+     * @return string|\stdClass
+     */
+    public function getBody($isJson = true)
+    {
+
+
+        if ($isJson)
+        {
+            return json_decode($this->body);
+        }
+
+        return $this->body;
+    }
+
+    /**
+     * @return string
+     */
+    public function getRequest()
+    {
+        return $this->request;
+    }
+
+    /**
+     * @return string
+     */
+    public function getHeader()
+    {
+        return $this->header;
+    }
+
+    /**
+     * @return int
+     */
+    public function getCode()
+    {
+        return $this->code;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isSuccess()
+    {
+        return (bool) ($this->code >= 200 && $this->code < 300);
+    }
+}

+ 22 - 0
core/Api/AbstractApi/Parser.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\Api\AbstractApi;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Interfaces\CurlParser;
+
+/**
+ * Description of Parser
+ *
+ * @author Rafał Ossowski <rafal.os@modulesgarden.com>
+ */
+class Parser implements CurlParser
+{
+
+    public function rebuild($head, $size)
+    {
+        return [
+            substr($head, 0, $size),
+            substr($head, $size)
+        ];
+    }
+}

+ 186 - 0
core/Api/Http.php

@@ -0,0 +1,186 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\Api;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Libs\Exceptions\WhmcsApiException;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ModuleConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Traits\IsDebugOn;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Libs\Exceptions\ApiException;
+
+
+/**
+ * Description of Http
+ *
+ * @author Paweł Złamaniec <pawel.zl@modulesgarden.com>
+ */
+class Http
+{
+    use IsDebugOn;
+
+    /**
+     * @var \AltoRouter;
+     */
+    protected $router;
+
+    public function __construct($basepath)
+    {
+        $this->loadRouter($basepath);
+        $this->router->addMatchTypes(["d" => "[^/]+"]);
+    }
+
+    /**
+     * Parse API request
+     */
+    public function run()
+    {
+        try
+        {
+            $logger = $this->getLoggerObject();
+            $match = $this->router->match();
+            if($match)
+            {
+                $auth = $this->getAuthObject();
+                $auth->run($match["name"]);
+
+                $validator = $this->getValidatorObject();
+                $validator->run($match["name"]);
+
+                $request = explode("#", $match['target']);
+                $action = [$this->getController($request[0]), $request[1]];
+                $result = call_user_func_array($action, $match['params']);
+
+                $logger->logInfo($match["name"], array_merge($match["params"], $_REQUEST), $result);
+
+                echo json_encode($result);
+            }
+            else
+            {
+                header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
+                echo json_encode(["error" => "Action not found"]);
+            }
+
+            exit;
+        }
+        catch (ApiException $mgex)
+        {
+            $code   = $mgex->getMgHttpCode();
+            $exdata = $mgex->getAdditionalData();
+
+            $message = "{$mgex->getMgMessage(false)}" . ($this->isDebugOn() ? " | " . print_r($exdata, true) : "");
+        }
+        catch (WhmcsApiException $whmcsex)
+        {
+            $exdata = $whmcsex->getAdditionalData();
+            $message = "{$exdata["data"]["result"]["message"]}: {$exdata["data"]["result"]["error"]}";
+        }
+        catch (\Exception $ex)
+        {
+            $exdata  = $this->isDebugOn() ? print_r($ex, true) : null;
+            $message = "Please contact administration (server side issue)" . ($exdata ? " | ". $exdata : "");
+        }
+
+        $logger->logError($match["name"], array_merge($match["params"], $_REQUEST), $exdata);
+
+        $response = $this->getResponseBuilderObject();
+        $message = $response->build($match["name"], $message);
+
+        http_response_code($code ?: 500);
+        echo json_encode(["error" => $message]);
+    }
+
+    /**
+     * Load router object
+     *
+     * @param $basePath
+     * @throws \Exception
+     */
+    protected function loadRouter($basePath)
+    {
+        $this->router = new \AltoRouter();
+        $this->router->setBasePath($basePath);
+
+        $routes = require ModuleConstants::getDevConfigDir().DS."api".DS."routes.php";
+        $this->router->addRoutes($routes);
+    }
+
+    /**
+     * Get controller object
+     *
+     * @return Object
+     */
+    protected function getController($classname)
+    {
+        $classname = "\\ModulesGarden\\Servers\\ProxmoxCloudVps\\App\\Http\\Api\\{$classname}";
+        return new $classname;
+    }
+
+    /**
+     * Get Authorization class object
+     *
+     * @return Auth class object
+     */
+    protected function getAuthObject()
+    {
+        $config = $this->getConfigElement("auth");
+        $auth = new $config["class"];
+
+        return $auth;
+    }
+
+    /**
+     * @return mixed
+     */
+    protected function getValidatorObject()
+    {
+        $config = $this->getConfigElement("validator");
+        $validator = new $config["class"];
+
+        return $validator;
+    }
+
+
+    /**
+     * Get Logger class object
+     *
+     * @return Logger class object
+     */
+    protected function getLoggerObject()
+    {
+        $config = $this->getConfigElement("logger");
+        $auth = new $config["class"];
+
+        return $auth;
+    }
+
+    /**
+     * Get Logger class object
+     *
+     * @return Logger class object
+     */
+    protected function getResponseBuilderObject()
+    {
+        $config = $this->getConfigElement("responseBuilder");
+        $auth = new $config["class"];
+
+        return $auth;
+    }
+
+    /**
+     * Get configuration element by type
+     *
+     * @param $type
+     * @return mixed
+     */
+    protected function getConfigElement($type)
+    {
+        $config = require ModuleConstants::getDevConfigDir().DS."api".DS."config.php";
+        foreach($config as $element)
+        {
+            if($element["type"] == $type)
+            {
+                return $element;
+            }
+        }
+    }
+}

+ 90 - 0
core/Api/Whmcs.php

@@ -0,0 +1,90 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\Api;
+
+use \ModulesGarden\Servers\ProxmoxCloudVps\Core\Models\Whmcs\Admins;
+use \ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\Exception;
+use \ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\ErrorCodes\ErrorCodesLib;
+
+class Whmcs
+{
+    /**
+     * @var Admins
+     */
+    protected $admins;
+
+    /**
+     * @var string
+     */
+    protected $username;
+
+    /**
+     * @param Admins $admins
+     * @throws \ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\Exception
+     */
+    public function __construct(Admins $admins)
+    {
+        $this->admins = $admins;
+        $this->getAdminUserName();
+
+        if (function_exists('localAPI') === false)
+        {
+            throw new Exception(ErrorCodesLib::CORE_WAPI_000001);
+        }
+    }
+
+    /**
+     * @return string
+     */
+    protected function getAdminUserName()
+    {
+        if (isset($this->username) === false)
+        {
+            $this->username = $this->admins->first()->toArray()['username'];
+        }
+
+        return $this->username;
+    }
+
+    public function call($command, $config = [])
+    {
+
+        $result = localAPI($command, $config, $this->getAdminUserName());
+
+        if ($result['result'] == 'error')
+        {
+            $exc = new Exception(ErrorCodesLib::CORE_WAPI_000002, ['command' => $command, 'data' => $config, 'result' => $result]);
+            $exc->setCustomMessage($result['message']);
+
+            throw $exc;
+        }
+        unset($result['result']);
+
+        return $result;
+    }
+
+    public function getAdminDetails($adminId)
+    {
+        $data = $this->admins->where("id", "LIKE", $adminId)->first();
+
+        if ($data === null)
+        {
+            throw new Exception(ErrorCodesLib::CORE_WAPI_000003, ['adminId' => $adminId], ['adminId' => $adminId]);
+        }
+
+        $result = localAPI("getadmindetails", [], $data->toArray()['username']);
+
+        if ($result['result'] == 'error')
+        {
+            $exc = new Exception(ErrorCodesLib::CORE_WAPI_000004, ['command' => "getadmindetails", 'data' => [], 'result' => $result]);
+            $exc->setCustomMessage($result['message']);
+
+            throw $exc;
+        }
+
+        $result['allowedpermissions'] = explode(",", $result['allowedpermissions']);
+        unset($result['result']);
+
+        return $result;
+    }
+}

+ 172 - 0
core/App/AppContext.php

@@ -0,0 +1,172 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\WhmcsErrorManagerWrapper;
+
+class AppContext
+{
+    protected $debugMode = true;
+
+    public function __construct()
+    {
+        require_once __DIR__ . DIRECTORY_SEPARATOR . 'ErrorHandler.php';
+
+        register_shutdown_function([$this, 'handleShutdown']);
+        set_error_handler([$this, 'handleError'], E_ALL);
+
+        $this->loadDebugState();
+
+        //require app bootstrap
+        require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Bootstrap.php';
+
+        if ($this->debugMode)
+        {
+            spl_autoload_register(array('\ModulesGarden\Servers\ProxmoxCloudVps\Core\App\AppContext', 'loadClassLoader'), true, false);
+        }
+    }
+
+    public function runApp($callerName = null, $params = [])
+    {
+        try
+        {
+            $app = new Application();
+            $result = $app->run($callerName, $params);
+
+            restore_error_handler();
+        }
+        catch (\Exception $exc)
+        {
+            restore_error_handler();
+
+            return [
+                'status' => 'error',
+                'message' => $exc->getMessage()
+            ];
+        }
+
+        return $result;
+    }
+
+    public function handleError($errno, $errstr, $errfile, $errline, $errcontext = null)
+    {
+        if ($this->debugMode || (!in_array($errno, ErrorHandler::WARNINGS) && !in_array($errno, ErrorHandler::NOTICES)))
+        {
+            $handler = new ErrorHandler();
+            $errorToken = md5(time());
+            $handler->logError($errorToken, $errno, $errstr, $errfile, $errline, $errcontext);
+        }
+
+        return true;
+    }
+
+    public function handleShutdown()
+    {
+        $errorInstance = null;
+        $errManager = WhmcsErrorManagerWrapper::getErrorManager();
+        if (is_object($errManager) && method_exists($errManager, 'getRunner'))
+        {
+            $runner = $errManager->getRunner();
+            if (is_object($runner) && method_exists($runner, 'getHandlers'))
+            {
+                $handlers = $runner->getHandlers();
+                foreach ($handlers as $handler)
+                {
+                    $rfHandler = new \ReflectionClass($handler);
+                    $method = $rfHandler->getMethod('getException');
+                    $method->setAccessible(true);
+                    $error = $method->invoke($handler);
+                    if (is_object($error))
+                    {
+                        $errorInstance = $error;
+                        break;
+                    }
+                }
+            }
+        }
+
+        if ($errorInstance === null)
+        {
+            $errorInstance = error_get_last();
+            if ($errorInstance === null)
+            {
+                return;
+            }
+
+            $this->handleError($errorInstance['type'], $errorInstance['message'], $errorInstance['file'], $errorInstance['line'], '');
+
+            return;
+        }
+
+        $handler = new ErrorHandler();
+        $errorToken = md5(time());
+        $handler->logError($errorToken, $errorInstance->getCode(), $errorInstance->getMessage(), $errorInstance->getFile(), $errorInstance->getLine(), $errorInstance->getTrace());
+        if ($errorToken)
+        {
+            echo '<input type="hidden" id="mg-sh-h-492318-64534" value="' . $errorToken . '" mg-sh-h-492318-64534-end >';
+        }
+    }
+
+    public function loadDebugState()
+    {
+        $path = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . '.debug';
+        if (file_exists($path))
+        {
+            $this->debugMode = true;
+
+            return;
+        }
+
+        $this->debugMode = false;
+    }
+
+    public static function loadClassLoader($class)
+    {
+        $rawClass = trim($class, '\\');
+        $pos = strpos($rawClass, 'ModulesGarden\Servers\ProxmoxCloudVps');
+        if ($pos === 0)
+        {
+            if (!class_exists($class) && self::DEPRECATED[$rawClass])
+            {
+                echo 'This class no longer exists: ' . $class . '<br>';
+                echo 'Use: ' . self::DEPRECATED[$rawClass];
+                die();
+            }
+        }
+    }
+
+    const DEPRECATED = [
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\BaseMassActionButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonMassAction',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\AddIconModalButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCreate',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\BaseSubmitButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonSubmitForm',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\BaseButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonBase',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\BaseDatatableModalButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDatatableShowModal',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\BaseModalDataTableActionButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\RedirectButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonRedirect',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\BaseModalButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonModal',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\RedirectWithOutTooltipButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonRedirect',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\OnOffAjaxSwitch' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonSwitchAjax',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\CustomActionButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonCustomAction',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\CustomAjaxActionButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonAjaxCustomAction',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\DatatableModalButtonContextLang' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDatatableModalContextLang',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\DropdownButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDropdown',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\MassActionButtonContextLang' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonMassActionContextLang',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\Submit' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonSubmitForm',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\WhmcsRegisterLoggin' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\WhmcsLogsHandler',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDropdown' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdown',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\Dropdowntems\DropdownItemButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\Dropdowntems\DropdownItemCustonAjaxButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\Dropdowntems\DropdownItemCustonButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\Dropdowntems\DropdownItemDivider' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\Dropdowntems\DropdownItemModalButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\Dropdowntems\DropdownItemRedirectButton' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\ApiException' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\Exception',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\ApiWhmcsException' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\Exception',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\ControllerException' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\Exception',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\DependencyInjectionException' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\Exception',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\MGModuleException' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\Exception',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\RegisterException' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\Exception',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\ServiceLocatorException' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\Exception',
+        'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\SmartyException' => 'ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\Exceptions\Exception',
+    ];
+}

+ 53 - 0
core/App/AppParamsContainer.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Addon\Config;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\di;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ModuleConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ServiceLocator;
+
+class AppParamsContainer
+{
+    /**
+     * @var array
+     * params container
+     */
+    protected $params = [];
+
+    public function __construct()
+    {
+        $addonConfig = ServiceLocator::call(Config::class);
+        $addonConfig->execute();
+        $params = $addonConfig->getConfig();
+
+        if (is_array($params))
+        {
+            $this->params = $params;
+        }
+
+        $this->params['moduleAppType'] = ModuleConstants::getModuleType();
+    }
+
+    public function getParams()
+    {
+        return $this->params;
+    }
+    
+    public function getParam($key, $default = null)
+    {
+        if (isset($this->params[$key]))
+        {
+            return $this->params[$key];
+        }
+        
+        return $default;
+    }
+    
+    public function setParam($key, $value = null)
+    {
+        $this->params[$key] = $value;
+        
+        return $this;
+    }
+}

+ 94 - 0
core/App/Application.php

@@ -0,0 +1,94 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\AppControllers\Http;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\AppControllers\Addon;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\AppControllers\Api;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Hook\InternalHooksWrapper;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ServiceLocator;
+
+use function \ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\di;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Traits\AppParams;
+
+class Application
+{
+    use AppParams;
+
+    public function run($callerName = null, $params = null)
+    {
+        try
+        {
+            $params = $this->runPreAppHook($params);
+
+            $this->setWhmcsParams($params);
+
+            $controller = $this->getControllerClass($callerName);
+
+            $controllerInstance = ServiceLocator::call($controller);
+
+            $result = $controllerInstance->runController($callerName, $params);
+
+            return $result;
+        }
+        catch (\Exception $exc)
+        {
+            $errorPage = ServiceLocator::call(Controllers\Instances\Http\ErrorPage::class);
+
+            $params['mgErrorDetails'] = $exc;
+
+            $result = $errorPage->execute($params);
+
+            return $result;
+        }
+    }
+
+    /**
+     * Saves provided WHMCS params to WhmcsParams service
+     * @param type array
+     */
+    protected function setWhmcsParams($params)
+    {
+        $whmcsParams = di('whmcsParams');
+        $whmcsParams->setParams($params);
+    }
+
+    public function getControllerClass($callerName = null)
+    {
+        $functionName = str_replace($this->getModuleName() . '_', '', $callerName);
+        switch ($functionName)
+        {
+            //HTTP controllers
+            case 'output':
+                return Http::class;
+            case 'clientarea':
+                return Http::class;
+
+            //API controller
+            case 'api':
+                return Api::class;
+
+            //Addon controllers
+            default:
+                return Addon::class;
+        }
+    }
+
+    public function getModuleName ()
+    {
+        return $this->getAppParam('systemName');
+    }
+
+    public function runPreAppHook ($params = [])
+    {
+        //run hook before any app controllers runs
+        $hookWrapper = new InternalHooksWrapper();
+        $newParams = $hookWrapper->runInternalHook('PreAppRun', $params);
+        if ($newParams && $newParams !== false)
+        {
+            return $newParams;
+        }
+
+        return $params;
+    }
+}

+ 19 - 0
core/App/Controllers/AppController.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ServiceLocator;
+
+abstract class AppController
+{
+    public function runController($callerName, $params)
+    {
+        $controller = $this->getControllerInstanceClass($callerName, $params);
+
+        $controllerInstance = ServiceLocator::call($controller);
+
+        $result = $controllerInstance->runExecuteProcess($params);
+
+        return $result;
+    }
+}

+ 36 - 0
core/App/Controllers/AppControllers/Addon.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\AppControllers;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Interfaces\AppController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Traits\AppParams;
+
+class Addon extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\AppController implements AppController
+{
+    use AppParams;
+
+    public function getControllerInstanceClass ($callerName, $params)
+    {
+        $functionName = str_replace($this->getModuleName() . '_', '', $callerName);
+
+        $coreAddon = '\ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Addon\\' . ucfirst($functionName);
+        if (class_exists($coreAddon) && is_subclass_of($coreAddon, AddonController::class))
+        {
+            return $coreAddon;
+        }
+
+        $appAddon = '\ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions\\' . ucfirst($functionName);
+        if (class_exists($appAddon) && is_subclass_of($appAddon, AddonController::class))
+        {
+            return $appAddon;
+        }
+
+        return null;
+    }
+
+    public function getModuleName ()
+    {
+        return $this->getAppParam('systemName');
+    }
+}

+ 13 - 0
core/App/Controllers/AppControllers/Api.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\AppControllers;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Interfaces\AppController;
+
+class Api implements AppController
+{
+    public function getControllerInstanceClass ($callerName, $params)
+    {
+        // TODO: Implement getControllerInstanceClass() method.
+    }
+}

+ 13 - 0
core/App/Controllers/AppControllers/Cron.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\AppControllers;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Interfaces\AppController;
+
+class Cron implements AppController
+{
+    public function getControllerInstanceClass ($callerName, $params)
+    {
+        // TODO: Implement runCalledController() method.
+    }
+}

+ 13 - 0
core/App/Controllers/AppControllers/Hooks.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\AppControllers;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Interfaces\AppController;
+
+class Hooks implements AppController
+{
+    public function getControllerInstanceClass ($callerName, $params)
+    {
+        // TODO: Implement getControllerInstanceClass() method.
+    }
+}

+ 34 - 0
core/App/Controllers/AppControllers/Http.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\AppControllers;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Interfaces\AppController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Http\AdminPageController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Http\ClientPageController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Traits\AppParams;
+
+class Http extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\AppController implements AppController
+{
+    use AppParams;
+
+    public function getControllerInstanceClass ($callerName, $params)
+    {
+        //todo
+        $functionName = str_replace($this->getModuleName() . '_', '', $callerName);
+        switch ($functionName)
+        {
+            //HTTP controllers
+            case 'output':
+                return AdminPageController::class;
+            case 'clientarea':
+                return ClientPageController::class;
+        }
+
+        return null;
+    }
+
+    public function getModuleName ()
+    {
+        return $this->getAppParam('systemName');
+    }
+}

+ 71 - 0
core/App/Controllers/Instances/Addon/Activate.php

@@ -0,0 +1,71 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Addon;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Interfaces\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\DependencyInjection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\DatabaseHelper;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ModuleConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ServiceLocator;
+
+/**
+ * Activate module actions
+ */
+class Activate extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController implements AddonController
+{
+    /**
+     * @var null|DatabaseHelper
+     */
+    protected $databaseHelper = null;
+
+    public function execute($params = [])
+    {
+        try
+        {
+            //Before module activation
+            $return = ServiceLocator::call(\ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Activate\Before::class)->execute($params);
+            if (!isset($return['status']))
+            {
+                $return['status'] = 'success';
+            }
+
+            //module activation process
+            $return = $this->activate($return);
+
+            //After module activation
+            $return = ServiceLocator::call(\ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Activate\After::class)->execute($return);
+
+            return $return;
+        }
+        catch (\Exception $exc)
+        {
+            ServiceLocator::call(\ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\ErrorManager::class)->addError(self::class, $exc->getMessage(), $return);
+            return [
+                'status' => 'error',
+                'description' => $exc->getMessage()
+            ];
+        }
+    }
+
+    protected function activate($params = [])
+    {
+        $this->databaseHelper = DependencyInjection::call(DatabaseHelper::class);
+
+        if ($params['status'] === 'error')
+        {
+            return $params;
+        }
+
+        $isErrorCore     = $this->databaseHelper->performQueryFromFile(ModuleConstants::getFullPath('core', 'Database', 'schema.sql'));
+        $isErrorApp     = $this->databaseHelper->performQueryFromFile(ModuleConstants::getFullPath('app', 'Database', 'schema.sql'));
+        $isErrorDataCore = $this->databaseHelper->performQueryFromFile(ModuleConstants::getFullPath('core', 'Database', 'data.sql'));
+        $isErrorDataApp = $this->databaseHelper->performQueryFromFile(ModuleConstants::getFullPath('app', 'Database', 'data.sql'));
+
+        if ($isErrorCore || $isErrorDataCore || $isErrorApp || $isErrorDataApp)
+        {
+            return ['status' => 'error', 'description' => ServiceLocator::call('errorManager')->getFirstError()->getMessage()];
+        }
+
+        return ['status' => 'success'];
+    }
+}

+ 149 - 0
core/App/Controllers/Instances/Addon/Config.php

@@ -0,0 +1,149 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Addon;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Interfaces\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Data;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\DependencyInjection;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ServiceLocator;
+
+/**
+ * Module configuration wrapper
+ */
+class Config extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController implements AddonController
+{
+    /**
+     * @var array
+     * list of params passed by WHMCS
+     */
+    private $params = [];
+
+    /**
+     * @var array
+     * module configuration list
+     */
+    protected $config = [];
+
+    /**
+     * @var null|\ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Data
+     *
+     */
+    protected $data = null;
+
+    /**
+     * @var array
+     * list of values to be returned as a part of
+     */
+    protected $configFields = [
+        'name',
+        'description',
+        'version',
+        'author',
+        'fields',
+        'systemName',
+        'debug',
+        'moduleIcon',
+        'clientareaName'
+    ];
+
+    /**
+     * @param array $params - WHMCS params for function _config
+     * @return array
+     */
+    public function execute($params = [])
+    {
+        if (!$this->config)
+        {
+            $this->setParams($params);
+            $this->loadConfig();
+
+            return $this->getConfig();
+        }
+
+        return $this->config;
+    }
+
+    /**
+     * @param array $params
+     */
+    protected function setParams($params = [])
+    {
+        if (is_array($params))
+        {
+            $this->params = $params;
+        }
+    }
+
+    /**
+     * loads module configuration from files yaml configs and moduleVersion.php
+     */
+    protected function loadConfig()
+    {
+        if (!$this->data)
+        {
+            $this->data = DependencyInjection::call(Data::class);
+        }
+    }
+
+    /**
+     * parses config data
+     */
+    public function getConfig()
+    {
+        if ($this->config)
+        {
+            return $this->config;
+        }
+
+        try
+        {
+            //Before loading the config
+            $params = [];
+            $return = ServiceLocator::call(\ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Config\Before::class)->execute($params);
+
+            foreach ($this->configFields as $field)
+            {
+                $value = $this->data->{$field};
+                if (isset($return[$field]) === false && $value !== null)
+                {
+                    if (is_numeric($value))
+                    {
+                        $return[$field] = (int)$value;
+                    }
+                    else
+                    {
+                        $return[$field] = $value;
+                    }
+                }
+            }
+
+            //After loading the config
+            $return = ServiceLocator::call(\ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Config\After::class)->execute($return);
+
+            $this->config = $return;
+
+            return $return;
+        }
+        catch (\Exception $ex)
+        {
+            ServiceLocator::call(\ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\ErrorManager::class)->addError(self::class, $ex->getMessage(), $return);
+
+            return $return ? : [];
+        }
+    }
+
+    public function getConfigValue($key, $defaultValue = null)
+    {
+        if (!$this->config)
+        {
+            $this->execute();
+        }
+
+        if (!isset($this->config[$key]))
+        {
+            return $defaultValue;
+        }
+
+        return $this->config[$key];
+    }
+}

+ 319 - 0
core/App/Controllers/Instances/Addon/ConfigOptions.php

@@ -0,0 +1,319 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Addon;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\ResponseResolver;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Installer\ModuleInstaller;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Http\JsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Models\Whmcs\Product;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Models\Whmcs\Server;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ModuleConstants;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ServiceLocator;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Traits\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Traits\OutputBuffer;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\RequestObjectHandler;
+
+/**
+ * ConfigOptions module actions
+ */
+class ConfigOptions extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController
+{
+    use AppParams;
+    use RequestObjectHandler;
+    use OutputBuffer;
+
+    public function execute($params = null)
+    {
+        $productId = $this->getRequestValue('id');
+        if (($this->getRequestValue('action') === 'module-settings' || ($this->getRequestValue('loadData') && $this->getRequestValue('ajax') == '1')))
+        {
+            try
+            {
+                //check storage
+                $invalidStoragePermissions = $this->getInvalidStoragePermitions();
+                if ($invalidStoragePermissions)
+                {
+                    return $this->getInvalidStoragePermissionsError($invalidStoragePermissions);
+                }
+
+                //check server type
+                if (!$this->isCorrectServerType())
+                {
+                    return $this->getInvalidServerTypeError();
+                }
+
+                $requirementsHandler = new \ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Requirements\Checker();
+
+                if ($requirementsHandler->getUnfulfilledRequirements())
+                {
+                    $data = $this->buildErrorMessage(implode('<br>', $requirementsHandler->getUnfulfilledRequirements()));
+
+                    return $this->returnAjaxResponse($data);
+                }
+
+                $this->updateProductType();
+                $this->addRequiredCustomFields();
+
+                //run installer
+                $installer = new ModuleInstaller();
+
+                $installer->makeInstall();
+
+                if (!$installer->isInstallCorrect())
+                {
+                    return $this->buildFailedQueriesMessage($installer->getFailedQueries());
+                }
+            }
+            catch (\Excpetion $exc)
+            {
+                $data = $this->buildErrorMessage($exc->getMessage());
+
+                return $this->returnAjaxResponse($data);
+            }
+
+            try
+            {
+                $this->setAppParam('IntegrationControlerName', \ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions\ConfigOptions::class);
+                $this->setAppParam('IntegrationControlerMethod', 'runExecuteProcess');
+
+                $configOptionsController = new \ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions\ConfigOptions();
+
+                $result = $configOptionsController->execute();
+
+                return $result;
+            }
+            catch (\Exception $exc)
+            {
+                $data = $this->buildErrorMessage($exc->getMessage());
+                $response = new JsonResponse();
+                $response->setData($data);
+
+                $resolver = new ResponseResolver($response);
+
+                $resolver->resolve();
+            }
+
+        }
+        else if ($this->getRequestValue('action') === 'save')
+        {
+            if (!$this->isCorrectServerType())
+            {
+                return [];
+            }
+
+            return [\ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions\ConfigOptions::class, 'runExecuteProcess'];
+        }
+
+        return [];
+    }
+
+    /**
+     * Catch errors during form creation
+     * @param null $params
+     * @return \ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\type
+     */
+    public function runExecuteProcess($params = null)
+    {
+        try
+        {
+            return parent::runExecuteProcess($params);;
+        }
+        catch(\Exception $exc)
+        {
+            $data = $this->buildErrorMessage($exc->getMessage());
+            $response = new JsonResponse();
+            $response->setData($data);
+
+            $resolver = new ResponseResolver($response);
+
+            $resolver->resolve();
+        }
+    }
+
+    public function getInvalidStoragePermitions()
+    {
+        $requiredPaths = [
+            ModuleConstants::getFullPath('storage'),
+            ModuleConstants::getFullPath('storage', 'app'),
+            ModuleConstants::getFullPath('storage', 'crons'),
+            ModuleConstants::getFullPath('storage', 'logs')
+        ];
+
+        $invalidPermissions = [];
+        $lang = ServiceLocator::call('lang');
+        foreach ($requiredPaths as $path)
+        {
+            if (!is_writable($path))
+            {
+                $invalidPermissions[] = $lang->addReplacementConstant('storage_path', $path)->absoluteT('permissionsStorage');
+            }
+            if (!is_readable($path))
+            {
+                $invalidPermissions[] = $lang->addReplacementConstant('storage_path', $path)->absoluteT('permissionsStorageReadable');
+            }
+        }
+
+        return $invalidPermissions;
+    }
+
+    public function buildFailedQueriesMessage($failedQueries = [])
+    {
+        $content = '';
+        foreach ($failedQueries as $query)
+        {
+            $content .= '<div class="panel panel-danger"><div class="panel-heading">Installation Error</div><div class="panel-body" style="padding:0px;"><ul class="list-group" style="margin-bottom: -5px;margin-top: -5px;">';
+            //$content .= '<li class="list-group-item ">Status: ' . $query['status'] . '</li>';
+            $content .= '<li class="list-group-item ">File: ' . $query['file'] . '</li>';
+            $content .= '<li class="list-group-item ">Error Message: ' . $query['errorMessage'] . '</li>';
+            $content .= '<li class="list-group-item ">Raw Query: ' . $query['rawQuery'] . '</li>';
+            $content .= '</ul></div></div>';
+        }
+
+        $data = [
+            'content' =>
+                '<tr><td class="fieldlabel" style="width:0%; display:none;"></td><td style="width=100%;" class="fieldarea">' . $content . '</td></tr>',
+            'mode' => 'advanced'
+        ];
+
+        return $this->returnAjaxResponse($data);
+    }
+
+    public function getInvalidStoragePermissionsError($permissions = [])
+    {
+        $data = $this->buildErrorMessage(implode('<br>', $permissions));
+
+        return $this->returnAjaxResponse($data);
+    }
+
+    public function isCorrectServerType()
+    {
+        try
+        {
+            if (class_exists('\ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions\MetaData'))
+            {
+                $metaDataController = new \ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Actions\MetaData();
+                $details = $metaDataController->execute(null);
+                if ($details['RequiresServer'] !== true)
+                {
+                    return true;
+                }
+
+                $serverGroupId = $this->getServerGroupId();
+
+                $sModel = new Server();
+                $server = $sModel
+                    ->select(['tblservers.type'])
+                    ->join('tblservergroupsrel', 'tblservergroupsrel.serverid', '=', 'tblservers.id')
+                    ->where('tblservergroupsrel.groupid', $serverGroupId)->first();
+
+                if (!$server)
+                {
+                    return false;
+                }
+
+                if ($server->type !== $this->getModuleName())
+                {
+                    return false;
+                }
+            }
+        }
+        catch (\Exception $exception)
+        {
+            //todo log me
+            return false;
+        }
+
+        return true;
+    }
+
+    public function getServerGroupId()
+    {
+        $gid = $this->getRequestValue('servergroup', false);
+        if (!$gid && $gid !== '0' && $gid !== 0)
+        {
+            $pid = $this->getRequestValue('id', 0);
+            $productModel = new Product();
+            $product = $productModel->where('id', $pid)->first();
+            if (!$product)
+            {
+                //can add first product here if needed
+                return 0;
+            }
+
+            return $product->servergroup;
+        }
+
+        return (int)$gid;
+    }
+
+    public function getInvalidServerTypeError()
+    {
+        $lang = ServiceLocator::call('lang');
+
+        $messaage = $lang->addReplacementConstant('provisioning_name', $this->getModuleDisplayName())->absoluteT('invalidServerType');
+        $data = $this->buildErrorMessage($messaage);
+
+        return $this->returnAjaxResponse($data);
+    }
+
+    public function buildErrorMessage($message)
+    {
+        $data = [
+            'content' =>
+                '<tr><td class="fieldlabel" style="width:0%; display:none;"></td><td style="width=100%;" class="fieldarea"><div style="width=100%; margin-bottom: 0px;" class="alert alert-danger">' . $message . '</div></td></tr>',
+            'mode' => 'advanced'
+        ];
+
+        return $data;
+    }
+
+    public function returnAjaxResponse($data = [])
+    {
+        $response = new JsonResponse();
+        $response->setData($data);
+
+        return $response;
+    }
+
+    public function updateProductType()
+    {
+        if ($this->getRequestValue('action') !== 'module-settings'
+            || $this->getAppParam('moduleAppType') !== 'server')
+        {
+            return false;
+        }
+
+        $moduleName = $this->getAppParam('systemName');
+        $pid = $this->getRequestValue('id', false);
+        $servergroup = $this->getRequestValue('servergroup', 0);
+
+        if ($pid && $servergroup > 0)
+        {
+            $product = new Product();
+            $product->where('id', $pid)->update(['servertype' => $moduleName, 'servergroup' => $servergroup]);
+        }
+    }
+
+    public function getModuleName()
+    {
+        return $this->getAppParam('systemName');
+    }
+
+    public function getModuleDisplayName()
+    {
+        return $this->getAppParam('name');
+    }
+
+    public function addRequiredCustomFields()
+    {
+        $pid = $this->getRequestValue('id', false);
+        if ($pid === false)
+        {
+            return;
+        }
+
+        $product = new \ModulesGarden\Servers\ProxmoxCloudVps\Packages\WhmcsService\Product($pid);
+
+        $product->createCustomFieldsFromConfig();
+    }
+}

+ 44 - 0
core/App/Controllers/Instances/Addon/Deactivate.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Addon;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Interfaces\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ServiceLocator;
+
+/**
+ * Deactivate module action
+ */
+class Deactivate extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController implements AddonController
+{
+
+    /**
+     * @param array $params
+     * @return array
+     */
+    public function execute($params = [])
+    {
+        try
+        {
+            // before
+            $return = ServiceLocator::call(\ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Deactivate\Before::class)->execute($params);
+
+            if (!isset($return['status']))
+            {
+                $return['status'] = 'success';
+            }
+
+            // after
+            $return = ServiceLocator::call(\ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Deactivate\After::class)->execute($return);
+
+            return $return;
+        }
+        catch (\Exception $exc)
+        {
+            ServiceLocator::call(\ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\ErrorManager::class)->addError(self::class, $exc->getMessage(), $return);
+            return [
+                'status' => 'error',
+                'description' => $exc->getMessage()
+            ];
+        }
+    }
+}

+ 48 - 0
core/App/Controllers/Instances/Addon/Upgrade.php

@@ -0,0 +1,48 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Addon;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Interfaces\AddonController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\DatabaseHelper;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ServiceLocator;
+
+/**
+ * module update process
+ */
+class Upgrade extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\AddonController implements AddonController
+{
+    /**
+     * @var null|DatabaseHelper
+     */
+    protected $databaseHelper = null;
+
+    public function execute($params = [])
+    {
+        if ($version == '')
+        {
+            $version = isset($this->params['version']) ? $this->params['version'] : $params['version'];
+        }
+
+        try
+        {
+            // after
+            $return = ServiceLocator::call(\ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Update\After::class)->execute(['version' => $version]);
+
+            // update
+            if (!isset($return['version']))
+            {
+                $return['version'] = $version;
+            }
+            $patchManager = ServiceLocator::call("patchManager")->run(/*$this->getConfig("version")*/ '', $version);
+
+            // before
+            $return = ServiceLocator::call(\ModulesGarden\Servers\ProxmoxCloudVps\Core\Configuration\Addon\Update\Before::class)->execute($return);
+
+            return $return;
+        }
+        catch (\Exception $ex)
+        {
+            ServiceLocator::call(\ModulesGarden\Servers\ProxmoxCloudVps\Core\HandlerError\ErrorManager::class)->addError(self::class, $ex->getMessage(), $return);
+        }
+    }
+}

+ 119 - 0
core/App/Controllers/Instances/AddonController.php

@@ -0,0 +1,119 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Http\PageNotFound;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Interfaces\DefaultController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\Http\JsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\ResponseResolver;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ViewAjax;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ViewIntegrationAddon;
+
+abstract class AddonController implements DefaultController
+{
+    use \ModulesGarden\Servers\ProxmoxCloudVps\Core\Traits\Lang;
+    use \ModulesGarden\Servers\ProxmoxCloudVps\Core\Traits\OutputBuffer;
+    use \ModulesGarden\Servers\ProxmoxCloudVps\Core\Traits\IsAdmin;
+    use \ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\RequestObjectHandler;
+    use \ModulesGarden\Servers\ProxmoxCloudVps\Core\Traits\ErrorCodesLibrary;
+    use \ModulesGarden\Servers\ProxmoxCloudVps\Core\Traits\AppParams;
+
+    public function runExecuteProcess($params = null)
+    {
+        $this->loadLangContext();
+
+        $resault = $this->execute($params);
+        if ($resault instanceof JsonResponse)
+        {
+            $resolver = new ResponseResolver($resault);
+
+            $resolver->resolve();
+        }
+
+        if ($this->isValidIntegrationCallback($resault))
+        {
+            $this->setAppParam('IntegrationControlerName', $resault[0]);
+            $this->setAppParam('IntegrationControlerMethod', $resault[1]);
+
+            //to do catch exceptions
+            $resault = Helper\di($resault[0], $resault[1]);
+        }
+
+        if ($resault instanceof ViewAjax)
+        {
+            $this->resolveAjax($resault);
+        }
+
+        if (!$resault instanceof ViewIntegrationAddon)
+        {
+            return $resault;
+        }
+
+        if ($resault instanceof JsonResponse)
+        {
+            $resolver = new ResponseResolver($resault);
+
+            $resolver->resolve();
+        }
+
+        $addonIntegration = $this->getIntegrationControler($params['action']);
+
+        return $addonIntegration->runExecuteProcess($resault);
+
+    }
+
+    public function isValidIntegrationCallback($callback = null)
+    {
+        if (is_callable($callback))
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    public function resolveAjax($resault)
+    {
+        $ajaxResponse = $resault->getResponse();
+
+        $resolver = new ResponseResolver($ajaxResponse);
+
+        $resolver->resolve();
+    }
+
+    protected function getIntegrationControler($action = null)
+    {
+        switch ($action)
+        {
+            case 'ConfigOptions':
+                return Helper\di(\ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Http\ConfigOptionsIntegration::class);
+                break;
+            case 'AdminServicesTabFields':
+                return Helper\di(\ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Http\AdminServicesTabFieldsIntegration::class);
+                break;
+            default:
+                return Helper\di(\ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Http\AddonIntegration::class);
+        }
+    }
+
+    public function loadLangContext()
+    {
+        $this->loadLang();
+
+        if ($this->getAppParam('IntegrationControlerName'))
+        {
+            $parts = explode('\\', $this->getAppParam('IntegrationControlerName'));
+
+            $controller = end($parts);
+        }
+        else
+        {
+            $parts = explode('\\', get_class($this));
+
+            $controller = end($parts);
+        }
+
+        $this->lang->setContext(($this->getAppParam('moduleAppType') . ($this->isAdmin() ? 'AA' : 'CA')), lcfirst($controller));
+    }
+}

+ 11 - 0
core/App/Controllers/Instances/Api/ApiController.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Api;
+
+class ApiController implements DefaultController
+{
+    public function execute ()
+    {
+        // TODO: Implement execute() method.
+    }
+}

+ 40 - 0
core/App/Controllers/Instances/Http/AddonIntegration.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\Http;
+
+use \ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Interfaces\AdminArea;
+use \ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Interfaces\ClientArea;
+use \ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Controllers\Instances\HttpController;
+
+class AddonIntegration extends HttpController implements AdminArea, ClientArea
+{
+    protected $templateName = 'addonIntegration';
+    protected $templateDir = null;
+
+    public function execute($response = null)
+    {
+        $this->loadLangContext();
+        $this->setControllerResult($response);
+        
+        if (!$this->controllerResult)
+        {
+            return '';
+        }
+
+        return $this->resolveResponse();
+    }
+
+    public function resolveResponse()
+    {
+        if ($this->controllerResult instanceof \ModulesGarden\Servers\ProxmoxCloudVps\Core\Http\Response)
+        {
+            $this->controllerResult->setForceHtml();
+        }
+
+        return $this->responseResolver->setResponse($this->controllerResult)
+            ->setTemplateName($this->getTemplateName())
+            ->setTemplateDir($this->getTemplateDir())
+            ->setPageController($this)
+            ->resolve();
+    }
+}

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä