Przeglądaj źródła

new version 3.4.0

andre 4 lat temu
rodzic
commit
cbc5177dde
89 zmienionych plików z 1706 dodań i 275 usunięć
  1. 12 0
      ProxmoxCloudVps.php
  2. 56 1
      app/Config/Packages/Provisioning.php
  3. 2 2
      app/Config/configuration.yml
  4. 20 0
      app/Config/cron.yml
  5. 5 0
      app/Helpers/ProxmoxAddonNotInstalledException.php
  6. 5 2
      app/Hooks/AdminAreaFooterOutput.php
  7. 5 3
      app/Http/Actions/ChangeUserRole.php
  8. 1 1
      app/Http/Actions/MetaData.php
  9. 14 4
      app/Http/Actions/ResetBandwidth.php
  10. 1 1
      app/Http/Admin/Product.php
  11. 100 1
      app/Http/Client/Console.php
  12. 24 6
      app/Http/Client/CustomTemplate.php
  13. 12 0
      app/UI/AccountSummary/Providers/AccountSummaryProvider.php
  14. 69 8
      app/UI/Admin/Product/Forms/VirtualizationChangeForm.php
  15. 30 0
      app/UI/Admin/Product/Sections/AlertSection.php
  16. 8 0
      app/UI/Admin/Product/Sections/BackupSection.php
  17. 10 0
      app/UI/Admin/Product/Sections/FirewallSection.php
  18. 25 0
      app/UI/Admin/Product/Sections/Lxc/ClientAreaSection.php
  19. 5 0
      app/UI/Admin/Product/Sections/Lxc/ConfigurableOptionUnitsSection.php
  20. 2 0
      app/UI/Admin/Product/Sections/Lxc/MountPointSection.php
  21. 5 0
      app/UI/Admin/Product/Sections/Lxc/ServerSection.php
  22. 10 1
      app/UI/Admin/Product/Sections/MainSection.php
  23. 25 0
      app/UI/Admin/Product/Sections/Qemu/AdditonalDisk.php
  24. 6 0
      app/UI/Admin/Product/Sections/Qemu/CloudInitSection.php
  25. 1 0
      app/UI/Admin/Product/Sections/Qemu/ConfigurableOptionUnitsSection.php
  26. 5 0
      app/UI/Admin/Product/Sections/Qemu/DefaultConfigurationSection.php
  27. 2 0
      app/UI/Admin/Product/Sections/Qemu/DiskSection.php
  28. 5 0
      app/UI/Admin/Product/Sections/Qemu/ServerSection.php
  29. 5 0
      app/UI/Admin/Product/Sections/TwiceColumnSection.php
  30. 0 6
      app/UI/Admin/User/Pages/UserDataTable.php
  31. 1 1
      app/UI/Backup/Forms/DeleteForm.php
  32. 37 5
      app/UI/Backup/Providers/BackupProvider.php
  33. 0 6
      app/UI/BackupJob/Buttons/CreateButton.php
  34. 0 6
      app/UI/BackupJob/Forms/DeleteForm.php
  35. 22 3
      app/UI/BackupJob/Modals/CreateModal.php
  36. 5 1
      app/UI/Client/Templates/assets/css/integration.css
  37. 45 2
      app/UI/Client/Templates/assets/img/buttons/backup.png
  38. 1 1
      app/UI/CustomTemplate/Buttons/CreateButton.php
  39. 0 17
      app/UI/Disk/Validators/DiskSizeValidator.php
  40. 47 0
      app/UI/Firewall/Buttons/DeleteButton.php
  41. 47 0
      app/UI/Firewall/Buttons/DownloadButton.php
  42. 22 0
      app/UI/Firewall/Buttons/EnableSwitchButton.php
  43. 50 0
      app/UI/Firewall/Buttons/UpRuleButton.php
  44. 60 0
      app/UI/Firewall/Buttons/UpdateRuleButton.php
  45. 20 0
      app/UI/Firewall/Forms/RuleForm.php
  46. 14 1
      app/UI/Firewall/Modals/UpdateGroupModal.php
  47. 23 0
      app/UI/Firewall/Providers/FirewallProvider.php
  48. 20 16
      app/UI/FirewallOption/Buttons/UpdateButton.php
  49. 1 1
      app/UI/FirewallOption/Modals/UpdateModal.php
  50. 7 0
      app/UI/FirewallOption/Providers/FirewallOptionProvider.php
  51. 9 0
      app/UI/MountPoint/Buttons/BackupSwitchButton.php
  52. 37 0
      app/UI/Resources/Pages/ResourcesContainer.php
  53. 39 0
      app/UI/Resources/Providers/BackupResourceProvider.php
  54. 5 0
      app/UI/Resources/Templates/pages/resourcesContainer.tpl
  55. 58 0
      app/UI/Resources/Templates/pages/resourcesContainer_components.js
  56. 39 0
      app/UI/Resources/Templates/pages/resourcesContainer_components.tpl
  57. 2 1
      app/UI/ServiceGraph/Pages/BaseGraph.php
  58. 2 0
      app/UI/Snapshot/Pages/SnapshotDataTable.php
  59. 1 0
      app/UI/Snapshot/Pages/SnapshotTrait.php
  60. 4 0
      app/UI/Snapshot/Providers/JobProvider.php
  61. 20 8
      app/UI/Snapshot/Providers/SnapshotProvider.php
  62. 46 5
      app/UI/VirtualInterface/Forms/CreateForm.php
  63. 2 0
      app/UI/VirtualNetwork/Buttons/CreateButton.php
  64. 5 1
      app/UI/Vm/Pages/DetailTab.php
  65. 55 0
      app/UI/Vm/Templates/pages/detailTab.tpl
  66. 8 1
      app/UI/VmCreate/Fields/IsoImageSelect.php
  67. 84 26
      app/UI/VmCreate/Fields/SecondaryIsoImageSelect.php
  68. 32 30
      app/UI/VmCreate/Sections/AccountSummary.php
  69. 14 25
      app/UI/VmCreate/Sections/Qemu/GeneralSection.php
  70. 0 2
      app/UI/VmCreate/Sections/TopSection.php
  71. 14 11
      app/UI/VmCreate/Sections/VirtualNetworkSection.php
  72. 31 0
      app/UI/VmCreate/Templates/sections/accountSummary.tpl
  73. 24 16
      app/UI/VmCreate/Validators/DiskSizeValidator.php
  74. 23 13
      app/UI/VmUpdate/Sections/Lxc/AdditionalDiskSection.php
  75. 4 8
      app/UI/VmUpdate/Sections/Qemu/AdditionalDiskSection.php
  76. 7 0
      app/UI/VmUpdate/Sections/VirtualNetworkSection.php
  77. 7 2
      app/UI/Vms/Modals/DeleteModal.php
  78. 3 0
      app/UI/Vms/Providers/DeleteVmProvider.php
  79. 1 1
      commands/commands.php
  80. 1 1
      core/App/Controllers/Instances/Addon/Deactivate.php
  81. 9 0
      core/UI/Widget/Forms/DataProviders/BaseModelDataProvider.php
  82. 171 18
      core/UI/Widget/Forms/Fields/Hidden.php
  83. 2 2
      logo.png
  84. 4 1
      packages/Provisioning/Config/PackageConfiguration.php
  85. 1 1
      templates/admin/assets/fonts/icons/Material-Design-Iconic-Font.eot
  86. 9 3
      templates/client/default/assets/css/mg_styles.css
  87. 3 1
      templates/client/default/assets/js/defaultComponents/ajaxFieldForDataTable.js
  88. 36 0
      templates/client/default/assets/js/defaultComponents/dataTableSelectFilter.js
  89. 2 2
      templates/client/default/ui/core/default/widget/forms/fields/hidden.tpl

+ 12 - 0
ProxmoxCloudVps.php

@@ -158,3 +158,15 @@ function ProxmoxCloudVps_ClientArea($params)
     return $appContext->runApp('clientarea', $params);
     return $appContext->runApp('clientarea', $params);
 }
 }
 
 
+function ProxmoxCloudVps_GetLicenseData($force = false)
+{
+    $class  = '';
+
+    if(!class_exists($class ))
+    {
+        return [];
+    }
+    $class = '\\'.$class;
+
+    return $class::getLicenseData($force);
+}

+ 56 - 1
app/Config/Packages/Provisioning.php

@@ -3,11 +3,11 @@
 
 
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Config\Packages;
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Config\Packages;
 
 
+use MGProvision\Proxmox\v2\repository\StorageRepository;
 use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
 use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
 use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\CustomField;
 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\Models\AvailableImages\Repository;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\ProductConfig\Providers\Config;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\ProductConfig\Providers\Config;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Packages\AppPackageConfiguration;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Packages\AppPackageConfiguration;
@@ -303,6 +303,61 @@ class WhmcsService extends AppPackageConfiguration
                 ]
                 ]
             ]
             ]
         ];
         ];
+        //snapshotJobs
+        $configOptions[] = [
+            Enum::OPTION_NAME         =>  ConfigurableOption::SNAPSHOT_JOBS.'|Snapshot Jobs',
+            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,
+                ]
+            ]
+        ];
+        //storage disk
+        $configOptions[] = [
+            Enum::OPTION_NAME => ConfigurableOption::STORAGE_DISK.'|Storage Disk Space',
+            Enum::OPTION_TYPE => Enum::OPTION_TYPE_DROPDOWN,
+        ];
+
+
         return $configOptions;
         return $configOptions;
     }
     }
+
+    public function storageDiskGetSubOptions()
+    {
+        $subOptions = [];
+        try
+        {
+            $subOptions[]               = [
+                Enum::OPTION_SUB_NAME  => '0|None',
+                Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+            ];
+            $unit = strtoupper($this->configuration()->getStorageUnit());
+            //node
+            $node = $this->getDefaultNode();
+            //storages
+            $storageRepository = new StorageRepository();
+            $storageRepository->findByNodes([$node->getNode()])
+                ->findEnabed();
+            $sizes =[100,200,300,400,500];
+            foreach ($storageRepository->fetch() as $storage)
+            {
+                foreach ($sizes as $size){
+                    $subOptions[] = [
+                        Enum::OPTION_SUB_NAME  => sprintf("%s:%s|%s %s %s",$storage->getStorage(), $size,$storage->getStorage(),$size, $unit),
+                        Enum::OPTION_SUB_ORDER => Enum::OPTION_SUB_ORDER_DEFAULT,
+                    ];
+                }
+            }
+            return $subOptions;
+        }
+        catch (ProxmoxApiException $ex)
+        {
+            return $subOptions;
+        }
+
+    }
 }
 }

+ 2 - 2
app/Config/configuration.yml

@@ -1,7 +1,7 @@
 version: '2.7.0'
 version: '2.7.0'
 systemName: 'ProxmoxCloudVps'
 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>.'
+name: 'Proxmox VE Cloud  VPS'
+description: 'Proxmox VE 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'
 clientareaName: 'MG Demo'
 author: '<a href="http://www.modulesgarden.com" targer="_blank">ModulesGarden</a>'
 author: '<a href="http://www.modulesgarden.com" targer="_blank">ModulesGarden</a>'
 moduleIcon: 'ip_manager'
 moduleIcon: 'ip_manager'

+ 20 - 0
app/Config/cron.yml

@@ -0,0 +1,20 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers;
+
+
+trait LicenseValidator
+{
+
+    public function isLicensePayingFullAnnuallyPrice($force = false){
+        if(!function_exists('ProxmoxCloudVps_GetLicenseData')){
+            return true;
+        }
+        $licenseData = ProxmoxCloudVps_GetLicenseData($force);
+        if(is_array($licenseData) && isset($licenseData['isPayingFullAnnuallyPrice']) && $licenseData['isPayingFullAnnuallyPrice'] !=1){
+            return false;
+        }
+        return true;
+    }
+}

+ 5 - 0
app/Helpers/ProxmoxAddonNotInstalledException.php

@@ -64,4 +64,9 @@ class UrlServiceHelper
         return $this->urlService->getUrl();
         return $this->urlService->getUrl();
     }
     }
 
 
+    public function getDownloadFirewallRulesUrl(){
+        $id = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
+        return $this->urlService->getUrl('vm', 'download',['vm'=> $id]);
+    }
+
 }
 }

+ 5 - 2
app/Hooks/AdminAreaFooterOutput.php

@@ -59,8 +59,11 @@ class ChangePackage extends AddonController
             //Assing ip
             //Assing ip
             if (!Utility::isIpManagerProxmoxCloudIntegration())
             if (!Utility::isIpManagerProxmoxCloudIntegration())
             {
             {
-                list($ip4, $ip6) = $this->networkService->getIpAddressesRequest();
-                $this->networkService->addIp($ip4, $ip6, $this->getDefaultNodeIfSet());
+                if($this->configuration()->isOrderPublicIp()){
+                    list($ip4, $ip6) = $this->networkService->getIpAddressesRequest();
+                    $bridge = $this->configuration()->getBridge();
+                    $this->networkService->addIp($ip4, $ip6, $this->getDefaultNodeIfSet(),$bridge);
+                }
             }
             }
             return "success";
             return "success";
         }catch (\Exception $ex)
         }catch (\Exception $ex)

+ 5 - 3
app/Http/Actions/ChangeUserRole.php

@@ -65,9 +65,11 @@ class CreateAccount extends AddonController
             //Assing ip
             //Assing ip
             if (!Utility::isIpManagerProxmoxCloudIntegration())
             if (!Utility::isIpManagerProxmoxCloudIntegration())
             {
             {
-                list($ip4, $ip6) = $this->networkService->getIpAddressesRequest();
-
-                $this->networkService->addIp($ip4, $ip6, $this->getDefaultNodeIfSet());
+                if($this->configuration()->isOrderPublicIp()){
+                    list($ip4, $ip6) = $this->networkService->getIpAddressesRequest();
+                    $bridge = $this->configuration()->getBridge();
+                    $this->networkService->addIp($ip4, $ip6, $this->getDefaultNodeIfSet(), $bridge);
+                }
             }
             }
             if( $this->isUser()){
             if( $this->isUser()){
                 return "success";
                 return "success";

+ 1 - 1
app/Http/Actions/MetaData.php

@@ -26,7 +26,7 @@ class MetaData extends AddonController
     public function execute($params = null)
     public function execute($params = null)
     {
     {
         return [
         return [
-            'DisplayName'    => 'Proxmox Cloud VPS',
+            'DisplayName'    => 'Proxmox VE Cloud  VPS',
             'RequiresServer' => true,
             'RequiresServer' => true,
             'DefaultNonSSLPort' => '8006', // Default Non-SSL Connection Port
             'DefaultNonSSLPort' => '8006', // Default Non-SSL Connection Port
             'DefaultSSLPort' => '8006', // Default SSL Connection Port
             'DefaultSSLPort' => '8006', // Default SSL Connection Port

+ 14 - 4
app/Http/Actions/ResetBandwidth.php

@@ -3,6 +3,7 @@
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Admin;
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Admin;
 
 
 use MGProvision\Proxmox\v2\Api;
 use MGProvision\Proxmox\v2\Api;
+use ModulesGarden\ProxmoxAddon\App\Repositories\ModuleSettingRepository;
 use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
@@ -31,17 +32,26 @@ class Home extends AbstractController
     use UserService;
     use UserService;
     public function index()
     public function index()
     {
     {
+        $this->moduleSetting = new ModuleSettingRepository();
         $view = Helper\viewIntegrationAddon();
         $view = Helper\viewIntegrationAddon();
         $view->initCustomAssetFiles();
         $view->initCustomAssetFiles();
         (new AppParams())->initFromWhmcsParams();
         (new AppParams())->initFromWhmcsParams();
         //Resurces
         //Resurces
-        $view->addElement(AccountResourcesContainer::class);
+        if($this->moduleSetting->isPermissionAccountResources()){
+            $view->addElement(AccountResourcesContainer::class);
+        }
         //VMs
         //VMs
-        $view->addElement(VmsDataTable::class);
+        if($this->moduleSetting->isPermissionVms()){
+            $view->addElement(VmsDataTable::class);
+        }
         //IPs
         //IPs
-        $view->addElement(IpAddressDataTable::class);
+        if($this->moduleSetting->isPermissionIpAddresses()){
+            $view->addElement(IpAddressDataTable::class);
+        }
         //User
         //User
-        $view->addElement(UserDataTable::class);
+        if($this->moduleSetting->isPermissionUserDetails()){
+            $view->addElement(UserDataTable::class);
+        }
         return $view;
         return $view;
 
 
     }
     }

+ 1 - 1
app/Http/Admin/Product.php

@@ -36,7 +36,7 @@ trait BaseClientController
         if (!$vmModel->vmid || $vmModel->vmid == 0 ){
         if (!$vmModel->vmid || $vmModel->vmid == 0 ){
             return false;
             return false;
         }
         }
-        if(Job::waiting()->ofHostingId($this->getWhmcsParamByKey("serviceid"))->ofJobs($jobs)->ofCustomId($vmModel->id)->count() > 0){
+        if(Job::waiting()->ofHostingId($vmModel->hosting_id)->ofJobs($jobs)->ofCustomId($vmModel->id)->count() > 0){
             return false;
             return false;
         }
         }
 
 

+ 100 - 1
app/Http/Client/Console.php

@@ -3,17 +3,25 @@
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Client;
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Client;
 
 
 use MGProvision\Proxmox\v2\Api;
 use MGProvision\Proxmox\v2\Api;
+use MGProvision\Proxmox\v2\models\Kvm;
+use MGProvision\Proxmox\v2\models\Lxc;
+use ModulesGarden\ProxmoxAddon\App\Factory\ProxyServiceFactory;
 use ModulesGarden\ProxmoxAddon\App\Models\ModuleSettings;
 use ModulesGarden\ProxmoxAddon\App\Models\ModuleSettings;
+use ModulesGarden\ProxmoxAddon\App\Repositories\ModuleSettingRepository;
+use ModulesGarden\ProxmoxAddon\App\Repositories\ServerConfigurationRepository;
 use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\UserService;
 use ModulesGarden\ProxmoxAddon\App\Services\Utility;
 use ModulesGarden\ProxmoxAddon\App\Services\Utility;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\LicenseValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\DetailsContainer;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Home\Pages\DetailsContainer;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\Http\AbstractClientController;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\Http\AbstractClientController;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\ModuleConstants;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\StreamedResponse;
 use Symfony\Component\HttpFoundation\StreamedResponse;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
 
 
 class Console extends AbstractClientController
 class Console extends AbstractClientController
 {
 {
@@ -23,8 +31,12 @@ class Console extends AbstractClientController
     use ApiService;
     use ApiService;
     use ProductService;
     use ProductService;
     use BaseClientController;
     use BaseClientController;
+    use LicenseValidator;
 
 
-
+    /**
+     * @var ModuleSettingRepository
+     */
+    protected $moduleConfiguration;
     /**
     /**
      * Console constructor.
      * Console constructor.
      */
      */
@@ -37,12 +49,20 @@ class Console extends AbstractClientController
     public function novnc()
     public function novnc()
     {
     {
         $this->acl()->novnc();
         $this->acl()->novnc();
+        $this->moduleConfiguration = new ModuleSettingRepository();
+        if($this->moduleConfiguration->getConsoleApiKey() && $this->moduleConfiguration->consoleHost && $this->isLicensePayingFullAnnuallyPrice()){
+            $this->novncProxy();
+        }
         $this->console(['novnc' => 1]);
         $this->console(['novnc' => 1]);
     }
     }
 
 
     public function xtermjs()
     public function xtermjs()
     {
     {
         $this->acl()->xtermjs();
         $this->acl()->xtermjs();
+        $this->moduleConfiguration = new ModuleSettingRepository();
+        if($this->moduleConfiguration->getConsoleApiKey() && $this->moduleConfiguration->consoleHost && $this->isLicensePayingFullAnnuallyPrice()){
+            $this->xtermjsProxy();
+        }
         $this->console(['xtermjs' => 1]);
         $this->console(['xtermjs' => 1]);
     }
     }
 
 
@@ -140,4 +160,83 @@ class Console extends AbstractClientController
         $response->send();
         $response->send();
         exit();
         exit();
     }
     }
+
+    /**
+     * @return Kvm|Lxc
+     */
+    protected function vmAsUser(){
+        if($this->vmAsUser){
+            return $this->vmAsUser;
+        }
+        //User
+        $vpsUser = $this->getUser();
+        if (empty($vpsUser->username))
+        {
+            throw new \Exception('User does not have permissions to access noVNC console');
+        }
+        $serverHost = $this->getWhmcsParamByKey('serverip') ? $this->getWhmcsParamByKey('serverip') : $this->getWhmcsParamByKey('serverhostname');
+        //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());
+        //websocket
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $vm->setApi($api);
+        if(!$vm->isRunning()){
+            throw new \Exception(sl('lang')->abtr("VM not running"));
+        }
+        return $this->vmUser = $vm;
+    }
+
+    public function novncProxy(){
+        $vars=[
+            'novncAppUrl' => './modules/addons/proxmoxAddon/templates/client/default/novnc'
+        ];
+        if($this->isAdmin()){
+            $vars['novncAppUrl']=  '../modules/addons/proxmoxAddon/templates/client/default/novnc';
+        }
+        try{
+            $vnc = $this->vmAsUser()->vncproxy(1);
+            $vncHost = $this->vmAsUser()->vncWebsocketPath( $vnc);
+            $clientIp = sl('request')->getClientIp();
+            //proxy generate token
+            $procyService = (new ProxyServiceFactory())->fromModuleConfiguration($this->moduleConfiguration);
+            $vars['websocketUrl'] = $procyService->proxmox("https://".$vncHost, $clientIp, $this->vmAsUser()->getApi()->getAuthCookieAsArray());
+            $vars['password'] = $vnc['ticket'];
+
+        }catch (\Exception $ex){
+            $vars['error'] = $ex->getMessage();
+        }
+        echo $this->getSmarty()
+            ->view(ModuleConstants::getFullPathWhmcs().DS.'modules'.DS.'addons'.DS.'proxmoxAddon'.DS.'templates'.DS.'client'.DS.'default'.DS.'pages'.DS.'console'.DS.'novnc', $vars);
+        exit();
+    }
+
+    public function xtermjsProxy(){
+
+        $vars=[
+            'appUrl' => './modules/addons/proxmoxAddon/templates/client/default',
+        ];
+        if($this->isAdmin()){
+            $vars['appUrl']=  '../modules/addons/proxmoxAddon/templates/client/default';
+        }
+        try{
+            $vnc = $this->vmAsUser()->termproxy();
+            $vncHost = $this->vmAsUser()->vncWebsocketPath( $vnc);
+            $clientIp = sl('request')->getClientIp();
+            //proxy generate token
+            $procyService = (new ProxyServiceFactory())->fromModuleConfiguration($this->moduleConfiguration);
+            $vars['websocketUrl'] = $procyService->proxmox("https://".$vncHost, $clientIp, $this->vmAsUser()->getApi()->getAuthCookieAsArray());
+            $vars['password'] = $vnc['ticket'];
+            $vars['user'] =$vnc['user'];
+        }catch (\Exception $ex){
+            $vars['error'] = $ex->getMessage();
+        }
+        echo $this->getSmarty()
+            ->view(ModuleConstants::getFullPathWhmcs().DS.'modules'.DS.'addons'.DS.'proxmoxAddon'.DS.'templates'.DS.'client'.DS.'default'.DS.'pages'.DS.'console'.DS.'xtermjs', $vars);
+        exit();
+    }
+
 }
 }

+ 24 - 6
app/Http/Client/CustomTemplate.php

@@ -4,6 +4,7 @@
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Client;
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\Http\Client;
 
 
 
 
+use MGProvision\Proxmox\v2\repository\FirewallRulesRepository;
 use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\AppParams;
@@ -21,6 +22,7 @@ use ModulesGarden\Servers\ProxmoxCloudVps\Core\Http\AbstractClientController;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\WhmcsParams;
 use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
 use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
 use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\view;
 use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\view;
+use Symfony\Component\HttpFoundation\StreamedResponse;
 
 
 class Vm extends AbstractClientController
 class Vm extends AbstractClientController
 {
 {
@@ -67,21 +69,37 @@ class Vm extends AbstractClientController
         (new AppParams())->initFromWhmcsParams();
         (new AppParams())->initFromWhmcsParams();
         $view = view();
         $view = view();
         $view->initCustomAssetFiles();
         $view->initCustomAssetFiles();
-        /**
-         * @deprecated
-         *     $view->addElement(\ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Sections\AccountSummary::class);
-         */
-
         return $view->addElement(VmCreateForm::class);
         return $view->addElement(VmCreateForm::class);
     }
     }
 
 
     public function update()
     public function update()
     {
     {
-//        sl("sidebar")->getSidebar("virtualMachinesProxmoxCloudVps")->getChild("vmupdate")->setActive(true);
         $this->initVm();
         $this->initVm();
         (new AppParams())->initFromWhmcsParams();
         (new AppParams())->initFromWhmcsParams();
         $this->api();
         $this->api();
         return view()->addElement(VmUpdateForm::class);
         return view()->addElement(VmUpdateForm::class);
     }
     }
 
 
+    public function download()
+    {
+        $this->initVm();
+        (new AppParams())->initFromWhmcsParams();
+        $this->api();
+        $response = new StreamedResponse();
+        $response->setStatusCode(200);
+        $response->headers->set('Content-Type', 'application/json; charset=utf-8');
+        $response->headers->set('Content-Transfer-Encoding', 'Binary');
+        $filename = sprintf("%s-firewal-rules.json",\ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->name);
+        $response->headers->set('Content-Disposition', 'attachment; filename="'.$filename.'"');
+        $firewalRules = new FirewallRulesRepository();
+        $firewalRules->setApi($this->api());
+        $firewalRules->findByVmModel([\ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()]);
+        $response->setCallback(function () use( $firewalRules)
+        {
+            echo  \json_encode($firewalRules->fetchAsArray());
+            die();
+        });
+        $response->send();
+    }
+
 }
 }

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

@@ -19,9 +19,11 @@
 
 
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Forms;
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Forms;
 
 
+use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\LicenseValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Buttons\VirtualizationChangButton;
 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\Providers\ProductProvider;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\AdminNotificationSection;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\AdminNotificationSection;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\AlertSection;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\BackupSection;
 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\ClientNotificationSection;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\ConsoleSection;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\ConsoleSection;
@@ -43,6 +45,8 @@ use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\FormIntegration;
 class MainForm extends FormIntegration implements AdminArea
 class MainForm extends FormIntegration implements AdminArea
 {
 {
 
 
+    use LicenseValidator;
+
     public function initContent()
     public function initContent()
     {
     {
        /**
        /**
@@ -56,6 +60,7 @@ class MainForm extends FormIntegration implements AdminArea
          *
          *
          */
          */
         $isQemu = !$this->dataProvider->getValueById('customconfigoption[virtualization]') || $this->dataProvider->getValueById('customconfigoption[virtualization]') == "qemu";
         $isQemu = !$this->dataProvider->getValueById('customconfigoption[virtualization]') || $this->dataProvider->getValueById('customconfigoption[virtualization]') == "qemu";
+        $this->licenseAlert();
         /**
         /**
          * Main Section
          * Main Section
          */
          */
@@ -134,4 +139,11 @@ class MainForm extends FormIntegration implements AdminArea
         }
         }
         return array_unique($fieldNames);
         return array_unique($fieldNames);
     }
     }
+
+    public function licenseAlert(){
+        if(!$this->isLicensePayingFullAnnuallyPrice(true)){
+            $this->addSection(new AlertSection("You can use proxy for Proxmox console connections to increase the security of your infrastructure. Please contact <a href='https://www.modulesgarden.com/support/ticket/product-presales/Proxmox%20module%20upgrade%20request%20-%20Proxy%20console' target='_blank'>ModulesGarden support</a> to get more details and upgrade your module."));
+        }
+
+    }
 }
 }

+ 69 - 8
app/UI/Admin/Product/Forms/VirtualizationChangeForm.php

@@ -24,9 +24,11 @@ use MGProvision\Proxmox\v2\repository\ClusterResourcesRepository;
 use MGProvision\Proxmox\v2\repository\FileRepository;
 use MGProvision\Proxmox\v2\repository\FileRepository;
 use MGProvision\Proxmox\v2\repository\NodeRepository;
 use MGProvision\Proxmox\v2\repository\NodeRepository;
 use MGProvision\Proxmox\v2\repository\StorageRepository;
 use MGProvision\Proxmox\v2\repository\StorageRepository;
+use ModulesGarden\ProxmoxAddon\App\Helper\VmidHelper;
 use ModulesGarden\ProxmoxAddon\App\Models\CloudInitScript;
 use ModulesGarden\ProxmoxAddon\App\Models\CloudInitScript;
 use ModulesGarden\ProxmoxAddon\App\Models\IpAddress;
 use ModulesGarden\ProxmoxAddon\App\Models\IpAddress;
 use ModulesGarden\ProxmoxAddon\App\Models\ProductConfiguration;
 use ModulesGarden\ProxmoxAddon\App\Models\ProductConfiguration;
+use ModulesGarden\ProxmoxAddon\App\Models\ServerGroup;
 use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Hosting;
 use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Hosting;
 use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Product;
 use ModulesGarden\ProxmoxAddon\App\Models\Whmcs\Product;
 use ModulesGarden\ProxmoxAddon\App\Repositories\Cloud\ProductConfigurationRepository;
 use ModulesGarden\ProxmoxAddon\App\Repositories\Cloud\ProductConfigurationRepository;
@@ -45,6 +47,7 @@ class ProductProvider extends BaseDataProvider implements AdminArea
 {
 {
     use ApiService;
     use ApiService;
     use ProductService;
     use ProductService;
+    use VmidHelper;
 
 
     private $productId;
     private $productId;
 
 
@@ -79,11 +82,7 @@ class ProductProvider extends BaseDataProvider implements AdminArea
     public function read()
     public function read()
     {
     {
         foreach ($this->configuration->all() as $key => $value) {
         foreach ($this->configuration->all() as $key => $value) {
-            if ($key == "serverSockets") {
-
-
-            }
-            //multiselect
+             //multiselect
             if (is_array($value)) {
             if (is_array($value)) {
                 $this->data[sprintf("customconfigoption[%s][]", $key)] = $value;
                 $this->data[sprintf("customconfigoption[%s][]", $key)] = $value;
                 continue;
                 continue;
@@ -130,6 +129,7 @@ class ProductProvider extends BaseDataProvider implements AdminArea
         $nodeRepository->setApi($this->api());
         $nodeRepository->setApi($this->api());
         $nodeRepository->findOnline(true);
         $nodeRepository->findOnline(true);
         foreach ($nodeRepository->fetch() as $node) {
         foreach ($nodeRepository->fetch() as $node) {
+            $this->nodes[] = $node->getNode();
             $this->availableValues["customconfigoption[defaultNode]"][$node->getNode()] = $node->getNode();
             $this->availableValues["customconfigoption[defaultNode]"][$node->getNode()] = $node->getNode();
             //locations
             //locations
             $this->availableValues["customconfigoption[locations][]"][$node->getNode()] = $node->getNode();
             $this->availableValues["customconfigoption[locations][]"][$node->getNode()] = $node->getNode();
@@ -219,13 +219,42 @@ class ProductProvider extends BaseDataProvider implements AdminArea
             "ndp" => $lang->abtr("NDP"),
             "ndp" => $lang->abtr("NDP"),
             "macfilter" => $lang->abtr("MAC Filter"),
             "macfilter" => $lang->abtr("MAC Filter"),
             "ipfilter" => $lang->abtr("IP Filter"),
             "ipfilter" => $lang->abtr("IP Filter"),
+            "policy_in" => $lang->abtr("Input Policy"),
+            "policy_out" => $lang->abtr("Output Policy"),
         ];
         ];
         //buttonSyle
         //buttonSyle
         $this->availableValues["customconfigoption[buttonSyle]"] = ["tiles" => $lang->tr('Tiles'), 'buttons' => $lang->tr('Buttons'),];
         $this->availableValues["customconfigoption[buttonSyle]"] = ["tiles" => $lang->tr('Tiles'), 'buttons' => $lang->tr('Buttons'),];
         //detailsView
         //detailsView
         $this->availableValues["customconfigoption[detailsView]"] = ["standard" => $lang->tr('Standard'),
         $this->availableValues["customconfigoption[detailsView]"] = ["standard" => $lang->tr('Standard'),
             'combined' => $lang->tr('Combined'),];
             'combined' => $lang->tr('Combined'),];
-
+        //serverGroup
+        $this->serverGroupRead();
+        //firewalOptionPolicyIn
+        $this->availableValues["customconfigoption[firewalOptionPolicyIn]"] = [
+            "0" => "",
+            "DROP"   => sl("lang")->abtr("DROP"),
+            "ACCEPT" => sl("lang")->abtr("ACCEPT"),
+            "REJECT" => sl("lang")->abtr("REJECT"),
+        ];
+        //firewalOptionPolicyOut
+        $this->availableValues["customconfigoption[firewalOptionPolicyOut]"] = [
+            "0" => "",
+            "DROP"   => sl("lang")->abtr("DROP"),
+            "ACCEPT" => sl("lang")->abtr("ACCEPT"),
+            "REJECT" => sl("lang")->abtr("REJECT"),
+        ];
+        //permissionBackupCompress
+        $this->availableValues["customconfigoption[permissionBackupCompress][]"] = [
+            "none"   => $lang->abtr("None"),
+            "lzo" => $lang->abtr("LZO (fast)"),
+            "gzip" => $lang->abtr("GZIP (good)"),
+            "zstd" => $lang->abtr("ZSTD (fast and good)"),
+        ];
+        //permissionSnapshotJobPeriod
+        $this->availableValues["customconfigoption[permissionSnapshotJobPeriod][]"] = [
+            JobPeriod::HOURLY => $lang->tr(JobPeriod::HOURLY),
+            JobPeriod::DAILY => $lang->tr(JobPeriod::DAILY)
+        ];
     }
     }
 
 
     /**
     /**
@@ -337,7 +366,7 @@ class ProductProvider extends BaseDataProvider implements AdminArea
         //memoryUnit
         //memoryUnit
         $this->availableValues["customconfigoption[memoryUnit]"] = ['mb' => $lang->tr("MB"), "gb" => $lang->tr("GB")];
         $this->availableValues["customconfigoption[memoryUnit]"] = ['mb' => $lang->tr("MB"), "gb" => $lang->tr("GB")];
         //storageUnit
         //storageUnit
-        $this->availableValues["customconfigoption[storageUnit]"] = ['mb' => $lang->tr("MB"), "gb" => $lang->tr("GB"), "tb" => $lang->tr("TB")];
+        $this->availableValues["customconfigoption[storageUnit]"] = [ "gb" => $lang->tr("GB"), "tb" => $lang->tr("TB")];
         //cdromType
         //cdromType
         $this->availableValues["customconfigoption[cdromType]"] = $this->availableValues["customconfigoption[diskType]"];
         $this->availableValues["customconfigoption[cdromType]"] = $this->availableValues["customconfigoption[diskType]"];
         //bios
         //bios
@@ -358,6 +387,17 @@ class ProductProvider extends BaseDataProvider implements AdminArea
         foreach ($jsonData->get() as $k => $name) {
         foreach ($jsonData->get() as $k => $name) {
             $this->availableValues["customconfigoption[cpu]"][$k] = $lang->tr($name);
             $this->availableValues["customconfigoption[cpu]"][$k] = $lang->tr($name);
         }
         }
+        //archive
+        $fileRepository->findBackupQemuTemplates();
+        $fileRepository->findByNodes($this->nodes);
+        foreach (   $fileRepository->fetch() as $file) {
+            if($this->vmidExistInWhmcs($file->getVmid())){
+                continue;
+            }
+            $this->availableValues["customconfigoption[archive][]"][$file->getNode().":".$file->getVolid()] = $file->formatVolid();
+        }
+        //cloudInitStorage
+        $this->availableValues["customconfigoption[cloudInitStorage]"] = [0=> ""] + $this->availableValues["customconfigoption[diskStorage]"];
 
 
     }
     }
 
 
@@ -395,7 +435,7 @@ class ProductProvider extends BaseDataProvider implements AdminArea
         //memoryUnit
         //memoryUnit
         $this->availableValues["customconfigoption[memoryUnit]"] = ['mb' => $lang->tr("MB"), "gb" => $lang->tr("GB")];
         $this->availableValues["customconfigoption[memoryUnit]"] = ['mb' => $lang->tr("MB"), "gb" => $lang->tr("GB")];
         //storageUnit
         //storageUnit
-        $this->availableValues["customconfigoption[storageUnit]"] = ['mb' => $lang->tr("MB"), "gb" => $lang->tr("GB"), "tb" => $lang->tr("TB")];
+        $this->availableValues["customconfigoption[storageUnit]"] = [ "gb" => $lang->tr("GB"), "tb" => $lang->tr("TB")];
         //persimonOsTemplates
         //persimonOsTemplates
         $this->availableValues["customconfigoption[permissionOsTemplates][]"] = $this->availableValues["customconfigoption[osTemplate]"];
         $this->availableValues["customconfigoption[permissionOsTemplates][]"] = $this->availableValues["customconfigoption[osTemplate]"];
         //mountPointStorage
         //mountPointStorage
@@ -423,6 +463,15 @@ class ProductProvider extends BaseDataProvider implements AdminArea
         ksort($this->availableValues["customconfigoption[bridge]"]);
         ksort($this->availableValues["customconfigoption[bridge]"]);
         //privateBridge
         //privateBridge
         $this->availableValues["customconfigoption[privateBridge]"] = ['0' => ""] + (array)$this->availableValues["customconfigoption[bridge]"];
         $this->availableValues["customconfigoption[privateBridge]"] = ['0' => ""] + (array)$this->availableValues["customconfigoption[bridge]"];
+        //archive
+        $fileRepository->findBackupLxcTemplates();
+        $fileRepository->findByNodes($this->nodes);
+        foreach (   $fileRepository->fetch() as $file) {
+            if($this->vmidExistInWhmcs($file->getVmid())){
+                continue;
+            }
+            $this->availableValues["customconfigoption[archive][]"][$file->getNode().":".$file->getVolid()] = $file->formatVolid();
+        }
     }
     }
 
 
     public function update()
     public function update()
@@ -479,4 +528,16 @@ class ProductProvider extends BaseDataProvider implements AdminArea
             $newEntity->save();
             $newEntity->save();
         }
         }
     }
     }
+
+    protected function serverGroupRead(){
+        $groupId  = sl("whmcsParams")->getWhmcsParams()['groupid'];
+        $sg = (new ServerGroup())->getTable();
+        $ssg = "tblservergroupsrel";
+        $query = ServerGroup::select("{$sg}.id", "{$sg}.name")
+            ->leftJoin($ssg,"{$ssg}.serverid","=","{$sg}.server_id"  )
+            ->where("{$ssg}.groupid", $groupId);
+        foreach ($query->get() as $row){
+            $this->availableValues['customconfigoption[serverGroup][]'][$row->id] = $row->name;
+        }
+    }
 }
 }

+ 30 - 0
app/UI/Admin/Product/Sections/AlertSection.php

@@ -0,0 +1,30 @@
+<?php
+
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
+
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Traits\Alerts;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
+
+class AlertSection extends BoxSection implements AdminArea
+{
+
+    use Alerts;
+
+    public function __construct($mesage , $type ='info')
+    {
+        $this->internalAlertMessage = $mesage;
+        $this->internalAlertMessageType = $type;
+        parent::__construct('alertSection');
+    }
+
+    public function initContent()
+    {
+//        dump($this->getTemplateDir());
+//        $this->getHtml();
+//        die();
+
+    }
+}

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

@@ -3,6 +3,7 @@
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections;
 
 
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
 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\Switcher;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\BoxSection;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Sections\HalfPageSection;
@@ -54,6 +55,13 @@ class FirewallOptionSection extends BoxSection implements AdminArea
         //ipfilter
         //ipfilter
         $field = new Switcher("customconfigoption[firewalOptionIpfilter]");
         $field = new Switcher("customconfigoption[firewalOptionIpfilter]");
         $this->addField($field);
         $this->addField($field);
+        //policy_out
+        $field = new Select("customconfigoption[firewalOptionPolicyIn]");
+        $this->addField($field);
+        //policy_out
+        $field = new Select("customconfigoption[firewalOptionPolicyOut]");
+        $this->addField($field);
+
     }
     }
 
 
     public function addField($field){
     public function addField($field){

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

@@ -50,6 +50,16 @@ class LoadBalancerSection extends BoxSection implements AdminArea
         $field = new Switcher('customconfigoption[loadBalancerStopOnUpgrade]');
         $field = new Switcher('customconfigoption[loadBalancerStopOnUpgrade]');
         $field->setDescription('tip');
         $field->setDescription('tip');
         $this->rightSection->addField($field);
         $this->rightSection->addField($field);
+        //serverGroup
+        $field = new Select('customconfigoption[serverGroup][]');
+        $field->enableMultiple();
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
+        //with-local-disks
+        $field = new Switcher('customconfigoption[loadBalancerMigrationWithLocalDisks]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+
     }
     }
 
 
 }
 }

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

@@ -164,6 +164,31 @@ class ClientAreaSection extends TwiceColumnSection implements AdminArea
         $field->setDescription('tip');
         $field->setDescription('tip');
         $field->setDefaultValue("on");
         $field->setDefaultValue("on");
         $this->addField($field);
         $this->addField($field);
+        //permissionBackupCompress
+        $field = new Select("customconfigoption[permissionBackupCompress][]");
+        $field->enableMultiple();
+        $field->setDescription('description');
+        $this->addField($field);
+        //Snapshot Jobs
+        $field = new Switcher('customconfigoption[permissionSnapshotJob]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //How Often
+        $field = new Select('customconfigoption[permissionSnapshotJobPeriod][]');
+        $field->setDescription('tip');
+        $field->enableMultiple();
+        $this->addField($field);
+        //permissionArchive
+        $field = new Switcher('customconfigoption[permissionArchive]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //archive
+        $field = new Select('customconfigoption[archive][]');
+        $field->enableMultiple();
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
     }
     }
 
 
 
 

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

@@ -86,6 +86,11 @@ class DefaultConfigurationSection extends TwiceColumnSection implements AdminAre
         $field->setDescription('tip');
         $field->setDescription('tip');
         $field->setDefaultValue(1);
         $field->setDefaultValue(1);
         $this->addField($field);
         $this->addField($field);
+        //snapshotJobs
+        $field = new Text('customconfigoption[snapshotJobs]');
+        $field->setDescription('tip');
+        $field->setDefaultValue(1);
+        $this->addField($field);
     }
     }
 
 
 }
 }

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

@@ -58,10 +58,12 @@ class NetworkSection extends BoxSection implements AdminArea
         $this->leftSection->addField($field);
         $this->leftSection->addField($field);
         //VLAN TAG Range From
         //VLAN TAG Range From
         $field = new Text('customconfigoption[tagFrom]');
         $field = new Text('customconfigoption[tagFrom]');
+        $field->setDecimal(1);
         $field->setDescription('tip');
         $field->setDescription('tip');
         $this->rightSection->addField($field);
         $this->rightSection->addField($field);
         //VLAN TAG Range To
         //VLAN TAG Range To
         $field = new Text('customconfigoption[tagTo]');
         $field = new Text('customconfigoption[tagTo]');
+        $field->setDecimal(4094);
         $field->setDescription('tip');
         $field->setDescription('tip');
         $this->leftSection->addField($field);
         $this->leftSection->addField($field);
         //Tag
         //Tag

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

@@ -56,5 +56,10 @@ class ServerSection extends TwiceColumnSection implements AdminArea
         $field->setDescription('tip');
         $field->setDescription('tip');
         $field->setDefaultValue('0-10');
         $field->setDefaultValue('0-10');
         $this->addField($field);
         $this->addField($field);
+        //serverInterfaces
+        $field = new Text('customconfigoption[serverVirtualInterfaces]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('0-10');
+        $this->addField($field);
     }
     }
 }
 }

+ 10 - 1
app/UI/Admin/Product/Sections/MainSection.php

@@ -40,7 +40,7 @@ class MiscellaneousSection extends BoxSection implements AdminArea
         $field->setDescription('tip');
         $field->setDescription('tip');
         $this->leftSection->addField($field);
         $this->leftSection->addField($field);
         //Reboot VM After Changing Package
         //Reboot VM After Changing Package
-        $field = new Switcher('customconfigoption[rebootVmAfterUpgrade');
+        $field = new Switcher('customconfigoption[rebootVmAfterUpgrade]');
         $field->setDescription('tip');
         $field->setDescription('tip');
         $this->rightSection->addField($field);
         $this->rightSection->addField($field);
         //Bandwidth Overage
         //Bandwidth Overage
@@ -61,6 +61,15 @@ class MiscellaneousSection extends BoxSection implements AdminArea
         $field->setDefaultValue('standard');
         $field->setDefaultValue('standard');
         $field->setDescription('tip');
         $field->setDescription('tip');
         $this->leftSection->addField($field);
         $this->leftSection->addField($field);
+        //Order Public IP
+        $field = new Switcher('customconfigoption[suspendOnBandwidthOverage]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+        //Order Public IP
+        $field = new Switcher('customconfigoption[orderPublicIp]');
+        $field->setDefaultValue('on');
+        $field->setDescription('tip');
+        $this->leftSection->addField($field);
     }
     }
 
 
 }
 }

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

@@ -221,6 +221,31 @@ class ClientAreaSection extends TwiceColumnSection implements AdminArea
         $field->enableMultiple();
         $field->enableMultiple();
         $field->setDescription('tip');
         $field->setDescription('tip');
         $this->leftSection->addField($field);
         $this->leftSection->addField($field);
+        //permissionBackupCompress
+        $field = new Select("customconfigoption[permissionBackupCompress][]");
+        $field->enableMultiple();
+        $field->setDescription('description');
+        $this->addField($field);
+        //Snapshot Jobs
+        $field = new Switcher('customconfigoption[permissionSnapshotJob]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //How Often
+        $field = new Select('customconfigoption[permissionSnapshotJobPeriod][]');
+        $field->setDescription('tip');
+        $field->enableMultiple();
+        $this->addField($field);
+        //permissionArchive
+        $field = new Switcher('customconfigoption[permissionArchive]');
+        $field->setDescription('tip');
+        $field->setDefaultValue("on");
+        $this->addField($field);
+        //archive
+        $field = new Select('customconfigoption[archive][]');
+        $field->enableMultiple();
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
     }
     }
     
     
 }
 }

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

@@ -4,6 +4,7 @@ namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\Qe
 
 
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\TwiceColumnSection;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Admin\Product\Sections\TwiceColumnSection;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
 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\Switcher;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
 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\Fields\Textarea;
@@ -31,6 +32,11 @@ class CloudInitSection extends TwiceColumnSection implements AdminArea
         $field = new Textarea('customconfigoption[cicustom]');
         $field = new Textarea('customconfigoption[cicustom]');
         $field->setDescription('tip');
         $field->setDescription('tip');
         $this->addField($field);
         $this->addField($field);
+        //cloudInitStorage
+        $field = new Select('customconfigoption[cloudInitStorage]');
+        $field->setDescription('tip');
+        $this->rightSection->addField($field);
+
 
 
     }
     }
 
 

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

@@ -171,6 +171,7 @@ class ConfigurationSection extends BoxSection implements AdminArea
         $field = new Text('customconfigoption[vgaMemory]');
         $field = new Text('customconfigoption[vgaMemory]');
         $field->setDescription('tip');
         $field->setDescription('tip');
         $this->leftSection->addField($field);
         $this->leftSection->addField($field);
+
     }
     }
 
 
 }
 }

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

@@ -84,6 +84,11 @@ class DefaultConfigurationSection extends TwiceColumnSection implements AdminAre
         $field->setDescription('tip');
         $field->setDescription('tip');
         $field->setDefaultValue(1);
         $field->setDefaultValue(1);
         $this->addField($field);
         $this->addField($field);
+        //snapshotJobs
+        $field = new Text('customconfigoption[snapshotJobs]');
+        $field->setDescription('tip');
+        $field->setDefaultValue(1);
+        $this->addField($field);
     }
     }
 
 
 }
 }

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

@@ -56,10 +56,12 @@ class NetworkSection extends TwiceColumnSection implements AdminArea
         $this->addField($field);
         $this->addField($field);
         //VLAN TAG Range From
         //VLAN TAG Range From
         $field = new Text('customconfigoption[tagFrom]');
         $field = new Text('customconfigoption[tagFrom]');
+        $field->setDecimal(1);
         $field->setDescription('tip');
         $field->setDescription('tip');
         $this->addField($field);
         $this->addField($field);
         //VLAN TAG Range To
         //VLAN TAG Range To
         $field = new Text('customconfigoption[tagTo]');
         $field = new Text('customconfigoption[tagTo]');
+        $field->setDecimal(4094);
         $field->setDescription('tip');
         $field->setDescription('tip');
         $this->addField($field);
         $this->addField($field);
         //Tag
         //Tag

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

@@ -61,5 +61,10 @@ class ServerSection extends TwiceColumnSection implements AdminArea
         $field->setDescription('tip');
         $field->setDescription('tip');
         $field->setDefaultValue('0-10');
         $field->setDefaultValue('0-10');
         $this->addField($field);
         $this->addField($field);
+        //serverInterfaces
+        $field = new Text('customconfigoption[serverVirtualInterfaces]');
+        $field->setDescription('tip');
+        $field->setDefaultValue('0-10');
+        $this->addField($field);
     }
     }
 }
 }

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

@@ -0,0 +1,5 @@
+<div class="alert {if $rawObject->getInternalAlertSize() !== ''}alert--{$rawObject->getInternalAlertSize()}{/if} alert-{$rawObject->getInternalAlertMessageType()} alert--faded datatable-alert-top" style="margin-top:0px; margin-bottom: 10px !important;">
+    <div class="alert__body">
+        {if $rawObject->isInternalAlertMessageRaw()|unescape:'html'}{$rawObject->getInternalAlertMessage()}{else}{$MGLANG->T($rawObject->getInternalAlertMessage())|unescape:'html'}{/if}
+    </div>
+</div>

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

@@ -64,12 +64,6 @@ class CreateForm extends BaseForm implements ClientArea
     {
     {
         //compress
         //compress
         $field = new Select('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');
         $field->setDefaultValue('zstd');
         $this->addField($field);
         $this->addField($field);
         //mode
         //mode

+ 1 - 1
app/UI/Backup/Forms/DeleteForm.php

@@ -52,7 +52,7 @@ class BackupDataTable extends DataTable implements ClientArea
         $createButton->addClass("pmCreateBackupButton");
         $createButton->addClass("pmCreateBackupButton");
         if (!$this->resourceGuard()->hasBackupLimit())
         if (!$this->resourceGuard()->hasBackupLimit())
         {
         {
-            $createButton->addClass("hidden");
+            $createButton->addClass("disabled");
         }
         }
         $this->unsetShowTitle();
         $this->unsetShowTitle();
         if ($this->configuration()->isPermissionBackup())
         if ($this->configuration()->isPermissionBackup())

+ 37 - 5
app/UI/Backup/Providers/BackupProvider.php

@@ -28,6 +28,7 @@ use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
 use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
 use function ModulesGarden\ProxmoxAddon\Core\Helper\queue;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
 
 
 class BackupProvider extends BaseDataProvider implements ClientArea
 class BackupProvider extends BaseDataProvider implements ClientArea
 {
 {
@@ -40,6 +41,25 @@ class BackupProvider extends BaseDataProvider implements ClientArea
         {
         {
             $this->data = json_decode(base64_decode($this->actionElementId), true);
             $this->data = json_decode(base64_decode($this->actionElementId), true);
         }
         }
+        $this->availableValues['compress'] = [
+            "0"    => sl("lang")->abtr("None"),
+            "lzo"  => sl("lang")->abtr("LZO (fast)"),
+            "gzip" => sl("lang")->abtr("GZIP (good)"),
+            "zstd" => sl("lang")->abtr("ZSTD (fast and good)")
+        ];
+        $optionBackupCompress = $this->configuration()->getPermissionBackupCompress();
+        if(empty($optionBackupCompress)){
+            return;
+        }
+        foreach ($this->availableValues['compress'] as $k => $option){
+            if($k=="0" && !in_array("none", $optionBackupCompress)){
+                unset($this->availableValues['compress'][$k]);
+            }
+            if(!in_array($k, $optionBackupCompress)){
+                unset($this->availableValues['compress'][$k]);
+            }
+        }
+
     }
     }
 
 
     public function create()
     public function create()
@@ -51,16 +71,23 @@ class BackupProvider extends BaseDataProvider implements ClientArea
         $maxFiles       =  $this->configuration()->getBackupMaxFiles();
         $maxFiles       =  $this->configuration()->getBackupMaxFiles();
         if($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) &&  $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)!="-1"){
         if($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) &&  $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)!="-1"){
             $maxFiles       = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
             $maxFiles       = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
-        }else if($this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)=="-1"){
+        }else if($this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES, $this->configuration()->getBackupMaxFiles())=="-1"){
             $maxFiles       = null;
             $maxFiles       = null;
         }
         }
         $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
         $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        if($vm->isLockBackup()){
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('The backup creation is in progress');
+        }
         $vm ->backup($storage, $routing, $maxFiles, $this->formData['compress'], $this->formData['mode']);
         $vm ->backup($storage, $routing, $maxFiles, $this->formData['compress'], $this->formData['mode']);
         return (new HtmlDataJsonResponse())
         return (new HtmlDataJsonResponse())
             ->setStatusSuccess()
             ->setStatusSuccess()
             ->setMessageAndTranslate('The backup creation is in progress')
             ->setMessageAndTranslate('The backup creation is in progress')
             ->addData('createButtonStatus', $this->configuration()->isPermissionBackup() && $this->resourceGuard()->hasBackupLimit())
             ->addData('createButtonStatus', $this->configuration()->isPermissionBackup() && $this->resourceGuard()->hasBackupLimit())
-            ->setCallBackFunction('pmToggleBackupButton');
+            ->setCallBackFunction('pmToggleBackupButton')
+            ->addRefreshTargetId('resourcesContainer')
+            ->addRefreshTargetId('backupDataTable');
     }
     }
 
 
     public function restore()
     public function restore()
@@ -92,7 +119,10 @@ class BackupProvider extends BaseDataProvider implements ClientArea
             ->setStatusSuccess()
             ->setStatusSuccess()
             ->setMessageAndTranslate('The backup has been deleted successfully')
             ->setMessageAndTranslate('The backup has been deleted successfully')
             ->addData('createButtonStatus', $this->configuration()->isPermissionBackup() && $this->resourceGuard()->hasBackupLimit())
             ->addData('createButtonStatus', $this->configuration()->isPermissionBackup() && $this->resourceGuard()->hasBackupLimit())
-            ->setCallBackFunction('pmToggleBackupButton');
+            ->setCallBackFunction('pmToggleBackupButton')
+            ->addRefreshTargetId('resourcesContainer')
+            ->addRefreshTargetId('backupDataTable');
+
     }
     }
 
 
     public function deleteMass()
     public function deleteMass()
@@ -113,7 +143,9 @@ class BackupProvider extends BaseDataProvider implements ClientArea
             ->setStatusSuccess()
             ->setStatusSuccess()
             ->setMessageAndTranslate('The backups have been deleted successfully')
             ->setMessageAndTranslate('The backups have been deleted successfully')
             ->addData('createButtonStatus', $this->configuration()->isPermissionBackup() && $this->resourceGuard()->hasBackupLimit())
             ->addData('createButtonStatus', $this->configuration()->isPermissionBackup() && $this->resourceGuard()->hasBackupLimit())
-            ->setCallBackFunction('pmToggleBackupButton');
+            ->setCallBackFunction('pmToggleBackupButton')
+            ->addRefreshTargetId('resourcesContainer')
+            ->addRefreshTargetId('backupDataTable');
     }
     }
 
 
-}
+}

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

@@ -94,12 +94,6 @@ class CreateForm extends BaseForm implements ClientArea
         $this->addField($field);
         $this->addField($field);
         //compress
         //compress
         $field = new Select('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->setDefaultValue('zstd');
         $field->notEmpty();
         $field->notEmpty();
         $this->addField($field);
         $this->addField($field);

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

@@ -98,12 +98,6 @@ class UpdateForm extends BaseForm implements ClientArea
         $this->addField($field);
         $this->addField($field);
         //compress
         //compress
         $field = new Select('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->setDefaultValue('zstd');
         $field->notEmpty();
         $field->notEmpty();
         $this->addField($field);
         $this->addField($field);

+ 22 - 3
app/UI/BackupJob/Modals/CreateModal.php

@@ -26,6 +26,7 @@ use ModulesGarden\ProxmoxAddon\App\Enum\Cloud\ConfigurableOption;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseDataProvider;
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
 
 
 class BackupJobProvider extends BaseDataProvider implements ClientArea
 class BackupJobProvider extends BaseDataProvider implements ClientArea
 {
 {
@@ -44,6 +45,24 @@ class BackupJobProvider extends BaseDataProvider implements ClientArea
             $mailto               = $this->data['mailto'];
             $mailto               = $this->data['mailto'];
             $this->data['mailto'] = $mailto ? "on" : "off";
             $this->data['mailto'] = $mailto ? "on" : "off";
         }
         }
+        $this->availableValues['compress'] = [
+            "0"    => sl("lang")->abtr("None"),
+            "lzo"  => sl("lang")->abtr("LZO (fast)"),
+            "gzip" => sl("lang")->abtr("GZIP (good)"),
+            "zstd" => sl("lang")->abtr("ZSTD (fast and good)")
+        ];
+        $optionBackupCompress = $this->configuration()->getPermissionBackupCompress();
+        if(empty($optionBackupCompress)){
+            return;
+        }
+        foreach ($this->availableValues['compress'] as $k => $option){
+            if($k=="0" && !in_array("none", $optionBackupCompress)){
+                unset($this->availableValues['compress'][$k]);
+            }
+            if(!in_array($k, $optionBackupCompress)){
+                unset($this->availableValues['compress'][$k]);
+            }
+        }
     }
     }
 
 
     public function create()
     public function create()
@@ -56,7 +75,7 @@ class BackupJobProvider extends BaseDataProvider implements ClientArea
 
 
         if($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) &&  $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)!="-1"){
         if($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) &&  $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)!="-1"){
             $maxFiles       = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
             $maxFiles       = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
-        }else if($this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)=="-1"){
+        }else if($this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES, $this->configuration()->getBackupMaxFiles())=="-1"){
             $maxFiles       = null;
             $maxFiles       = null;
         }
         }
         $backupSchedule = new BackupSchedule();
         $backupSchedule = new BackupSchedule();
@@ -90,7 +109,7 @@ class BackupJobProvider extends BaseDataProvider implements ClientArea
         $maxFiles       =  $this->configuration()->getBackupMaxFiles();
         $maxFiles       =  $this->configuration()->getBackupMaxFiles();
         if($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) &&  $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)!="-1"){
         if($this->isWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES) &&  $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)!="-1"){
             $maxFiles       = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
             $maxFiles       = $this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES);
-        }else if($this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES)=="-1"){
+        }else if($this->getWhmcsConfigOption(ConfigurableOption::BACKUPS_FILES, $this->configuration()->getBackupMaxFiles())=="-1"){
             $maxFiles       = null;
             $maxFiles       = null;
         }
         }
         $backupSchedule = new BackupSchedule();
         $backupSchedule = new BackupSchedule();
@@ -130,4 +149,4 @@ class BackupJobProvider extends BaseDataProvider implements ClientArea
     }
     }
 
 
 
 
-}
+}

+ 5 - 1
app/UI/Client/Templates/assets/css/integration.css

@@ -154,4 +154,8 @@ input[type=range]:focus::-ms-fill-upper {
 
 
 .vm-actions .lu-btn{
 .vm-actions .lu-btn{
     width: 23%;
     width: 23%;
-}
+}
+
+#layers #resourcesContainer .lu-progress--h .lu-progress__label {
+    flex-basis: 24% !important;
+}

+ 45 - 2
app/UI/Client/Templates/assets/img/buttons/backup.png


+ 1 - 1
app/UI/CustomTemplate/Buttons/CreateButton.php

@@ -123,7 +123,7 @@ class DiskProvider extends BaseDataProvider implements ClientArea
         }
         }
         if($hdd->isMaster()){
         if($hdd->isMaster()){
             $vm->config(true);
             $vm->config(true);
-            $vmModel->disk =  $vm->getMasterHddSize();
+            $vmModel->disk =  $vm->getHardDiskRepostiory()->findById($hdd->getId())->getGb();
         }else{
         }else{
             $vmModel->disks = $vm->getHardDiskRepostiory()->additionalSize();
             $vmModel->disks = $vm->getHardDiskRepostiory()->additionalSize();
         }
         }

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

@@ -1,21 +1,4 @@
 <?php
 <?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;
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons;
 
 

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

@@ -0,0 +1,47 @@
+<?php
+
+
+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\Vps\ProductService;
+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\ResponseTemplates\DataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class DownRuleButton extends ButtonDataTableModalAction implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+    protected $icon           = 'lu-btn__icon lu-zmdi lu-zmdi-long-arrow-down';
+
+    public function initContent()
+    {
+        $this->initIds('downRuleButton');
+        $this->htmlAttributes['@click'] = 'buttonAction($event, \'' . $this->id . '\')';
+    }
+
+    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->moveto( $pos+2);
+        }
+        catch (\Exception $exc)
+        {
+            return (new DataJsonResponse())->setStatusError()->setMessage($exc->getMessage())->setCallBackFunction($this->callBackFunction)->addRefreshTargetId($this->refreshActionIds);
+        }
+        return (new DataJsonResponse())->setMessageAndTranslate('changesSaved')->addRefreshTargetId('firewallDataTable');
+    }
+
+
+}

+ 47 - 0
app/UI/Firewall/Buttons/DownloadButton.php

@@ -0,0 +1,47 @@
+<?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\Helpers\UrlServiceHelper;
+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\ButtonCreate;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonRedirect;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\DropdawnButtonWrappers\ButtonDropdownItem;
+
+
+class DownloadButton extends ButtonRedirect  implements ClientArea
+{
+    protected $id='downloadButton';
+    protected $name ='downloadButton';
+    protected $title='downloadButton';
+    protected $icon  = 'lu-dropdown__link-icon lu-zmdi  lu-zmdi-download';
+    protected $class          = ['lu-dropdown__link'];
+    protected $showTitle = true;
+
+    public function initContent()
+    {
+        $this->initIds('downloadButton');
+        $url = (new UrlServiceHelper())->getDownloadFirewallRulesUrl();
+        $this->setRawUrl($url);
+    }
+
+
+}

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

@@ -0,0 +1,22 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals\CreateGroupModal;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals\RestoreModal;
+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\DropdawnButtonWrappers\ButtonDropdownItem;
+
+
+class RestoreButton extends ButtonDropdownItem  implements ClientArea
+{
+    protected $id = 'restoreButton';
+    protected $icon  = 'lu-dropdown__link-icon lu-zmdi  lu-zmdi-time-restore';
+
+    public function initContent()
+    {
+        $this->initIds('restoreButton');
+        $this->initLoadModalAction(new RestoreModal());
+    }
+}

+ 50 - 0
app/UI/Firewall/Buttons/UpRuleButton.php

@@ -0,0 +1,50 @@
+<?php
+
+
+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\Vps\ProductService;
+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\ResponseTemplates\DataJsonResponse;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Buttons\ButtonDataTableModalAction;
+
+class UpRuleButton extends ButtonDataTableModalAction implements ClientArea
+{
+    use ProductService;
+    use ApiService;
+    protected $icon           = 'lu-btn__icon lu-zmdi lu-zmdi-long-arrow-up';//zmdi-long-arrow-down
+
+    public function initContent()
+    {
+        $this->initIds('upRuleButton');
+        $this->htmlAttributes['@click'] = 'buttonAction($event, \'' . $this->id . '\')';
+    }
+
+    public function returnAjaxData()
+    {
+        try
+        {
+            $data         = json_decode(base64_decode($this->getRequestValue('actionElementId')), true);
+            $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+            if($data['pos']==0){
+                return (new DataJsonResponse())->setMessageAndTranslate('changesSaved')->setCallBackFunction($this->callBackFunction)->addRefreshTargetId($this->refreshActionIds);
+            }
+            $firewallRule = new FirewallRule();
+            $firewallRule->setApi($this->api());
+            $pos = $data['pos'];
+            $firewallRule->setPath($vm->getPath() . "/firewall/rules/{$pos}");
+            $firewallRule->moveto( $pos-1);
+        }
+        catch (\Exception $exc)
+        {
+            return (new DataJsonResponse())->setStatusError()->setMessage($exc->getMessage())->setCallBackFunction($this->callBackFunction)->addRefreshTargetId($this->refreshActionIds);
+        }
+        return (new DataJsonResponse())->setMessageAndTranslate('changesSaved')->addRefreshTargetId('firewallDataTable');
+    }
+
+
+}

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

@@ -0,0 +1,60 @@
+<?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;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\BaseForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\FileField;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Hidden;
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Text;
+
+class RestoreForm extends BaseForm implements ClientArea
+{
+    use ApiService;
+
+    public function initContent()
+    {
+        $this->initIds('restoreForm');
+        $this->setFormType('restore');
+        $this->setProvider(new FirewallProvider());
+        $this->initFields();
+        $this->loadDataToForm();
+    }
+
+    public function getAllowedActions()
+    {
+        return ['restore'];
+    }
+
+    protected function initFields(){
+        //rules
+        $field = new FileField('rules');
+        $field->setId('pmFirewallRules');
+        $this->addField($field);
+        //rules
+        $field = new Hidden('rulesJson');
+        $field->addHtmlAttribute('id','pmRulesJson');
+        $this->addField($field);
+
+    }
+
+}

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

@@ -0,0 +1,20 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Modals;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms\CreateGroupForm;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Forms\RestoreForm;
+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\ModalConfirmSuccess;
+
+class RestoreModal extends BaseEditModal implements ClientArea
+{
+
+    public function initContent()
+    {
+        $this->initIds('restoreModal');
+        $this->addForm(new RestoreForm());
+    }
+
+}

+ 14 - 1
app/UI/Firewall/Modals/UpdateGroupModal.php

@@ -26,9 +26,12 @@ use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\CreateGroupBut
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\CreateRuleButton;
 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\DeleteButton;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\DeleteMassButton;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\DeleteMassButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\DownloadButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\DownRuleButton;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\EnableSwitchButton;
 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\RestoreButton;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\UpdateRuleButton;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\UpdateRuleButton;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Firewall\Buttons\UpRuleButton;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 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\Column;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\DataTable\DataProviders\Providers\ArrayDataProvider;
@@ -58,6 +61,15 @@ class FirewallDataTable extends DataTable implements ClientArea
         }
         }
         $this->addButton($createRule);
         $this->addButton($createRule);
         $this->addButton($createGroup);
         $this->addButton($createGroup);
+        //download rules
+        $this->addButton(new DownloadButton());
+        //restore rules
+        $this->addButton(new RestoreButton());
+        //up
+        $this->addActionButton(new UpRuleButton());
+        //down
+        $this->addActionButton(new DownRuleButton());
+
         //Update
         //Update
         $this->addActionButton(new UpdateRuleButton());
         $this->addActionButton(new UpdateRuleButton());
         //Delete
         //Delete
@@ -66,7 +78,8 @@ class FirewallDataTable extends DataTable implements ClientArea
 
 
     protected function loadHtml()
     protected function loadHtml()
     {
     {
-        $this->addColumn((new Column('enable')))
+        $this->addColumn((new Column('pos'))->setSearchable(true, "string")->setOrderable())
+            ->addColumn((new Column('enable')))
             ->addColumn((new Column('type'))->setSearchable(true, "string")->setOrderable())
             ->addColumn((new Column('type'))->setSearchable(true, "string")->setOrderable())
             ->addColumn((new Column('action'))->setSearchable(true, "string")->setOrderable())
             ->addColumn((new Column('action'))->setSearchable(true, "string")->setOrderable())
             ->addColumn((new Column('iface'))->setSearchable(true, "string")->setOrderable())
             ->addColumn((new Column('iface'))->setSearchable(true, "string")->setOrderable())

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

@@ -104,5 +104,28 @@ class FirewallProvider extends BaseDataProvider implements ClientArea
             ->setCallBackFunction('pmToggleFirewallButton');
             ->setCallBackFunction('pmToggleFirewallButton');
     }
     }
 
 
+    public function restore(){
+        $rules = \json_decode(html_entity_decode($this->getFormDataValues()['rulesJson'],ENT_QUOTES),true);
+        if(!$this->getFormDataValues()['rulesJson'] || !$rules ){
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('The file with firewall rules is empty or invalid');
+        }
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        $this->acl()->firewall();
+        $this->resourceGuard()->firewallLimit(count($rules));
+        foreach ($rules as $rule){
+            $firewallRule = new FirewallRule();
+            $firewallRule->setApi($this->api());
+            $firewallRule->setPath($vm->getPath() . "/firewall/rules/");
+            $firewallRule->setAttributes($rule);
+            $firewallRule->create();
+        }
+        return (new HtmlDataJsonResponse())
+            ->setStatusSuccess()
+            ->setMessageAndTranslate('The firewall rules have been restored successfully')
+            ->addData('createButtonStatus', $this->resourceGuard()->hasfirewallLimit())
+            ->setCallBackFunction('pmToggleButton');
+    }
 
 
 }
 }

+ 20 - 16
app/UI/FirewallOption/Buttons/UpdateButton.php

@@ -100,22 +100,26 @@ class UpdateForm extends BaseForm implements ClientArea
         $field->setAvailableValues($logLevels);
         $field->setAvailableValues($logLevels);
         $this->addField($field);
         $this->addField($field);
         //policy_in
         //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);
+        if($this->acl()->hasFirewallOption("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
         //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);
+        if($this->acl()->hasFirewallOption("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);
+        }
     }
     }
 }
 }

+ 1 - 1
app/UI/FirewallOption/Modals/UpdateModal.php

@@ -54,7 +54,7 @@ class FirewallOption extends BaseContainer implements ClientArea, AjaxElementInt
     {
     {
         $vars = ['entries' => []];
         $vars = ['entries' => []];
         $lang = sl("lang");
         $lang = sl("lang");
-        $allowed = ['log_level_in', 'log_level_out', 'policy_in', 'policy_out'];
+        $allowed = ['log_level_in', 'log_level_out'];
         $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
         $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
         foreach ($vm->firewallOptions()->read()->toArray() as $key => $value)
         foreach ($vm->firewallOptions()->read()->toArray() as $key => $value)
         {
         {

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

@@ -28,6 +28,7 @@ use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\IpSetIpFilterService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\IpSetIpFilterService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\IpLogService;
 use ModulesGarden\ProxmoxAddon\App\Services\Utility;
 use ModulesGarden\ProxmoxAddon\App\Services\Utility;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
@@ -87,6 +88,7 @@ class IpAddressProvider extends BaseDataProvider implements ClientArea
     {
     {
         try {
         try {
             $this->api();
             $this->api();
+            $ipunassigned = [];
             DB::beginTransaction();
             DB::beginTransaction();
             Api::beginTransaction();
             Api::beginTransaction();
             //delete ip
             //delete ip
@@ -115,10 +117,15 @@ class IpAddressProvider extends BaseDataProvider implements ClientArea
                 ->delete();
                 ->delete();
             //delete in hosting
             //delete in hosting
             $ip->hosting->ipDelete($ip->ip);
             $ip->hosting->ipDelete($ip->ip);
+            $ipunassigned[] = $ip->ip;
             if ($this->configuration()->isIpsetIpFilter() && $vm)
             if ($this->configuration()->isIpsetIpFilter() && $vm)
             {
             {
                 $this->ipSetIpFilterService->create();
                 $this->ipSetIpFilterService->create();
             }
             }
+            $ip->hosting->save();
+            if(!empty( $ipunassigned)){
+                (new IpLogService())->unassigned($ipunassigned);
+            }
             DB::commit();
             DB::commit();
             Api::commit();
             Api::commit();
             return (new HtmlDataJsonResponse())
             return (new HtmlDataJsonResponse())

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

@@ -21,6 +21,7 @@ namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Providers;
 
 
 
 
 use MGProvision\Proxmox\v2\models\Kvm;
 use MGProvision\Proxmox\v2\models\Kvm;
+use MGProvision\Proxmox\v2\repository\FirewallRulesRepository;
 use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Reinstall\BackupVmJob;
 use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Reinstall\BackupVmJob;
 use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Reinstall\CreateVmJob;
 use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Reinstall\CreateVmJob;
 use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Reinstall\DeleteVmJob;
 use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\Reinstall\DeleteVmJob;
@@ -64,10 +65,14 @@ class TemplateInstallProvider extends BaseDataProvider implements ClientArea, Ad
                 ->setStatusError()
                 ->setStatusError()
                 ->setMessageAndTranslate("Task 'Reinstall' already exist");
                 ->setMessageAndTranslate("Task 'Reinstall' already exist");
         }
         }
+        $firewalRules = new FirewallRulesRepository();
+        $firewalRules->setApi($this->api());
+        $firewalRules->findByVmModel( \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel());
         $arguments = [
         $arguments = [
             'hostingId'  => $this->getWhmcsParamByKey('serviceid'),
             'hostingId'  => $this->getWhmcsParamByKey('serviceid'),
             "osTemplate" => $this->formData['id'],
             "osTemplate" => $this->formData['id'],
             "password"   => encrypt(html_entity_decode($this->formData['password'],ENT_QUOTES)),
             "password"   => encrypt(html_entity_decode($this->formData['password'],ENT_QUOTES)),
+            "firewallRules" => $firewalRules->fetchAsArray()
         ];
         ];
         \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->data['osTemplate'] =   $this->formData['id'];
         \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->data['osTemplate'] =   $this->formData['id'];
         \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->save();
         \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->save();
@@ -116,10 +121,14 @@ class TemplateInstallProvider extends BaseDataProvider implements ClientArea, Ad
         }
         }
         \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->data['osTemplate'] =  $vmTemplate->status()['name'];
         \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->data['osTemplate'] =  $vmTemplate->status()['name'];
         \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->save();
         \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->save();
+        $firewalRules = new FirewallRulesRepository();
+        $firewalRules->setApi($this->api());
+        $firewalRules->findByVmModel( \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel());
         $arguments = [
         $arguments = [
             'hostingId'  => $this->getWhmcsParamByKey('serviceid'),
             'hostingId'  => $this->getWhmcsParamByKey('serviceid'),
             "osTemplate" => $this->formData['id'],
             "osTemplate" => $this->formData['id'],
             "password"   => encrypt(html_entity_decode($this->formData['password'],ENT_QUOTES)),
             "password"   => encrypt(html_entity_decode($this->formData['password'],ENT_QUOTES)),
+            "firewallRules" => $firewalRules->fetchAsArray()
         ];
         ];
         //automaticaly configure administartor username for window
         //automaticaly configure administartor username for window
         $this->setHostingId($this->getWhmcsParamByKey('serviceid'));
         $this->setHostingId($this->getWhmcsParamByKey('serviceid'));

+ 37 - 0
app/UI/Resources/Pages/ResourcesContainer.php

@@ -0,0 +1,37 @@
+<?php
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Resources\Pages;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Resources\Providers\BackupResourceProvider;
+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;
+
+class ResourcesContainer extends BaseContainer implements ClientArea, AjaxElementInterface
+{
+    protected $id = 'resourcesContainer';
+    protected $name = 'resourcesContainer';
+    protected $title = 'resourcesContainer';
+    protected $vueComponent = true;
+    protected $defaultVueComponentName = 'mg-resourcesContainer';
+
+    public function isShowTitle()
+    {
+        return false;
+    }
+    public function initContent()
+    {
+        $this->provider = new BackupResourceProvider();
+    }
+
+    public function prepareAjaxData()
+    {
+
+        return $this->provider->read();
+    }
+
+    public function returnAjaxData()
+    {
+        return new RawDataJsonResponse(['data' => $this->prepareAjaxData()]);
+    }
+}

+ 39 - 0
app/UI/Resources/Providers/BackupResourceProvider.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Resources\Providers;
+
+use ModulesGarden\ProxmoxAddon\App\Libs\Format;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
+
+use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
+
+class BackupResourceProvider
+{
+
+    public function read()
+    {
+        $resourceManager = new ResourceManager();
+        $lang = sl('lang');
+        $bs = $resourceManager->backupSize();
+        $resurces = [];
+        if(!$bs->isUnlimited() ){
+            $resurces[  ] = [
+                "name" => $lang->tr($bs->getName()),
+                "used" => Format::convertBytes($bs->getUsed()),
+                "total" => $bs->isUnlimited() ? $lang->abtr("Unlimited") : Format::convertBytes($bs->getTotal()),
+                "unit" => "",
+                "percent" => $bs->getPercent()
+            ];
+        }
+        if(!$resourceManager->backupFiles()->isUnlimited()){
+            $resurces[ ] = [
+                "name" => $lang->tr($resourceManager->backupFiles()->getName() ),
+                "used" => $resourceManager->backupFiles()->getUsed(),
+                "total" =>  $resourceManager->backupFiles()->isUnlimited() ? $lang->abtr("Unlimited") : $resourceManager->backupFiles()->getTotal(),
+                "unit" => "",
+                "percent" => $resourceManager->backupFiles()->getPercent()
+            ];
+        }
+        return $resurces;
+    }
+}

+ 5 - 0
app/UI/Resources/Templates/pages/resourcesContainer.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}>

+ 58 - 0
app/UI/Resources/Templates/pages/resourcesContainer_components.js

@@ -0,0 +1,58 @@
+mgJsComponentHandler.addDefaultComponent('mg-resourcesContainer', {
+    template: '#t-mg-resourcesContainer',
+    props: [
+        'component_id',
+        'component_namespace',
+        'component_index'
+    ],
+    data: function () {
+        return {
+            data: {
+            },
+            loading_state: false,
+            passwordShow: false,
+
+        };
+    },
+    created: function () {
+        var self = this;
+        self.$nextTick(function () {
+            self.loadAjaxData();
+        });
+        self.$parent.$root.$on('reloadMgData', this.updateMgData);
+    },
+    methods: {
+        loadAjaxData: function () {
+            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();
+            }
+        },
+        widthPercent: function(percent){
+            return 'width: '+percent+ '%';
+        }
+    }
+});

+ 39 - 0
app/UI/Resources/Templates/pages/resourcesContainer_components.tpl

@@ -0,0 +1,39 @@
+<script type="text/x-template" id="t-mg-resourcesContainer-{$elementId|strtolower}"
+        :component_id="component_id"
+        :component_namespace="component_namespace"
+        :component_index="component_index"
+>
+    <div class="lu-row">
+
+    <div class="lu-col-md-12" id="{$rawObject->getId()}" namespace="{$namespace}"
+         index="{$rawObject->getIndex()}" actionid="{$rawObject->getIndex()}">
+        <div class="lu-widget">
+            {if   $rawObject->isShowTitle()}
+            <div class="lu-widget__header">
+                <div class="lu-widget__top lu-top">
+                    <div class="lu-top__title">
+                        <span>{$MGLANG->absoluteT('serverCA' ,'availableResources')}</span>
+                    </div>
+                </div>
+            </div>
+            {/if}
+            <div class="lu-widget__body">
+                <div class="lu-widget__content">
+                    <div class="lu-progress lu-progress--h lu-progress--s lu-progress__label" v-for="(bar, key) in data">
+                        <div class="lu-progress__label">
+                            {{ bar.name }} {{ bar.used }} / {{ bar.total }} <span v-if="bar.unit"> {{ bar.unit }}  </span>
+                        </div>
+                        <div class="lu-progress__bar progress-bar-danger">
+                            <div class="lu-progress__fill"  :style=widthPercent(bar.percent)></div>
+                        </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>

+ 2 - 1
app/UI/ServiceGraph/Pages/BaseGraph.php

@@ -118,7 +118,8 @@ class JobRawDataTable extends RawDataTable implements ClientArea, AdminArea
             ->query()
             ->query()
             ->getQuery()
             ->getQuery()
             ->select('id','name','description','vmstate','period', 'run_every','days','start_time','updated_at','created_at')
             ->select('id','name','description','vmstate','period', 'run_every','days','start_time','updated_at','created_at')
-            ->where("hosting_id", $this->getWhmcsParamByKey('serviceid'));
+            ->where("hosting_id", $this->getWhmcsParamByKey('serviceid'))
+            ->where("vm_id", \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id);
         $dataProv = new QueryDataProvider();
         $dataProv = new QueryDataProvider();
         $dataProv->setData($query);
         $dataProv->setData($query);
         $dataProv->setDefaultSorting("created_at", 'DESC');
         $dataProv->setDefaultSorting("created_at", 'DESC');

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

@@ -28,10 +28,12 @@ class SnapshotTab extends TabsWidget implements ClientArea, AdminArea
 {
 {
     protected $id = 'snapshotTab';
     protected $id = 'snapshotTab';
     protected $name = 'snapshotTab';
     protected $name = 'snapshotTab';
+    protected $title = 'snapshotTabTitle';
     protected $vueComponent = true;
     protected $vueComponent = true;
 
 
     public function initContent()
     public function initContent()
     {
     {
+        $this->unsetShowTitle();
         $this->addElement(new SnapshotRawDataTable());
         $this->addElement(new SnapshotRawDataTable());
         $this->addElement(new JobRawDataTable());
         $this->addElement(new JobRawDataTable());
 
 

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

@@ -29,6 +29,7 @@ trait SnapshotTrait
 
 
     public function initContent()
     public function initContent()
     {
     {
+
         //Create
         //Create
         $createButton = new CreateButton();
         $createButton = new CreateButton();
         $createButton->addClass("pmCreateSnapshotButton");
         $createButton->addClass("pmCreateSnapshotButton");

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

@@ -71,6 +71,7 @@ class JobProvider  extends BaseModelDataProvider implements ClientArea
 
 
     public function create()
     public function create()
     {
     {
+        $this->resourceGuard()->snapshotJobLimit();
         //vmstate
         //vmstate
         if(isset($this->formData['vmstate'])){
         if(isset($this->formData['vmstate'])){
             $vmstate = $this->formData['vmstate']=="on" ? 1:0;
             $vmstate = $this->formData['vmstate']=="on" ? 1:0;
@@ -78,6 +79,8 @@ class JobProvider  extends BaseModelDataProvider implements ClientArea
         }
         }
         //hosting_id
         //hosting_id
         $this->formData['hosting_id']= $this->getWhmcsParamByKey('serviceid');
         $this->formData['hosting_id']= $this->getWhmcsParamByKey('serviceid');
+        //vm_id
+        $this->formData['vm_id']= \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id;
         //fill from data
         //fill from data
         $this->model->fill($this->formData)->save();
         $this->model->fill($this->formData)->save();
         sl('lang')->addReplacementConstant('name', $this->formData['name']);
         sl('lang')->addReplacementConstant('name', $this->formData['name']);
@@ -112,6 +115,7 @@ class JobProvider  extends BaseModelDataProvider implements ClientArea
 
 
     public function delete()
     public function delete()
     {
     {
+
         parent::delete();
         parent::delete();
         sl('lang')->addReplacementConstant('name', $this->formData['name']);
         sl('lang')->addReplacementConstant('name', $this->formData['name']);
         return (new HtmlDataJsonResponse())->setMessageAndTranslate('Snapshot Job :name: has been deleted successfully')
         return (new HtmlDataJsonResponse())->setMessageAndTranslate('Snapshot Job :name: has been deleted successfully')

+ 20 - 8
app/UI/Snapshot/Providers/SnapshotProvider.php

@@ -4,6 +4,8 @@ namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Fields;
 
 
 use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
 use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
 use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
 use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
+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\Ip\Ipv4Range;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\AjaxFields\Select;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\AjaxFields\Select;
@@ -11,24 +13,34 @@ use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
 
 
 class NetworkSelect extends Select implements ClientArea
 class NetworkSelect extends Select implements ClientArea
 {
 {
+    use ProductService;
+
     protected $id   = 'networkSelect';
     protected $id   = 'networkSelect';
     protected $name = 'network';
     protected $name = 'network';
 
 
     public function prepareAjaxData()
     public function prepareAjaxData()
     {
     {
         session_write_close();
         session_write_close();
-        $this->availableValues[]    = [
-            'key' => 'public',
-            'value' => sl('lang')->abtr('Public')
-        ];
-        foreach (VirtualNetwork::ofHostingId($this->getWhmcsParamByKey('serviceid'))->select('id', 'name')->get() as $vn)
-        {
+        if($this->configuration()->isOrderPublicIp()){
             $this->availableValues[]    = [
             $this->availableValues[]    = [
-                'key' => $vn->id,
-                'value' => $vn->name
+                'key' => 'public',
+                'value' => sl('lang')->abtr('Public')
             ];
             ];
         }
         }
 
 
+        $resurceManager = new ResourceManager();
+        $resurceManager->vmIds([\ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id]);
+        if(!$resurceManager->virtualInterfaces()->getMax() ||  $resurceManager->virtualInterfaces()->free()){
+            foreach (VirtualNetwork::ofHostingId($this->getWhmcsParamByKey('serviceid'))->select('id', 'name')->get() as $vn)
+            {
+                $this->availableValues[]    = [
+                    'key' => $vn->id,
+                    'value' => $vn->name
+                ];
+            }
+        }
+
+
         if($this->availableValues)
         if($this->availableValues)
         {
         {
             $this->value    = $this->availableValues[0]['key'];
             $this->value    = $this->availableValues[0]['key'];

+ 46 - 5
app/UI/VirtualInterface/Forms/CreateForm.php

@@ -21,6 +21,8 @@ namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Provider
 
 
 use MGProvision\Proxmox\v2\Api;
 use MGProvision\Proxmox\v2\Api;
 use MGProvision\Proxmox\v2\models\Kvm;
 use MGProvision\Proxmox\v2\models\Kvm;
+use MGProvision\Proxmox\v2\models\Lxc;
+use MGProvision\Proxmox\v2\models\NetworkDeviceLxc;
 use MGProvision\Proxmox\v2\ProxmoxApiException;
 use MGProvision\Proxmox\v2\ProxmoxApiException;
 use ModulesGarden\ProxmoxAddon\App\Models\VirtualInterface;
 use ModulesGarden\ProxmoxAddon\App\Models\VirtualInterface;
 use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
 use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
@@ -29,6 +31,7 @@ use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\IpSetIpFilterService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\IpSetIpFilterService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\VirtualInterfaceConverter;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\VirtualInterfaceConverter;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
@@ -58,9 +61,15 @@ class VirtualInterfaceProvider extends BaseModelDataProvider implements ClientAr
     public function read()
     public function read()
     {
     {
         $this->availableValues['vn_id']['public'] = sl('lang')->abtr('Public');
         $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;
+        $resurceManager = new ResourceManager();
+        $resurceManager->vmIds([\ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel()->id]);
+
+        if(!$resurceManager->virtualInterfaces()->getMax() ||  $resurceManager->virtualInterfaces()->free()){
+            foreach (VirtualNetwork::ofHostingId($this->getWhmcsParamByKey('serviceid'))->select('id', 'name')->get() as $vn) {
+                $this->availableValues['vn_id'][$vn->id] = $vn->name;
+            }
         }
         }
+
         if ($this->getActionElementIdValue()) {
         if ($this->getActionElementIdValue()) {
             $this->data['id'] = $this->getActionElementIdValue();
             $this->data['id'] = $this->getActionElementIdValue();
         }
         }
@@ -93,8 +102,14 @@ class VirtualInterfaceProvider extends BaseModelDataProvider implements ClientAr
                     $cloudInitDrive = $cdrom->getCloudInitDrive();
                     $cloudInitDrive = $cdrom->getCloudInitDrive();
                 }
                 }
                 try {
                 try {
-                    $vm->updateConfig($conveter->getNetworkDevicesAsConfig());
-                    $vm->updateConfig($conveter->getIpConfigsAsConfig());
+                    $networkDevices = $conveter->getNetworkDevicesAsConfig();
+                    $ipConfig = $conveter->getIpConfigsAsConfig();
+                    if(!empty($networkDevices)){
+                        $vm->updateConfig($networkDevices);
+                    }
+                    if(!empty($ipConfig)){
+                        $vm->updateConfig($ipConfig);
+                    }
                     //Regenerate image
                     //Regenerate image
                     if($cloudInitDrive ){
                     if($cloudInitDrive ){
                         $cloudInitDrive->unmount();
                         $cloudInitDrive->unmount();
@@ -114,7 +129,10 @@ class VirtualInterfaceProvider extends BaseModelDataProvider implements ClientAr
                 }
                 }
             }else{
             }else{
                 //Update container
                 //Update container
-                $vm->updateConfig($conveter->asConfig());
+                $config = $conveter->asConfig();
+                if(!empty($config)){
+                    $vm->updateConfig($config);
+                }
             }
             }
             DB::commit();
             DB::commit();
             if ($this->configuration()->isIpsetIpFilter()){
             if ($this->configuration()->isIpsetIpFilter()){
@@ -146,6 +164,12 @@ class VirtualInterfaceProvider extends BaseModelDataProvider implements ClientAr
         $vi = $this->model->where('id', $this->getFormDataValues()['id'])
         $vi = $this->model->where('id', $this->getFormDataValues()['id'])
             ->ofHostingId($this->getWhmcsParamByKey('serviceid'))
             ->ofHostingId($this->getWhmcsParamByKey('serviceid'))
             ->firstOrFail();
             ->firstOrFail();
+        if(!$this->canDelete($vi)){
+            sl("lang")->addReplacementConstant("ip", $vi->ip);
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('Delete the primary Ip Address :ip: is restricted.');
+        }
         $this->networkService->deleteByIpAddresses([$vi]);
         $this->networkService->deleteByIpAddresses([$vi]);
         if ($this->configuration()->isIpsetIpFilter()){
         if ($this->configuration()->isIpsetIpFilter()){
             $ipSetFilterService =  new IpSetIpFilterService();
             $ipSetFilterService =  new IpSetIpFilterService();
@@ -161,5 +185,22 @@ class VirtualInterfaceProvider extends BaseModelDataProvider implements ClientAr
 
 
     }
     }
 
 
+    protected function canDelete(VirtualInterface  $vi){
+        if(!$this->configuration()->isOneNetworkDevice()){
+            return true;
+        }
+        if( $vi->net != "net0"  ){
+            return  true;
+        }
+        $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
+        if($vm instanceof  Kvm && $vm->getIpConfig()->findByNetworkId("net0")->fetch()[0]->getIp(false) == $vi->ip   ){
+            return false;
+        }
+        if($vm instanceof  Lxc && $vm->findNetworkDevice($vi->ip) instanceof NetworkDeviceLxc){
+            return false;
+        }
+        return  true;
+    }
+
 
 
 }
 }

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

@@ -8,6 +8,7 @@ use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Pages\BackupDataTable;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Pages\BackupDataTable;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Pages\BackupRawDataTable;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Backup\Pages\BackupRawDataTable;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Pages\BackupJobDataTable;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\BackupJob\Pages\BackupJobDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Resources\Pages\ResourcesContainer;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\TabsWidget\TabsWidget;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\TabsWidget\TabsWidget;
 
 
@@ -25,6 +26,7 @@ class BackupTab extends TabsWidget implements ClientArea
         $this->unsetShowTitle();
         $this->unsetShowTitle();
         $this->addElement(new BackupDataTable());
         $this->addElement(new BackupDataTable());
         $this->addElement(new BackupJobDataTable);
         $this->addElement(new BackupJobDataTable);
+        $this->addElement(new ResourcesContainer());
 
 
     }
     }
 }
 }

+ 5 - 1
app/UI/Vm/Pages/DetailTab.php

@@ -13,6 +13,7 @@ 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\ReinstallTab;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages\TemplateDataTable;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Reinstall\Pages\TemplateDataTable;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Pages\SnapshotDataTable;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Pages\SnapshotDataTable;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Snapshot\Pages\SnapshotTab;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\TaskHistory\Pages\TaskHistoryDataTable;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\TaskHistory\Pages\TaskHistoryDataTable;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Pages\VirtualInterfaceDataTable;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VirtualInterface\Pages\VirtualInterfaceDataTable;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
@@ -44,10 +45,13 @@ class VmTabs extends TabsWidget implements ClientArea
             }
             }
         }
         }
         //snapshot
         //snapshot
-        if ($this->configuration()->isPermissionSnapshot())
+        if ($this->configuration()->isPermissionSnapshot() && !$this->configuration()->isPermissionSnapshotJob() )
         {
         {
             $this->addElement(new SnapshotDataTable());
             $this->addElement(new SnapshotDataTable());
+        }else if($this->configuration()->isPermissionSnapshot() && $this->configuration()->isPermissionSnapshotJob() ){
+            $this->addElement(new SnapshotTab());
         }
         }
+
         //backup
         //backup
         if ($this->configuration()->isPermissionBackupJob())
         if ($this->configuration()->isPermissionBackupJob())
         {
         {

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

@@ -0,0 +1,55 @@
+<?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 ArchiveSelect 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();
+        $fileRepository = new FileRepository();
+        $fileRepository->findByNodes([$defaultNode])
+            ->findByStorages($storages);
+        if($this->configuration()->isLxc()){
+            $fileRepository->findBackupLxcTemplates();
+        }
+        if($this->configuration()->isQemu()){
+            $fileRepository->findBackupQemuTemplates();
+        }
+        foreach ($fileRepository->fetch() as $entity)
+        {
+            $fileKey = sprintf("%s:%s",$entity->getNode(),$entity->getVolid());
+            if ($this->configuration()->archive && !in_array($fileKey, $this->configuration()->archive))
+            {
+                continue;
+            }
+
+            $this->availableValues[]=[
+                "key" => $fileKey ,
+                "value"     => $entity->formatVolid(),
+            ];
+        }
+    }
+
+
+}

+ 8 - 1
app/UI/VmCreate/Fields/IsoImageSelect.php

@@ -40,10 +40,17 @@ class OsTemplateSelect extends Select implements ClientArea
         {
         {
             $this->loadLxcTemplates();
             $this->loadLxcTemplates();
         }
         }
+
         if($this->availableValues[0]['key']){
         if($this->availableValues[0]['key']){
             $this->value = $this->availableValues[0]['key'];
             $this->value = $this->availableValues[0]['key'];
         }
         }
-
+        if ( $this->configuration()->isPermissionArchive())
+        {
+            $this->availableValues[] = [
+                "key"   => 'installationFromArchive',
+                "value" => sl('lang')->abtr('template','InstallationFromArchive'),
+            ];
+        }
         $this->data['additionalData']['showItemDescription']  = true;
         $this->data['additionalData']['showItemDescription']  = true;
     }
     }
 
 

+ 84 - 26
app/UI/VmCreate/Fields/SecondaryIsoImageSelect.php

@@ -8,25 +8,25 @@ use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CloneQemuJob;
 use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateLxcJob;
 use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateLxcJob;
 use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateQemuJob;
 use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateQemuJob;
 use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateSnippet;
 use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\CreateSnippet;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\MigrateVmJob;
+use ModulesGarden\ProxmoxAddon\App\Jobs\Cloud\RestoreArchiveJob;
 use ModulesGarden\ProxmoxAddon\App\Libs\Format;
 use ModulesGarden\ProxmoxAddon\App\Libs\Format;
 use ModulesGarden\ProxmoxAddon\App\Models\CloudInitScript;
 use ModulesGarden\ProxmoxAddon\App\Models\CloudInitScript;
 use ModulesGarden\ProxmoxAddon\App\Models\VirtualInterface;
 use ModulesGarden\ProxmoxAddon\App\Models\VirtualInterface;
-use ModulesGarden\ProxmoxAddon\App\Models\VirtualNetwork;
 use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
 use ModulesGarden\ProxmoxAddon\App\Models\VmIpAddress;
 use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
 use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
 use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\NetworkService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ResourceManager;
-use ModulesGarden\ProxmoxAddon\App\Services\Ip\Ipv4Range;
 use ModulesGarden\ProxmoxAddon\App\Services\Utility;
 use ModulesGarden\ProxmoxAddon\App\Services\Utility;
-use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\BuildUrl;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\UrlServiceHelper;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\Helpers\UrlServiceHelper;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\FileReader\Reader\Json;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\FileReader\Reader\Json;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\ModuleConstants;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\ModuleConstants;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\ClientArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\ResponseTemplates\HtmlDataJsonResponse;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\DataProviders\BaseModelDataProvider;
 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\queue;
 use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
 use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
 
 
@@ -114,11 +114,29 @@ class VmCreateProvider extends BaseModelDataProvider implements ClientArea
                 ->setMessageAndTranslate('You are not able to set :additional_disks_size: GB of the additional disks size. The available size is: :size: GB');
                 ->setMessageAndTranslate('You are not able to set :additional_disks_size: GB of the additional disks size. The available size is: :size: GB');
         }
         }
         //ipv4
         //ipv4
-        if($this->configuration()->serverIpv4->min &&  $this->configuration()->serverIpv4->min > $this->countPublicIpv4() ){
+        if($this->configuration()->isOrderPublicIp() && $this->configuration()->serverIpv4->min &&  $this->configuration()->serverIpv4->min > $this->countPublicIpv4() ){
             return (new HtmlDataJsonResponse())
             return (new HtmlDataJsonResponse())
                 ->setStatusError()
                 ->setStatusError()
                 ->setMessageAndTranslate('Select the Virtual Network with IPv4 address');
                 ->setMessageAndTranslate('Select the Virtual Network with IPv4 address');
         }
         }
+        //serverVirtualInterfaces
+        if($this->configuration()->isPermissionVirtualNetwork() && $this->configuration()->serverVirtualInterfaces->min &&  $this->configuration()->serverVirtualInterfaces->min > $this->countVirtualIntefaces() ){
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('Select the Virtual Network');
+        }
+        if($this->configuration()->isPermissionVirtualNetwork() && $this->configuration()->serverVirtualInterfaces->max  && $this->configuration()->serverVirtualInterfaces->max < $vi =$this->countVirtualIntefaces() ){
+            sl("lang")->addReplacementConstant("virtual_interfaces", (string)$vi);
+            sl("lang")->addReplacementConstant("max",$this->configuration()->serverVirtualInterfaces->max);
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('You are not able to set :virtual_interfaces: of the virtual inferfaces. The  available virtual interfec is: :max:');
+        }
+        if($this->configuration()->isPermissionVirtualNetwork() && $this->configuration()->serverVirtualInterfaces->min &&  $this->configuration()->serverVirtualInterfaces->min > $this->countVirtualIntefaces() ){
+            return (new HtmlDataJsonResponse())
+                ->setStatusError()
+                ->setMessageAndTranslate('Select the Virtual Network');
+        }
         $this->vmModel = new VmModel();
         $this->vmModel = new VmModel();
         $this->fillVmModel();
         $this->fillVmModel();
         if($this->vmTemplate instanceof  Kvm){
         if($this->vmTemplate instanceof  Kvm){
@@ -138,9 +156,29 @@ class VmCreateProvider extends BaseModelDataProvider implements ClientArea
         if($this->configuration()->isCalculateSocketsAndCores()){
         if($this->configuration()->isCalculateSocketsAndCores()){
             $this->calculateSocketsAndCores();
             $this->calculateSocketsAndCores();
         };
         };
+        $networkService = new NetworkService();
+        $bridge = $this->configuration()->getBridge();
+        if(!$this->configuration()->isOrderPublicIp()){
+            //ip validation
+            $networkService->hasIp((int)$this->formData['ipv4'], (int)$this->formData['ipv6'], $this->vmModel->node,  $bridge );
+        }
         //init vm
         //init vm
         $this->vmModel->save();
         $this->vmModel->save();
         \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->setVmModel($this->vmModel);
         \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->setVmModel($this->vmModel);
+        //assign IPs
+        if(!$this->configuration()->isOrderPublicIp()){
+            $networkService->addIp((int)$this->formData['ipv4'], (int)$this->formData['ipv6'], $this->vmModel->node,$bridge);
+            foreach (VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                         ->ofVmId($this->vmModel->id)->get() as $vmIp){
+                $vi = new VirtualInterface();
+                $vi->ip = $vmIp->ip;
+                $vi->ip_long = ip2long($vmIp->ip);
+                $vi->vm_id = $this->vmModel->id;
+                $vi->vn_id = 0;
+                $vi->hosting_id = $this->getWhmcsParamByKey('serviceid');
+                $vi->save();
+            }
+        }
         $this->createJob();
         $this->createJob();
         //virtual interfaces
         //virtual interfaces
         for($i=1; $i<=20; $i++){
         for($i=1; $i<=20; $i++){
@@ -164,24 +202,6 @@ class VmCreateProvider extends BaseModelDataProvider implements ClientArea
             $vi->save();
             $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())
         return (new  HtmlDataJsonResponse())
             ->setMessageAndTranslate('The process of Virtual Machine creation is in progress')
             ->setMessageAndTranslate('The process of Virtual Machine creation is in progress')
             ->setCallBackFunction('pcVmCreatedAjaxDone')
             ->setCallBackFunction('pcVmCreatedAjaxDone')
@@ -190,8 +210,10 @@ class VmCreateProvider extends BaseModelDataProvider implements ClientArea
     }
     }
 
 
     private function getJobClass(){
     private function getJobClass(){
-        if($this->getFormDataValues()['osTemplate']  && $this->formData['osTemplate'] !='installationFromIso' && $this->configuration()->isQemu()){
+        if($this->getFormDataValues()['osTemplate']  && !in_array($this->formData['osTemplate'] ,['installationFromIso','installationFromArchive']) && $this->configuration()->isQemu()){
             return CloneQemuJob::class;
             return CloneQemuJob::class;
+        }elseif (  $this->configuration()->isQemu() && $this->formData['osTemplate'] == "installationFromArchive"){
+            return RestoreArchiveJob::class;
         }elseif (  $this->configuration()->isQemu()){
         }elseif (  $this->configuration()->isQemu()){
             return CreateQemuJob::class;
             return CreateQemuJob::class;
         }else{
         }else{
@@ -208,6 +230,7 @@ class VmCreateProvider extends BaseModelDataProvider implements ClientArea
 
 
     private function createJob(){
     private function createJob(){
         $jobClass = $this->getJobClass();
         $jobClass = $this->getJobClass();
+        //snippet
         if($jobClass == CloneQemuJob::class  && $this->getFormDataValues()['cloudInitScript']){
         if($jobClass == CloneQemuJob::class  && $this->getFormDataValues()['cloudInitScript']){
             $parent = queue(
             $parent = queue(
                 CreateSnippet::class,
                 CreateSnippet::class,
@@ -218,7 +241,7 @@ class VmCreateProvider extends BaseModelDataProvider implements ClientArea
                 $this->vmModel->id
                 $this->vmModel->id
             );
             );
         }
         }
-        return queue(
+        $parent = queue(
             $this->getJobClass(),
             $this->getJobClass(),
             $this->getJobArguments(),
             $this->getJobArguments(),
             $parent->id,
             $parent->id,
@@ -226,6 +249,26 @@ class VmCreateProvider extends BaseModelDataProvider implements ClientArea
             $this->getWhmcsParamByKey("serviceid"),
             $this->getWhmcsParamByKey("serviceid"),
             $this->vmModel->id
             $this->vmModel->id
         );
         );
+        //archive
+        if($this->formData['archive'] && $this->formData['osTemplate'] == "installationFromArchive"  ){
+            list($backupNode, $volid) = explode(":", $this->formData['archive'], 2);
+            if($this->vmModel->node != $backupNode){
+                $attributes = [
+                    "targetNode" => $this->vmModel->node,
+                    "online"     => 1,
+                    'with-local-disks' => 1,
+                    'restart' => 1
+                ];
+                queue(
+                    MigrateVmJob::class,
+                    $attributes,
+                    $parent->id,
+                    "hosting",
+                    $this->getWhmcsParamByKey("serviceid"),
+                    $this->vmModel->id
+                );
+            }
+        }
     }
     }
 
 
 
 
@@ -252,7 +295,7 @@ class VmCreateProvider extends BaseModelDataProvider implements ClientArea
         $diskSizeBytes = $this->formData['disk'];
         $diskSizeBytes = $this->formData['disk'];
         Utility::unitFormat($diskSizeBytes,'gb','bytes');
         Utility::unitFormat($diskSizeBytes,'gb','bytes');
         $this->templateDiskSizeBytes = $this->vmTemplate->getMasterHardDisk()->getBytes();
         $this->templateDiskSizeBytes = $this->vmTemplate->getMasterHardDisk()->getBytes();
-        return $diskSizeBytes > $this->templateDiskSizeBytes;
+        return $diskSizeBytes >= $this->templateDiskSizeBytes;
     }
     }
 
 
     protected function fillVmModel(){
     protected function fillVmModel(){
@@ -340,4 +383,19 @@ class VmCreateProvider extends BaseModelDataProvider implements ClientArea
         return $total;
         return $total;
     }
     }
 
 
-}
+    public function countVirtualIntefaces(){
+        $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;
+    }
+}

+ 32 - 30
app/UI/VmCreate/Sections/AccountSummary.php

@@ -10,13 +10,16 @@ use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\IpAddressValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\PasswordValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\PasswordValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\SshPublicKeyValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\SshPublicKeyValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields\ArchiveSelect;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields\OsTemplateSelect;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields\OsTemplateSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\ArchiveValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\DiskSizeValidator;
 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\Range;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Select;
 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\Text;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
 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\BaseSection;
+
 use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
 use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
 
 
 class GeneralSection extends BaseSection
 class GeneralSection extends BaseSection
@@ -37,40 +40,33 @@ class GeneralSection extends BaseSection
 
 
     public function 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
         //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);
+        if ($this->configuration()->isPermissionIpv4() && !$this->configuration()->isOrderPublicIp()) {
+            $field = new Text('ipv4');
+            $field->addValidator(
+                new NumberValidator(
+                    $this->resourceManager->ipv4()->getMin(),
+                    $this->resourceManager->ipv4()->free(),
+                    $this->resourceManager->ipv4()->getMin() > 0
+                )
+            );
+            $field->setDefaultValue($this->configuration()->serverIpv4->min);
+            $field->setDescription('description');
+            $this->addField($field);
         }
         }
         //ipv6
         //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);
+        if($this->configuration()->isPermissionIpv6() && !$this->configuration()->isOrderPublicIp()) {
+            $field = new Text('ipv6');
+            $field->addValidator(
+                new NumberValidator(
+                    $this->resourceManager->ipv6()->getMin(),
+                    $this->resourceManager->ipv6()->free(),
+                    $this->resourceManager->ipv6()->getMin() > 0
+                )
+            );
+            $field->setDefaultValue($this->configuration()->serverIpv6->min);
+            $this->addField($field);
         }
         }
-         */
         $cpuPrioryty = $this->configuration()->hasCpuPriority();
         $cpuPrioryty = $this->configuration()->hasCpuPriority();
         //location
         //location
         if($this->configuration()->getLocations()){
         if($this->configuration()->getLocations()){
@@ -169,5 +165,11 @@ class GeneralSection extends BaseSection
             $field->setDescription('description');
             $field->setDescription('description');
             $this->addField($field);
             $this->addField($field);
         }
         }
+        if($this->configuration()->isPermissionArchive() ){
+            $field = new ArchiveSelect('archive');
+            $field->setDescription('description');
+            $field->addValidator(new ArchiveValidator());
+            $this->addField($field);
+        }
     }
     }
 }
 }

+ 14 - 25
app/UI/VmCreate/Sections/Qemu/GeneralSection.php

@@ -10,9 +10,11 @@ use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\HostnameValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\IpAddressValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\IpAddressValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\NumberValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\SshPublicKeyValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Validators\SshPublicKeyValidator;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields\ArchiveSelect;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields\IsoImageSelect;
 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\OsTemplateSelect;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields\SecondaryIsoImageSelect;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Fields\SecondaryIsoImageSelect;
+use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\ArchiveValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\DiskSizeValidator;
 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\IsoImageValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\NameserverValidator;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators\NameserverValidator;
@@ -46,24 +48,7 @@ class GeneralSection extends HalfPageSection
     public function initFields()
     public function initFields()
     {
     {
         $advancedUser = new AdvancedUserHelper($this->getWhmcsParamByKey('userid'));
         $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
         $cpuPrioryty = $this->configuration()->hasCpuPriority();
         $cpuPrioryty = $this->configuration()->hasCpuPriority();
         //location
         //location
         if($this->configuration()->getLocations()){
         if($this->configuration()->getLocations()){
@@ -200,24 +185,28 @@ class GeneralSection extends HalfPageSection
             $field->setDescription('description');
             $field->setDescription('description');
             $this->addField($field);
             $this->addField($field);
         }
         }
-        /**
-         * @deprecated
+        if($this->configuration()->isPermissionArchive() ){
+            $field = new ArchiveSelect('archive');
+            $field->setDescription('description');
+            $field->addValidator(new ArchiveValidator());
+            $this->addField($field);
+        }
         //ipv4
         //ipv4
-        if($this->configuration()->isPermissionIpv4()){
+        if($this->configuration()->isPermissionIpv4() && !$this->configuration()->isOrderPublicIp()){
             $field = new Text('ipv4');
             $field = new Text('ipv4');
-            $field->addValidator(new NumberValidator($this->resourceManager->ipv4()->getMin(), $this->resourceManager->ipv4()->free(),false));
+            $field->addValidator(new NumberValidator($this->resourceManager->ipv4()->getMin(), $this->resourceManager->ipv4()->free(),$this->resourceManager->ipv4()->getMin() > 0));
             $field->setDefaultValue($this->configuration()->serverIpv4->min);
             $field->setDefaultValue($this->configuration()->serverIpv4->min);
             $field->setDescription('description');
             $field->setDescription('description');
             $this->addField($field);
             $this->addField($field);
         }
         }
         //ipv6
         //ipv6
-        if($this->configuration()->isPermissionIpv6()){
+        if($this->configuration()->isPermissionIpv6() && !$this->configuration()->isOrderPublicIp()){
             $field = new Text('ipv6');
             $field = new Text('ipv6');
-            $field->addValidator(new NumberValidator($this->resourceManager->ipv6()->getMin(), $this->resourceManager->ipv6()->free(),false));
+            $field->addValidator(new NumberValidator($this->resourceManager->ipv6()->getMin(), $this->resourceManager->ipv6()->free(),$this->resourceManager->ipv6()->getMin() > 0));
             $field->setDefaultValue($this->configuration()->serverIpv6->min);
             $field->setDefaultValue($this->configuration()->serverIpv6->min);
             $field->setDescription('description');
             $field->setDescription('description');
             $this->addField($field);
             $this->addField($field);
         }
         }
-         */
+
     }
     }
 }
 }

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

@@ -31,8 +31,6 @@ class TopSection extends RawSection
         }
         }
         //description
         //description
         $field = new Textarea('description');
         $field = new Textarea('description');
-        //$field->unsetShowTitle();
-        //$field->setPlaceholder(sl('lang')->tr('Description'));
         $field->setRows(2);
         $field->setRows(2);
         $field->replaceClasses(['lu-m-t-1x lu-m-b-0x']);
         $field->replaceClasses(['lu-m-t-1x lu-m-b-0x']);
         $this->addField($field);
         $this->addField($field);

+ 14 - 11
app/UI/VmCreate/Sections/VirtualNetworkSection.php

@@ -27,21 +27,25 @@ class VirtualNetworkSection extends BaseSection implements ClientArea
     public function initFields()
     public function initFields()
     {
     {
         //virtualNetwork
         //virtualNetwork
-        $this->customTplVars['virtualNetwork'] = ["public" => sl('lang')->abtr('Public')];
+        if($this->configuration()->isOrderPublicIp()){
+            $this->customTplVars['virtualNetwork'] = ["public" => sl('lang')->abtr('Public')];
+        }
         //ips
         //ips
         $this->customTplVars['ips']=[];
         $this->customTplVars['ips']=[];
         //Public
         //Public
         $this->customTplVars['ipSelected'] =null;
         $this->customTplVars['ipSelected'] =null;
-        foreach (VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))->ofVmIdNull()->get() as $ip)
-        {
-            if(!$this->customTplVars['ipSelected'] ){
-                $this->customTplVars['ipSelected']  = $ip->ip;
+        if($this->configuration()->isOrderPublicIp()){
+            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
+                ];
             }
             }
-            $this->customTplVars['ips'][] =[
-                "networkId" => "public",
-                "ip" => $ip->ip,
-                "id" => $ip->id
-            ];
         }
         }
         if(empty($this->customTplVars['ips'])){
         if(empty($this->customTplVars['ips'])){
             unset($this->customTplVars['virtualNetwork']['public']);
             unset($this->customTplVars['virtualNetwork']['public']);
@@ -61,6 +65,5 @@ class VirtualNetworkSection extends BaseSection implements ClientArea
             }
             }
         }
         }
 
 
-
     }
     }
 }
 }

+ 31 - 0
app/UI/VmCreate/Templates/sections/accountSummary.tpl

@@ -0,0 +1,31 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\VmCreate\Validators;
+
+use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Validators\BaseValidator;
+
+class ArchiveValidator extends BaseValidator
+{
+
+    protected function validate($data, $additionalData = null)
+    {
+        if($additionalData->get('formData')['osTemplate'] && $additionalData->get('formData')['osTemplate']!='installationFromArchive' ){
+            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;
+    }
+
+}

+ 24 - 16
app/UI/VmCreate/Validators/DiskSizeValidator.php

@@ -58,11 +58,10 @@ class VmUpdateProvider extends VmCreateProvider
         $ns = explode(" ",$config['nameserver']);
         $ns = explode(" ",$config['nameserver']);
         $this->data['nameserver[0]'] = $ns[0];
         $this->data['nameserver[0]'] = $ns[0];
         $this->data['nameserver[1]'] = $ns[1];
         $this->data['nameserver[1]'] = $ns[1];
-        /**
-         * @deprecated
-        $this->data['ipv4'] = $this->vmModel->ipv4Addresses->count();
-        $this->data['ipv6'] = $this->vmModel->ipv6Addresses->count();
-         */
+        if(!$this->configuration()->isOrderPublicIp()){
+            $this->data['ipv4'] = $this->vmModel->ipv4Addresses->count();
+            $this->data['ipv6'] = $this->vmModel->ipv6Addresses->count();
+        }
         //Boot order
         //Boot order
         if($vm instanceof Kvm){
         if($vm instanceof Kvm){
             $bootOrder                           = $vm->getBootOrder();
             $bootOrder                           = $vm->getBootOrder();
@@ -140,16 +139,23 @@ class VmUpdateProvider extends VmCreateProvider
         $this->vmModel = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
         $this->vmModel = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVmModel();
         $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
         $vm = \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm();
         $this->networkService = new NetworkService();
         $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);
-         */
-
+        if(!$this->configuration()->isOrderPublicIp()){
+            $ipv4 = (int) $this->getFormDataValues()['ipv4'] - (int)  $this->vmModel->ipv4Addresses->count();
+            $ipv6  = (int)$this->getFormDataValues()['ipv6'] - (int)  $this->vmModel->ipv6Addresses->count();
+            $this->networkService->hasIp($ipv4, $ipv6, $this->vmModel->node, $this->configuration()->getBridge());
+            $this->networkService->addIp($ipv4, $ipv6, $this->vmModel->node, $this->configuration()->getBridge());
+            $this->networkService->unassignIpAddressesAndDeleteNetwork($ipv4, $ipv6);
+            foreach (VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))
+                         ->ofVmId($this->vmModel->id)->ofNetNull()->get() as $vmIp){
+                $vi = new VirtualInterface();
+                $vi->ip = $vmIp->ip;
+                $vi->ip_long = ip2long($vmIp->ip);
+                $vi->vm_id = $this->vmModel->id;
+                $vi->vn_id = 0;
+                $vi->hosting_id = $this->getWhmcsParamByKey('serviceid');
+                $vi->save();
+            }
+        }
         //load data
         //load data
         $this->getFormDataValues();
         $this->getFormDataValues();
         if ($vm instanceof Kvm)
         if ($vm instanceof Kvm)
@@ -298,7 +304,9 @@ class VmUpdateProvider extends VmCreateProvider
             }
             }
             if ($newVi) {
             if ($newVi) {
                 $config = (new VirtualInterfaceConverter($newVi, \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm()))->asConfig();
                 $config = (new VirtualInterfaceConverter($newVi, \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm()))->asConfig();
-                \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm()->updateConfig($config);
+                if(!empty($config)){
+                    \ModulesGarden\ProxmoxAddon\Core\Helper\sl('Vm')->getVm()->updateConfig($config);
+                }
             }
             }
             DB::commit();
             DB::commit();
         } catch (\Exception $ex) {
         } catch (\Exception $ex) {

+ 23 - 13
app/UI/VmUpdate/Sections/Lxc/AdditionalDiskSection.php

@@ -15,6 +15,7 @@ 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\Text;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Textarea;
 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\BaseSection;
+
 use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
 use function ModulesGarden\Servers\ProxmoxCloudVps\Core\Helper\sl;
 
 
 class GeneralSection extends BaseSection
 class GeneralSection extends BaseSection
@@ -37,23 +38,32 @@ class GeneralSection extends BaseSection
 
 
     public function initFields()
     public function initFields()
     {
     {
-        /**
-         * @deprecated
         //ipv4
         //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);
+        if (!$this->configuration()->isOrderPublicIp() && $this->configuration()->isPermissionIpv4()) {
+            $field = new Text('ipv4');
+            $field->addValidator(
+                new NumberValidator(
+                    $this->resourceManager->ipv4()->getMin(),
+                    $this->resourceManager->ipv4()->free(),
+                    $this->resourceManager->ipv4()->getMin() > 0
+                )
+            );
+            $field->setDescription('description');
+            $this->addField($field);
         }
         }
         //ipv6
         //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);
+        if (!$this->configuration()->isOrderPublicIp() && $this->configuration()->isPermissionIpv6()) {
+            $field = new Text('ipv6');
+            $field->addValidator(
+                new NumberValidator(
+                    $this->resourceManager->ipv6()->getMin(),
+                    $this->resourceManager->ipv6()->free(),
+                    $this->resourceManager->ipv6()->getMin() > 0
+                )
+            );
+            $field->setDescription('description');
+            $this->addField($field);
         }
         }
-         */
         $cpuPrioryty = $this->configuration()->hasCpuPriority();
         $cpuPrioryty = $this->configuration()->hasCpuPriority();
         //name
         //name
         $field = new Text('name');
         $field = new Text('name');

+ 4 - 8
app/UI/VmUpdate/Sections/Qemu/AdditionalDiskSection.php

@@ -128,24 +128,20 @@ class GeneralSection extends BaseSection
             $field->setDescription('description');
             $field->setDescription('description');
             $this->addField($field);
             $this->addField($field);
         }
         }
-        /**
-         * @deprecated
         //ipv4
         //ipv4
-        if($this->configuration()->isPermissionIpv4()){
+        if(!$this->configuration()->isOrderPublicIp() && $this->configuration()->isPermissionIpv4()){
             $field = new Text('ipv4');
             $field = new Text('ipv4');
-            $field->addValidator(new NumberValidator($this->resourceManager->ipv4()->getMin(), $this->resourceManager->ipv4()->free(),false));
+            $field->addValidator(new NumberValidator($this->resourceManager->ipv4()->getMin(), $this->resourceManager->ipv4()->free(),$this->resourceManager->ipv4()->getMin() > 0));
             $field->setDescription('description');
             $field->setDescription('description');
             $this->addField($field);
             $this->addField($field);
         }
         }
         //ipv6
         //ipv6
-        if($this->configuration()->isPermissionIpv6()){
+        if(!$this->configuration()->isOrderPublicIp() && $this->configuration()->isPermissionIpv6()){
             $field = new Text('ipv6');
             $field = new Text('ipv6');
-            $field->addValidator(new NumberValidator($this->resourceManager->ipv6()->getMin(), $this->resourceManager->ipv6()->free(),false));
+            $field->addValidator(new NumberValidator($this->resourceManager->ipv6()->getMin(), $this->resourceManager->ipv6()->free(),$this->resourceManager->ipv6()->getMin() > 0));
             $field->setDescription('description');
             $field->setDescription('description');
             $this->addField($field);
             $this->addField($field);
         }
         }
-         *
-         */
         //dnsdomain
         //dnsdomain
         if($this->configuration()->isPermissionSearchdomain()){
         if($this->configuration()->isPermissionSearchdomain()){
              $field = new Text('searchdomain');
              $field = new Text('searchdomain');

+ 7 - 0
app/UI/VmUpdate/Sections/VirtualNetworkSection.php

@@ -19,6 +19,7 @@
 
 
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Forms;
 namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Forms;
 
 
+use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers\MigrateProvider;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Providers\MigrateProvider;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Helpers\AlertTypesConstants;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Helpers\AlertTypesConstants;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
 use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Interfaces\AdminArea;
@@ -29,6 +30,8 @@ use ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields\Switcher;
 
 
 class MigrateForm extends BaseForm implements AdminArea
 class MigrateForm extends BaseForm implements AdminArea
 {
 {
+    use ProductService;
+
     public function initContent()
     public function initContent()
     {
     {
         $this->initIds('migrateForm');
         $this->initIds('migrateForm');
@@ -55,5 +58,9 @@ class MigrateForm extends BaseForm implements AdminArea
         $this->addField($field);
         $this->addField($field);
         //online
         //online
         $this->addField((new Switcher('online'))->setDescription('tip'));
         $this->addField((new Switcher('online'))->setDescription('tip'));
+        //with-local-disks kvm only
+        if($this->configuration()->isQemu()){
+            $this->addField((new Switcher('with-local-disks'))->setDescription('tip')->setDefaultValue('on'));
+        }
     }
     }
 }
 }

+ 7 - 2
app/UI/Vms/Modals/DeleteModal.php

@@ -22,6 +22,7 @@ namespace ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Pages;
 use MGProvision\Proxmox\v2\VmFactory;
 use MGProvision\Proxmox\v2\VmFactory;
 use ModulesGarden\ProxmoxAddon\App\Decorators\OsTemplateDecorator;
 use ModulesGarden\ProxmoxAddon\App\Decorators\OsTemplateDecorator;
 use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
 use ModulesGarden\ProxmoxAddon\App\Models\VmModel;
+use ModulesGarden\ProxmoxAddon\App\Repositories\ModuleSettingRepository;
 use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\ApiService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\ProxmoxAddon\App\Services\Cloud\ProductService;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Buttons\CreateButton;
 use ModulesGarden\Servers\ProxmoxCloudVps\App\UI\Vms\Buttons\CreateButton;
@@ -54,6 +55,7 @@ class VmsDataTable extends DataTable implements ClientArea, AdminArea
         $this->addClass('lu-text-left');
         $this->addClass('lu-text-left');
 
 
         $isAdmin = isAdmin();
         $isAdmin = isAdmin();
+        $moduleSettings = new ModuleSettingRepository();
         //create
         //create
         if(!$isAdmin){
         if(!$isAdmin){
             $createButton = new ButtonRedirect('createVmButton');
             $createButton = new ButtonRedirect('createVmButton');
@@ -67,6 +69,8 @@ class VmsDataTable extends DataTable implements ClientArea, AdminArea
         //import
         //import
         if($isAdmin){
         if($isAdmin){
             $this->addButton(new ImportButton());
             $this->addButton(new ImportButton());
+        }
+        if($isAdmin && $moduleSettings->isPermissionMigrate()){
             //migrate
             //migrate
             $this->addActionButton(new MigrateButton());
             $this->addActionButton(new MigrateButton());
         }
         }
@@ -82,7 +86,8 @@ class VmsDataTable extends DataTable implements ClientArea, AdminArea
     protected function loadHtml()
     protected function loadHtml()
     {
     {
         if(isAdmin()){
         if(isAdmin()){
-            $this->addColumn((new Column('vmid')));
+            $this->addColumn((new Column('vmid')))
+                ->addColumn((new Column('node')));
         }
         }
         $this->addColumn((new Column('name')))
         $this->addColumn((new Column('name')))
             ->addColumn((new Column('status')))
             ->addColumn((new Column('status')))
@@ -138,7 +143,7 @@ class VmsDataTable extends DataTable implements ClientArea, AdminArea
 
 
     protected function loadData()
     protected function loadData()
     {
     {
-        $query    = VmModel::select("id", "name", "vcpus", "memory", "disk","disks", "vmid","data")
+        $query    = VmModel::select("id", "name", "vcpus", "memory", "disk","disks", "vmid","data","node")
             ->ofHostingId($this->getWhmcsParamByKey('serviceid'))
             ->ofHostingId($this->getWhmcsParamByKey('serviceid'))
             ->notTemplate()
             ->notTemplate()
             ->getQuery();
             ->getQuery();

+ 3 - 0
app/UI/Vms/Providers/DeleteVmProvider.php

@@ -78,6 +78,9 @@ class MigrateProvider extends BaseDataProvider implements AdminArea
             "targetNode" => $this->formData['target'],
             "targetNode" => $this->formData['target'],
             "online"     => $this->formData['online'] == "on" ? 1 : 0
             "online"     => $this->formData['online'] == "on" ? 1 : 0
         ];
         ];
+        if($this->formData['with-local-disks'] && $this->configuration()->isQemu()){
+            $attributes['with-local-disks'] = $this->formData['with-local-disks'] == "on" ? 1 : 0;
+        }
         if (Job::where("job", MigrateVmJob::class. '@handle')->whereIn("status", ['waiting', "running", ""])
         if (Job::where("job", MigrateVmJob::class. '@handle')->whereIn("status", ['waiting', "running", ""])
                                                   ->where("rel_id", $this->getWhmcsParamByKey("serviceid"))
                                                   ->where("rel_id", $this->getWhmcsParamByKey("serviceid"))
                                                   ->where("rel_type", "hosting")
                                                   ->where("rel_type", "hosting")

+ 1 - 1
commands/commands.php

@@ -260,7 +260,7 @@ class ConfigOptions extends \ModulesGarden\Servers\ProxmoxCloudVps\Core\App\Cont
     {
     {
         $data = [
         $data = [
             'content' =>
             '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>',
+                '<div style="width=100%; margin-bottom: 0px;" class="alert alert-danger">' . $message . '</div>',
             'mode' => 'advanced'
             'mode' => 'advanced'
         ];
         ];
 
 

+ 1 - 1
core/App/Controllers/Instances/Addon/Deactivate.php

@@ -58,7 +58,7 @@ abstract class BaseDataProvider implements FormDataProviderInterface
 
 
     public function getAvailableValuesById($id)
     public function getAvailableValuesById($id)
     {
     {
-        if (is_array($this->availableValues[$id]) || count($this->availableValues[$id]) > 0)
+        if (is_array($this->availableValues[$id]) || (is_object($this->availableValues[$id]) &&  count($this->availableValues[$id]) > 0))
         {
         {
             return $this->availableValues[$id];
             return $this->availableValues[$id];
         }
         }

+ 9 - 0
core/UI/Widget/Forms/DataProviders/BaseModelDataProvider.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace ModulesGarden\Servers\ProxmoxCloudVps\Core\UI\Widget\Forms\Fields;
+
+class FileField extends BaseField
+{
+    protected $id   = 'fileField';
+    protected $name = 'fileField';
+}

+ 171 - 18
core/UI/Widget/Forms/Fields/Hidden.php

@@ -86,8 +86,8 @@ $_LANG['FormValidators']['PleaseProvideANumericValueBetween'] = 'Please provide
  * ******************************************************************************************************************** */
  * ******************************************************************************************************************** */
 //General
 //General
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['mainSection']['mainSection'] = 'General';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['mainSection']['mainSection'] = 'General';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['mainSection']['rightSection']['customconfigoption[resetUsageFirstDayOfMonth]']['customconfigoption[resetUsageFirstDayOfMonth]'] = 'Reset Usage First Day Of Month';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['mainSection']['rightSection']['customconfigoption[resetUsageFirstDayOfMonth]']['tip'] = 'Reset Usage First Day Of Month';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['mainSection']['rightSection']['customconfigoption[resetUsageFirstDayOfMonth]']['customconfigoption[resetUsageFirstDayOfMonth]'] = 'Reset Usage First Day of Month';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['mainSection']['rightSection']['customconfigoption[resetUsageFirstDayOfMonth]']['tip'] = 'Enable to reset the usage on the first day of the month';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['mainSection']['leftSection']['customconfigoption[virtualization]']['customconfigoption[virtualization]'] = 'Virtualization Type';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['mainSection']['leftSection']['customconfigoption[virtualization]']['customconfigoption[virtualization]'] = 'Virtualization Type';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['mainSection']['leftSection']['customconfigoption[debugMode]']['customconfigoption[debugMode]'] = 'Debug Mode';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['mainSection']['leftSection']['customconfigoption[debugMode]']['customconfigoption[debugMode]'] = 'Debug Mode';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['mainSection']['leftSection']['customconfigoption[debugMode]']['tip'] = 'Enable to store logs in the Module Log section';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['mainSection']['leftSection']['customconfigoption[debugMode]']['tip'] = 'Enable to store logs in the Module Log section';
@@ -163,6 +163,14 @@ $_LANG['serverAA']['product']['mainContainer']['mainForm']['containerSection']['
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['containerSection']['rightSection']['customconfigoption[swap]']['tip'] = 'Enter the number of SWAP files for the VM';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['containerSection']['rightSection']['customconfigoption[swap]']['tip'] = 'Enter the number of SWAP files for the VM';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['defaultConfigurationSection']['leftSection']['customconfigoption[swap]']['customconfigoption[swap]']= 'SWAP For VM [MiB]';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['defaultConfigurationSection']['leftSection']['customconfigoption[swap]']['customconfigoption[swap]']= 'SWAP For VM [MiB]';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['defaultConfigurationSection']['leftSection']['customconfigoption[swap]']['tip']  = 'Enter the number of SWAP files for the VM';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['defaultConfigurationSection']['leftSection']['customconfigoption[swap]']['tip']  = 'Enter the number of SWAP files for the VM';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['defaultConfigurationSection']['rightSection']['customconfigoption[snapshotJobs]']['customconfigoption[snapshotJobs]'] = 'Snapshot Jobs';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['defaultConfigurationSection']['rightSection']['customconfigoption[snapshotJobs]']['tip'] = 'Enter the maximum number of snapshot jobs or type in -1 to set it as unlimited';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['leftSection']['customconfigoption[permissionSnapshotJobPeriod][]']['customconfigoption[permissionSnapshotJobPeriod][]'] = 'Snapshot Job Period';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['leftSection']['customconfigoption[permissionSnapshotJobPeriod][]']['tip'] = 'Select the snapshot job period that should be available in the client area';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['rightSection']['customconfigoption[permissionSnapshotJob]']['customconfigoption[permissionSnapshotJob]'] = 'Snapshot Jobs';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['rightSection']['customconfigoption[permissionSnapshotJob]']['tip'] = 'If enabled, a client will be able to create the "Snapshot Job"  on their server';
+$_LANG['serverAA']['configOptions']['hourly'] = 'Hourly';
+$_LANG['serverAA']['configOptions']['daily'] = 'Daily';
 //Server Limits
 //Server Limits
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['serverSection'] = 'Server Limits';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['serverSection'] = 'Server Limits';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['leftSection']['customconfigoption[serverSockets]']['customconfigoption[serverSockets]'] = 'CPU Sockets';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['leftSection']['customconfigoption[serverSockets]']['customconfigoption[serverSockets]'] = 'CPU Sockets';
@@ -193,6 +201,11 @@ $_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['lef
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['leftSection']['customconfigoption[serverIpv4]']['tip'] = 'min-max';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['leftSection']['customconfigoption[serverIpv4]']['tip'] = 'min-max';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['leftSection']['customconfigoption[serverSwap]']['customconfigoption[serverSwap]'] = 'SWAP';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['leftSection']['customconfigoption[serverSwap]']['customconfigoption[serverSwap]'] = 'SWAP';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['leftSection']['customconfigoption[serverSwap]']['tip'] = 'min-max [MB]';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['leftSection']['customconfigoption[serverSwap]']['tip'] = 'min-max [MB]';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['rightSection']['customconfigoption[serverVirtualInterfaces]']['customconfigoption[serverVirtualInterfaces]'] = 'Virtual Interfaces';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['rightSection']['customconfigoption[serverVirtualInterfaces]']['tip'] = 'min-max ';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['leftSection']['customconfigoption[serverVirtualInterfaces]']['customconfigoption[serverVirtualInterfaces]'] = 'Virtual Interfaces';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['serverSection']['leftSection']['customconfigoption[serverVirtualInterfaces]']['tip'] = 'min-max';
+
 
 
 //network
 //network
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['networkSection']['networkSection'] = 'Network';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['networkSection']['networkSection'] = 'Network';
@@ -327,7 +340,7 @@ $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rig
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[additionalDiskReplicate]']['tip'] = 'If enabled, the replication of additional disks will be skipped';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[additionalDiskReplicate]']['tip'] = 'If enabled, the replication of additional disks will be skipped';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[additionalDiskDiscard]']['customconfigoption[additionalDiskDiscard]'] = 'Discard';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[additionalDiskDiscard]']['customconfigoption[additionalDiskDiscard]'] = 'Discard';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[additionalDiskDiscard]']['tip'] = 'Toggle discard';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[additionalDiskDiscard]']['tip'] = 'Toggle discard';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[permissionAdditionalDiskBackup]']['customconfigoption[permissionAdditionalDiskBackup]'] = 'Backups On Additional Disks';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[permissionAdditionalDiskBackup]']['customconfigoption[permissionAdditionalDiskBackup]'] = 'Backups on Additional Disks';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[permissionAdditionalDiskBackup]']['tip'] = 'If enabled, backups will be allowed on additional disks';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[permissionAdditionalDiskBackup]']['tip'] = 'If enabled, backups will be allowed on additional disks';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[additionalDiskSsd]']['customconfigoption[additionalDiskSsd]'] = 'SSD Emulation';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[additionalDiskSsd]']['customconfigoption[additionalDiskSsd]'] = 'SSD Emulation';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[additionalDiskSsd]']['tip'] = 'Toggle SSD emulation';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['additonalDisk']['rightSection']['customconfigoption[additionalDiskSsd]']['tip'] = 'Toggle SSD emulation';
@@ -385,6 +398,8 @@ $_LANG['serverAA']['product']['mainContainer']['mainForm']['firewallOptionSectio
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['firewallOptionSection']['rightSection']['customconfigoption[firewalOptionDhcp]']['customconfigoption[firewalOptionDhcp]'] = 'Enable DHCP';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['firewallOptionSection']['rightSection']['customconfigoption[firewalOptionDhcp]']['customconfigoption[firewalOptionDhcp]'] = 'Enable DHCP';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['firewallOptionSection']['rightSection']['customconfigoption[firewalOptionRadv]']['customconfigoption[firewalOptionRadv]'] = 'Allow Router Advertisement';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['firewallOptionSection']['rightSection']['customconfigoption[firewalOptionRadv]']['customconfigoption[firewalOptionRadv]'] = 'Allow Router Advertisement';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['firewallOptionSection']['rightSection']['customconfigoption[firewalOptionIpfilter]']['customconfigoption[firewalOptionIpfilter]'] = 'IP Filter';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['firewallOptionSection']['rightSection']['customconfigoption[firewalOptionIpfilter]']['customconfigoption[firewalOptionIpfilter]'] = 'IP Filter';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['firewallOptionSection']['leftSection']['customconfigoption[firewalOptionPolicyIn]']['customconfigoption[firewalOptionPolicyIn]'] = 'Input Policy';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['firewallOptionSection']['rightSection']['customconfigoption[firewalOptionPolicyOut]']['customconfigoption[firewalOptionPolicyOut]'] = 'Output Policy';
 //cloud init
 //cloud init
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['cloudInitSection'] = 'Cloud-Init';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['cloudInitSection'] = 'Cloud-Init';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['leftSection']['customconfigoption[cloudInit]']['customconfigoption[cloudInit]'] = 'Cloud-Init';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['leftSection']['customconfigoption[cloudInit]']['customconfigoption[cloudInit]'] = 'Cloud-Init';
@@ -395,9 +410,11 @@ $_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['rightSection']['customconfigoption[ciuser]']['tip'] = 'Enter the username to change SSH keys and password instead of using the image\'s configured default user';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['rightSection']['customconfigoption[ciuser]']['tip'] = 'Enter the username to change SSH keys and password instead of using the image\'s configured default user';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['leftSection']['customconfigoption[cicustom]']['customconfigoption[cicustom]'] = 'Custom Cloud-Init Configuration';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['leftSection']['customconfigoption[cicustom]']['customconfigoption[cicustom]'] = 'Custom Cloud-Init Configuration';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['leftSection']['customconfigoption[cicustom]']['tip'] = "Specify custom files to replace the automatically generated ones at start";
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['leftSection']['customconfigoption[cicustom]']['tip'] = "Specify custom files to replace the automatically generated ones at start";
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['rightSection']['customconfigoption[cloudInitStorage]']['customconfigoption[cloudInitStorage]'] = 'Storage';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['cloudInitSection']['rightSection']['customconfigoption[cloudInitStorage]']['tip'] = 'Select storage for Cloud-Init';
 //guest agent
 //guest agent
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['guestAgentSection'] = 'Guest Agent';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['guestAgentSection'] = 'Guest Agent';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agentPassword]']['customconfigoption[agentPassword]'] = 'Allow To Set Password';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agentPassword]']['customconfigoption[agentPassword]'] = 'Allow to Set Password';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agentPassword]']['tip'] = 'Allow To Set Password';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agentPassword]']['tip'] = 'Allow To Set Password';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agent]']['customconfigoption[agent]'] = 'Guest Agent';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agent]']['customconfigoption[agent]'] = 'Guest Agent';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agent]']['tip'] = 'If enabled, Guest Agent will run in a guest machine on boot, and search for configuration data to apply to the guest system during initialization';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agent]']['tip'] = 'If enabled, Guest Agent will run in a guest machine on boot, and search for configuration data to apply to the guest system during initialization';
@@ -405,10 +422,10 @@ $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection'][
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agentServicePassword]']['tip'] = 'If enabled, the service password will be used';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agentServicePassword]']['tip'] = 'If enabled, the service password will be used';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['rightSection']['customconfigoption[agentConfigureNetwork]']['customconfigoption[agentConfigureNetwork]'] = 'Configure Network';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['rightSection']['customconfigoption[agentConfigureNetwork]']['customconfigoption[agentConfigureNetwork]'] = 'Configure Network';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['rightSection']['customconfigoption[agentConfigureNetwork]']['tip'] = 'Automatically configure network (OS Window  only)';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['rightSection']['customconfigoption[agentConfigureNetwork]']['tip'] = 'Automatically configure network (OS Window  only)';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['rightSection']['customconfigoption[agentPassword]']['customconfigoption[agentPassword]'] = 'Allow To Set Password';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['rightSection']['customconfigoption[agentPassword]']['customconfigoption[agentPassword]'] = 'Allow to Set Password';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agentConfigureNetwork]']['customconfigoption[agentConfigureNetwork]'] = 'Configure Network';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agentConfigureNetwork]']['customconfigoption[agentConfigureNetwork]'] = 'Configure Network';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agentConfigureNetwork]']['tip'] = 'Automatically configure network (OS Window  only)';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['leftSection']['customconfigoption[agentConfigureNetwork]']['tip'] = 'Automatically configure network (OS Window  only)';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['rightSection']['customconfigoption[agentPassword]']['tip'] = 'Allow To Set Password';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['guestAgentSection']['rightSection']['customconfigoption[agentPassword]']['tip'] = 'Enable to allow setting the password';
 //user
 //user
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['userSection']['userSection'] = 'User';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['userSection']['userSection'] = 'User';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['userSection']['rightSection']['customconfigoption[oneUserPerVps]']['customconfigoption[oneUserPerVps]'] = 'One Username Per VPS';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['userSection']['rightSection']['customconfigoption[oneUserPerVps]']['customconfigoption[oneUserPerVps]'] = 'One Username Per VPS';
@@ -444,7 +461,7 @@ $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['rightSection']['customconfigoption[serverNameservers]']['tip'] = 'If enabled, the VM nameservers will be set based on the module\'s server configuration (provided in the form of an IP address), regardless of the nameservers defined by the client in the order.';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['rightSection']['customconfigoption[serverNameservers]']['tip'] = 'If enabled, the VM nameservers will be set based on the module\'s server configuration (provided in the form of an IP address), regardless of the nameservers defined by the client in the order.';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['leftSection']['customconfigoption[suspensionAction]']['customconfigoption[suspensionAction]'] = 'Suspension Action';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['leftSection']['customconfigoption[suspensionAction]']['customconfigoption[suspensionAction]'] = 'Suspension Action';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['leftSection']['customconfigoption[suspensionAction]']['tip'] = 'Choose the action to be performed on the server upon the WHMCS product suspension';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['leftSection']['customconfigoption[suspensionAction]']['tip'] = 'Choose the action to be performed on the server upon the WHMCS product suspension';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['rightSection']['customconfigoption[suspendOnBandwidthOverage]']['customconfigoption[suspendOnBandwidthOverage]'] = 'Suspend On Bandwidth Overage';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['rightSection']['customconfigoption[suspendOnBandwidthOverage]']['customconfigoption[suspendOnBandwidthOverage]'] = 'Suspend on Bandwidth Overage';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['rightSection']['customconfigoption[suspendOnBandwidthOverage]']['tip'] = 'Choose whether the WHMCS product should be suspended upon the server\'s bandwidth overage';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['rightSection']['customconfigoption[suspendOnBandwidthOverage]']['tip'] = 'Choose whether the WHMCS product should be suspended upon the server\'s bandwidth overage';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['rightSection']['customconfigoption[rebootVmAfterUpgrade']['customconfigoption[rebootVmAfterUpgrade'] = 'Reboot VM After Upgrade';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['rightSection']['customconfigoption[rebootVmAfterUpgrade']['customconfigoption[rebootVmAfterUpgrade'] = 'Reboot VM After Upgrade';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['rightSection']['customconfigoption[rebootVmAfterUpgrade']['tip'] = 'Reboot VM After Upgrade';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['rightSection']['customconfigoption[rebootVmAfterUpgrade']['tip'] = 'Reboot VM After Upgrade';
@@ -453,6 +470,8 @@ $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['networkSection']['rightSection']['customconfigoption[tags][]']['ip_manager_integration_tag'] = 'Tag';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['networkSection']['rightSection']['customconfigoption[tags][]']['ip_manager_integration_tag'] = 'Tag';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['leftSection']['customconfigoption[detailsView]']['customconfigoption[detailsView]'] = 'Details View';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['leftSection']['customconfigoption[detailsView]']['customconfigoption[detailsView]'] = 'Details View';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['leftSection']['customconfigoption[detailsView]']['tip'] = 'Select Virtual Machine details view.';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['leftSection']['customconfigoption[detailsView]']['tip'] = 'Select Virtual Machine details view.';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['leftSection']['customconfigoption[orderPublicIp]']['customconfigoption[orderPublicIp]'] = 'Order Public IP Addresses';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['miscellaneousSection']['leftSection']['customconfigoption[orderPublicIp]']['tip'] = 'Order public IP addresses on create account';
 $_LANG['serverAA']['configOptions']['Standard'] = 'Standard';
 $_LANG['serverAA']['configOptions']['Standard'] = 'Standard';
 $_LANG['serverAA']['configOptions']['Combined'] = 'Combined';
 $_LANG['serverAA']['configOptions']['Combined'] = 'Combined';
 $_LANG['serverAA']['configOptions']['Buttons'] ='Buttons';
 $_LANG['serverAA']['configOptions']['Buttons'] ='Buttons';
@@ -466,9 +485,9 @@ $_LANG['serverAA']['configOptions']['Hibernate VM'] = 'Hibernate VM';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['loadBalancerSection'] = 'Load Balancer';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['loadBalancerSection'] = 'Load Balancer';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['leftSection']['customconfigoption[loadBalancer]']['customconfigoption[loadBalancer]'] = 'Enable Load Balancer';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['leftSection']['customconfigoption[loadBalancer]']['customconfigoption[loadBalancer]'] = 'Enable Load Balancer';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['leftSection']['customconfigoption[loadBalancer]']['tip'] = 'If enabled, nodes will be dynamically rotated, and the VM will be created on the one with the lowest load';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['leftSection']['customconfigoption[loadBalancer]']['tip'] = 'If enabled, nodes will be dynamically rotated, and the VM will be created on the one with the lowest load';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['leftSection']['customconfigoption[loadBalancerShutdownOnUpgrade]']['customconfigoption[loadBalancerShutdownOnUpgrade]'] = 'Shut Down VM On Upgrade';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['leftSection']['customconfigoption[loadBalancerShutdownOnUpgrade]']['customconfigoption[loadBalancerShutdownOnUpgrade]'] = 'Shut Down VM on Upgrade';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['leftSection']['customconfigoption[loadBalancerShutdownOnUpgrade]']['tip'] = 'If enabled, the VM will be shut down before migration';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['leftSection']['customconfigoption[loadBalancerShutdownOnUpgrade]']['tip'] = 'If enabled, the VM will be shut down before migration';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['rightSection']['customconfigoption[loadBalancerOnUpgrade]']['customconfigoption[loadBalancerOnUpgrade]'] = 'Action On Upgrade';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['rightSection']['customconfigoption[loadBalancerOnUpgrade]']['customconfigoption[loadBalancerOnUpgrade]'] = 'Action on Upgrade';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['rightSection']['customconfigoption[loadBalancerOnUpgrade]']['tip'] = 'Select the action that should be performed upon the upgrade: "None" - disabled; "Block" - the upgrade process is blocked as there are insufficient resources on the VM node; "Migrate" - the upgrade process will be performed after previous migration of the VM to a server with sufficient free space';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['rightSection']['customconfigoption[loadBalancerOnUpgrade]']['tip'] = 'Select the action that should be performed upon the upgrade: "None" - disabled; "Block" - the upgrade process is blocked as there are insufficient resources on the VM node; "Migrate" - the upgrade process will be performed after previous migration of the VM to a server with sufficient free space';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['rightSection']['customconfigoption[loadBalancerStopOnUpgrade]']['customconfigoption[loadBalancerStopOnUpgrade]'] = 'Stop VM If Shutdown Fails';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['rightSection']['customconfigoption[loadBalancerStopOnUpgrade]']['customconfigoption[loadBalancerStopOnUpgrade]'] = 'Stop VM If Shutdown Fails';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['rightSection']['customconfigoption[loadBalancerStopOnUpgrade]']['tip'] = 'If enabled, the VM will be stopped in case the process of its shutting down fails';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['rightSection']['customconfigoption[loadBalancerStopOnUpgrade]']['tip'] = 'If enabled, the VM will be stopped in case the process of its shutting down fails';
@@ -497,7 +516,7 @@ $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[vga]']['tip'] = 'If you want to use high resolution modes (&gt;= 1280x1024x16), you should use the option \'std\' or \'vmware\'. The default one is \'std\' for Win8/Win7/w2k8, and \'cirrur\' for other OS types';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[vga]']['tip'] = 'If you want to use high resolution modes (&gt;= 1280x1024x16), you should use the option \'std\' or \'vmware\'. The default one is \'std\' for Win8/Win7/w2k8, and \'cirrur\' for other OS types';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[vgaMemory]']['customconfigoption[vgaMemory]'] = 'Graphic Card Memory';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[vgaMemory]']['customconfigoption[vgaMemory]'] = 'Graphic Card Memory';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[vgaMemory]']['tip'] = 'MiB';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[vgaMemory]']['tip'] = 'MiB';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[osTemplatesInAllNodes]']['customconfigoption[osTemplatesInAllNodes]'] = 'Search For Templates On All Nodes';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[osTemplatesInAllNodes]']['customconfigoption[osTemplatesInAllNodes]'] = 'Search for Templates on All Nodes';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[osTemplatesInAllNodes]']['tip'] = 'Enable searching for the reinstallation templates on all nodes';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[osTemplatesInAllNodes]']['tip'] = 'Enable searching for the reinstallation templates on all nodes';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['rightSection']['customconfigoption[acpi]']['customconfigoption[acpi]'] = 'ACPI';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['rightSection']['customconfigoption[acpi]']['customconfigoption[acpi]'] = 'ACPI';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['rightSection']['customconfigoption[acpi]']['tip'] = 'If enabled, ACPI will be used to send shutdown signals to the VM (QEMU/KVM)';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['rightSection']['customconfigoption[acpi]']['tip'] = 'If enabled, ACPI will be used to send shutdown signals to the VM (QEMU/KVM)';
@@ -521,7 +540,7 @@ $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['rightSection']['customconfigoption[cloneMode]']['tip'] = 'Select the clone type';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['rightSection']['customconfigoption[cloneMode]']['tip'] = 'Select the clone type';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[start]']['customconfigoption[start]'] = 'Start VM After Creation';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[start]']['customconfigoption[start]'] = 'Start VM After Creation';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[start]']['tip'] = 'If enabled, the VM will be started after it has been successfully created';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[start]']['tip'] = 'If enabled, the VM will be started after it has been successfully created';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['rightSection']['customconfigoption[cloneOnTheSameStorage]']['customconfigoption[cloneOnTheSameStorage]'] = 'Clone On The Same Storage As Source';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['rightSection']['customconfigoption[cloneOnTheSameStorage]']['customconfigoption[cloneOnTheSameStorage]'] = 'Clone on the Same Storage as Source';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['rightSection']['customconfigoption[cloneOnTheSameStorage]']['tip'] = 'Enable if you want VMs to be cloned on the same storage as the template.';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['rightSection']['customconfigoption[cloneOnTheSameStorage]']['tip'] = 'Enable if you want VMs to be cloned on the same storage as the template.';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[md-clear]']['customconfigoption[md-clear]'] = 'MD-CLEAR';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[md-clear]']['customconfigoption[md-clear]'] = 'MD-CLEAR';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[md-clear]']['tip'] = 'Required to let the guest OS know if MDS is mitigated correctly';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['configurationSection']['leftSection']['customconfigoption[md-clear]']['tip'] = 'Required to let the guest OS know if MDS is mitigated correctly';
@@ -604,13 +623,21 @@ $_LANG['serverAA']['configOptions']['cpu'] = 'CPU';
 $_LANG['serverAA']['configOptions']['memory'] = 'Memory';
 $_LANG['serverAA']['configOptions']['memory'] = 'Memory';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['leftSection']['customconfigoption[calculateSocketsAndCores]']['customconfigoption[calculateSocketsAndCores]'] = 'Calculate Sockets And Cores';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['leftSection']['customconfigoption[calculateSocketsAndCores]']['customconfigoption[calculateSocketsAndCores]'] = 'Calculate Sockets And Cores';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['leftSection']['customconfigoption[calculateSocketsAndCores]']['tip'] = 'Enable automatic calculations of sockets and cores';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['leftSection']['customconfigoption[calculateSocketsAndCores]']['tip'] = 'Enable automatic calculations of sockets and cores';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['leftSection']['customconfigoption[permissionBackupCompress][]']['customconfigoption[permissionBackupCompress][]'] = 'Backup Compression';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['leftSection']['customconfigoption[permissionBackupCompress][]']['description'] = 'Select the backup compression that should be available in the client area or leave blank to enable all.';
+$_LANG['LZO (fast)'] = 'LZO (fast)';
+$_LANG['GZIP (good)'] = 'GZIP (good)';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['rightSection']['customconfigoption[permissionArchive]']['customconfigoption[permissionArchive]'] = 'Archive';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['rightSection']['customconfigoption[permissionArchive]']['tip'] = 'Enable Archive';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['rightSection']['customconfigoption[archive][]']['customconfigoption[archive][]'] = 'Archives';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['clientAreaSection']['rightSection']['customconfigoption[archive][]']['tip'] = 'Select the archives that should be available in the client area';
 //Additional KVM Configuration
 //Additional KVM Configuration
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['advancedSection'] = 'Additional KVM Configuration';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['advancedSection'] = 'Additional KVM Configuration';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[balloon]']['customconfigoption[balloon]'] = 'Minimum RAM For VM [MiB]';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[balloon]']['customconfigoption[balloon]'] = 'Minimum RAM for VM [MiB]';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[balloon]']['tip'] = 'Enter zero to disable the balloon driver';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[balloon]']['tip'] = 'Enter zero to disable the balloon driver';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[args]']['customconfigoption[args]'] = 'Arguments';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[args]']['customconfigoption[args]'] = 'Arguments';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[args]']['tip'] = 'This option is for experts only. It allows you to pass arbitrary arguments to KVM, for example: -no-reboot -no-hpet.';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[args]']['tip'] = 'This option is for experts only. It allows you to pass arbitrary arguments to KVM, for example: -no-reboot -no-hpet.';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[migrate_speed]']['customconfigoption[migrate_speed]'] = 'Maximum Speed For Migrations [MB/s]';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[migrate_speed]']['customconfigoption[migrate_speed]'] = 'Maximum Speed for Migrations [MB/s]';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[migrate_speed]']['tip'] = 'Set the maximum speed in MB/s for migrations. Enter 0 to set no limits.';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[migrate_speed]']['tip'] = 'Set the maximum speed in MB/s for migrations. Enter 0 to set no limits.';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[startdate]']['customconfigoption[startdate]'] = 'Real Time Clock Initial Date';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[startdate]']['customconfigoption[startdate]'] = 'Real Time Clock Initial Date';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[startdate]']['tip'] = '(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS) >Set the initial date of the real time clock. Valid formats: \'now\' or \'2006-06-17T16:01:21\' or \'2006-06-17\'';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['advancedSection']['leftSection']['customconfigoption[startdate]']['tip'] = '(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS) >Set the initial date of the real time clock. Valid formats: \'now\' or \'2006-06-17T16:01:21\' or \'2006-06-17\'';
@@ -640,11 +667,11 @@ $_LANG['serverAA']['configOptions']['OVMF (UEFI)'] = 'OVMF (UEFI)';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['highAvailabilityClusterSection'] = 'High Availability Cluster';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['highAvailabilityClusterSection'] = 'High Availability Cluster';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['leftSection']['customconfigoption[clusterState]']['customconfigoption[clusterState]'] = 'State';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['leftSection']['customconfigoption[clusterState]']['customconfigoption[clusterState]'] = 'State';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['leftSection']['customconfigoption[clusterState]']['tip'] = 'Select the resource state, and the Cluster Resource Manager will act accordingly. Note that "Enabled" is just an alias for "started".';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['leftSection']['customconfigoption[clusterState]']['tip'] = 'Select the resource state, and the Cluster Resource Manager will act accordingly. Note that "Enabled" is just an alias for "started".';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['leftSection']['customconfigoption[clusterMaxRestart]']['customconfigoption[clusterMaxRestart]'] = 'Maximum Number Of Restarts';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['leftSection']['customconfigoption[clusterMaxRestart]']['customconfigoption[clusterMaxRestart]'] = 'Maximum Number of Restarts';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['leftSection']['customconfigoption[clusterMaxRestart]']['tip'] = 'Enter the maximum number of attempts to restart the service on a node when it has failed to start';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['leftSection']['customconfigoption[clusterMaxRestart]']['tip'] = 'Enter the maximum number of attempts to restart the service on a node when it has failed to start';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['rightSection']['customconfigoption[clusterGroup]']['customconfigoption[clusterGroup]'] = 'Group';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['rightSection']['customconfigoption[clusterGroup]']['customconfigoption[clusterGroup]'] = 'Group';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['rightSection']['customconfigoption[clusterGroup]']['tip'] = 'Select the HA group identifier';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['rightSection']['customconfigoption[clusterGroup]']['tip'] = 'Select the HA group identifier';
-$_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['rightSection']['customconfigoption[clusterMaxRelocate]']['customconfigoption[clusterMaxRelocate]'] = 'Maximum Number Of Relocations';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['rightSection']['customconfigoption[clusterMaxRelocate]']['customconfigoption[clusterMaxRelocate]'] = 'Maximum Number of Relocations';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['rightSection']['customconfigoption[clusterMaxRelocate]']['tip'] = 'Enter the maximum number of service relocation attempts when it has failed to start';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['highAvailabilityClusterSection']['rightSection']['customconfigoption[clusterMaxRelocate]']['tip'] = 'Enter the maximum number of service relocation attempts when it has failed to start';
 $_LANG['serverAA']['configOptions']['Started'] = 'Started';
 $_LANG['serverAA']['configOptions']['Started'] = 'Started';
 $_LANG['serverAA']['configOptions']['Stopped'] = 'Stopped';
 $_LANG['serverAA']['configOptions']['Stopped'] = 'Stopped';
@@ -914,6 +941,12 @@ $_LANG['serverAA']['product']['mainContainer']['mainForm']['cpuPrioritySection']
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cpuPrioritySection']['rightSection']['customconfigoption[cpulimitPriority4]']['tip'] = 'Provide High CPU Limit';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cpuPrioritySection']['rightSection']['customconfigoption[cpulimitPriority4]']['tip'] = 'Provide High CPU Limit';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cpuPrioritySection']['rightSection']['customconfigoption[cpulimitPriority5]']['customconfigoption[cpulimitPriority5]'] = 'Very High CPU Limit';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cpuPrioritySection']['rightSection']['customconfigoption[cpulimitPriority5]']['customconfigoption[cpulimitPriority5]'] = 'Very High CPU Limit';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cpuPrioritySection']['rightSection']['customconfigoption[cpulimitPriority5]']['tip'] = 'Provide Very High CPU Limit';
 $_LANG['serverAA']['product']['mainContainer']['mainForm']['cpuPrioritySection']['rightSection']['customconfigoption[cpulimitPriority5]']['tip'] = 'Provide Very High CPU Limit';
+
+$_LANG['serverAA']['adminServicesTabFields']['migrateModal']['migrateForm']['with-local-disks']['with-local-disks'] = 'Migration With Local Disks';
+$_LANG['serverAA']['adminServicesTabFields']['migrateModal']['migrateForm']['with-local-disks']['tip'] = 'Migration with local disks might take a while.';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['rightSection']['customconfigoption[loadBalancerMigrationWithLocalDisks]']['customconfigoption[loadBalancerMigrationWithLocalDisks]'] = 'Migration With Local Disks';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['rightSection']['customconfigoption[loadBalancerMigrationWithLocalDisks]']['tip'] = 'Run migration with local disks';
+
 /* * ********************************************************************************************************************
 /* * ********************************************************************************************************************
  *                                                    Templates                                                      *
  *                                                    Templates                                                      *
  * ******************************************************************************************************************** */
  * ******************************************************************************************************************** */
@@ -923,6 +956,7 @@ $_LANG['template']['Debian 9.0 Standard 9.7 1 Amd64'] = 'Debian 9.0 Standard 9.7
 $_LANG['template']['VM 9000'] = 'Ubuntu';
 $_LANG['template']['VM 9000'] = 'Ubuntu';
 $_LANG['template']['Installation From ISO Image']='Installation From ISO Image';
 $_LANG['template']['Installation From ISO Image']='Installation From ISO Image';
 $_LANG['template']['installationFromIso']='Installation From ISO Image';
 $_LANG['template']['installationFromIso']='Installation From ISO Image';
+$_LANG['template']['InstallationFromArchive']='Installation From Archive';
 $_LANG['template_desc']['Template contains  Ubuntu Server 18.04 LTS (Bionic Beaver) daily builds'] ='Template contains  Ubuntu Server 18.04 LTS (Bionic Beaver) daily builds';
 $_LANG['template_desc']['Template contains  Ubuntu Server 18.04 LTS (Bionic Beaver) daily builds'] ='Template contains  Ubuntu Server 18.04 LTS (Bionic Beaver) daily builds';
 //Virtual Machines
 //Virtual Machines
 $_LANG['serverAA']['home']['mainContainer']['dataTable']['table']['vmid'] = 'VMID';
 $_LANG['serverAA']['home']['mainContainer']['dataTable']['table']['vmid'] = 'VMID';
@@ -950,6 +984,7 @@ $_LANG['serverAA']['home']['mainContainer']['ipAddressDataTable']['table']['mac_
 $_LANG['serverAA']['home']['mainContainer']['ipAddressDataTable']['table']['subnet_mask'] = 'Subnet Mask';
 $_LANG['serverAA']['home']['mainContainer']['ipAddressDataTable']['table']['subnet_mask'] = 'Subnet Mask';
 $_LANG['serverAA']['home']['mainContainer']['ipAddressDataTable']['table']['gateway'] = 'Gateway';
 $_LANG['serverAA']['home']['mainContainer']['ipAddressDataTable']['table']['gateway'] = 'Gateway';
 $_LANG['serverAA']['home']['mainContainer']['ipAddressDataTable']['deleteButton']['button']['deleteButton'] = 'Delete';
 $_LANG['serverAA']['home']['mainContainer']['ipAddressDataTable']['deleteButton']['button']['deleteButton'] = 'Delete';
+$_LANG['serverAA']['home']['mainContainer']['dataTable']['table']['node'] = 'Node';
 //delete ip address
 //delete ip address
 $_LANG['serverAA']['adminServicesTabFields']['deleteModal']['modal']['deleteModal'] = 'Delete IP Address';
 $_LANG['serverAA']['adminServicesTabFields']['deleteModal']['modal']['deleteModal'] = 'Delete IP Address';
 $_LANG['serverAA']['adminServicesTabFields']['deleteModal']['deleteForm']['confirmDelete'] = 'Are you sure that you want to delete the :ip: IP address?';
 $_LANG['serverAA']['adminServicesTabFields']['deleteModal']['deleteForm']['confirmDelete'] = 'Are you sure that you want to delete the :ip: IP address?';
@@ -1101,7 +1136,7 @@ $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['gene
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['memory']['memory'] = 'VM RAM [MiB]';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['memory']['memory'] = 'VM RAM [MiB]';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['memory']['description'] = 'Enter the default RAM size of the VM';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['memory']['description'] = 'Enter the default RAM size of the VM';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['disk']['disk'] = 'Disk Size [GB]';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['disk']['disk'] = 'Disk Size [GB]';
-$_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['disk']['description'] = 'Enter the default storage size [GB]';
+$_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['disk']['description'] = 'Enter the default storage size [GB], please enter integres only, without values after comma ';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['searchdomain']['searchdomain'] = 'Search Domain';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['searchdomain']['searchdomain'] = 'Search Domain';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['searchdomain']['description'] = 'Enter a domains name for search';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['searchdomain']['description'] = 'Enter a domains name for search';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['nameserver[0]']['nameserver[0]'] = 'Name Server';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['nameserver[0]']['nameserver[0]'] = 'Name Server';
@@ -1113,6 +1148,8 @@ $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['gene
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['sshkeys']['sshkeys'] = 'SSH Key';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['sshkeys']['sshkeys'] = 'SSH Key';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['sshkeys']['description'] = 'Enter a SSH key';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['sshkeys']['description'] = 'Enter a SSH key';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['baseSubmitButton']['button']['submit'] = 'Save Changes';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['baseSubmitButton']['button']['submit'] = 'Save Changes';
+$_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['archive']['archive'] = 'Archive';
+$_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['archive']['desciption'] = 'Select archive ';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netdisk']['virtualNetworkSection']['virtualNetworkSection']        = 'Virtual Networks'   ;
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netdisk']['virtualNetworkSection']['virtualNetworkSection']        = 'Virtual Networks'   ;
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netdisk']['virtualNetworkSection']['Add New Virtual Network']='Add New Virtual Network';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netdisk']['virtualNetworkSection']['Add New Virtual Network']='Add New Virtual Network';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netdisk']['virtualNetworkSection']['Virtual Network']='Virtual Network';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netdisk']['virtualNetworkSection']['Virtual Network']='Virtual Network';
@@ -1128,7 +1165,7 @@ $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netd
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netdisk']['additionalDiskSection']['additionalDiskBackup']['additionalDiskBackup'] = 'Backup';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netdisk']['additionalDiskSection']['additionalDiskBackup']['additionalDiskBackup'] = 'Backup';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netdisk']['additionalDiskSection']['additional_disk_add_info'] = 'Click on blue button to add additional disk';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netdisk']['additionalDiskSection']['additional_disk_add_info'] = 'Click on blue button to add additional disk';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['swap']['swap'] ='SWAP';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['swap']['swap'] ='SWAP';
-$_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['swap']['description']='SWAP';
+$_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['swap']['description']='Allows the container to use additional swap memory from the host swap space. This corresponds to the memory.memsw.limit_in_bytes cgroup setting, which is set to the sum of both value (memory + swap)';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['cloudInitScript']['cloudInitScript']= 'Cloud-Init Script';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['cloudInitScript']['cloudInitScript']= 'Cloud-Init Script';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['cloudInitScript']['description'] = 'Select Cloud-Init Script ';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['cloudInitScript']['description'] = 'Select Cloud-Init Script ';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netdisk']['additionalDiskSection']['additionalDiskMp']['additionalDiskMp'] ='Path';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['netdisk']['additionalDiskSection']['additionalDiskMp']['additionalDiskMp'] ='Path';
@@ -1143,6 +1180,14 @@ $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['isoDataTable'] = 'ISO I
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['dataTable']['Select the template for reinstallation. If you proceed, all data located on the virtual machine will be lost.'] = 'Select the template for reinstallation. If you proceed, all data located on the virtual machine will be lost.';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['dataTable']['Select the template for reinstallation. If you proceed, all data located on the virtual machine will be lost.'] = 'Select the template for reinstallation. If you proceed, all data located on the virtual machine will be lost.';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['dataTable']['table']['name'] = 'Name';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['dataTable']['table']['name'] = 'Name';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['dataTable']['isoInstallButton']['button']['isoInstallButton'] = 'Install';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['dataTable']['isoInstallButton']['button']['isoInstallButton'] = 'Install';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['detailTab']['baseStandaloneFormExtSections']['generalSection']['ipv4']['ipv4'] = 'IPv4 Addresses';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['detailTab']['baseStandaloneFormExtSections']['generalSection']['ipv4']['description'] = 'Number of IPv4 addresses for VM';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['detailTab']['baseStandaloneFormExtSections']['generalSection']['ipv6']['ipv6'] = 'IPv6 Addresses';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['detailTab']['baseStandaloneFormExtSections']['generalSection']['ipv6']['description'] = 'Number of IPv6 addresses for VM';
+$_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['ipv4']['ipv4'] = 'IPv4 Addresses';
+$_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['ipv4']['description'] = 'Number of IPv4 addresses for VM';
+$_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['ipv6']['ipv6'] = 'IPv6 Addresses';
+$_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['ipv6']['description'] = 'Number of IPv6 addresses for VM';
 $_LANG['Enable'] = 'Enable';
 $_LANG['Enable'] = 'Enable';
 $_LANG['Disable'] = 'Disable';
 $_LANG['Disable'] = 'Disable';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['cpuPriority']['cpuPriority'] = 'CPU Priority';
 $_LANG['serverCA']['vm']['mainContainer']['baseStandaloneFormExtSections']['generalSection']['cpuPriority']['cpuPriority'] = 'CPU Priority';
@@ -1312,7 +1357,7 @@ $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['diskDataTable']['table'
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['diskDataTable']['table']['bytes'] = 'Size';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['diskDataTable']['table']['bytes'] = 'Size';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['diskDataTable']['updateDiskButton']['button']['updateDiskButton'] = 'Edit';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['diskDataTable']['updateDiskButton']['button']['updateDiskButton'] = 'Edit';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['diskDataTable']['deleteDiskButton']['button']['deleteDiskButton'] = 'Delete';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['diskDataTable']['deleteDiskButton']['button']['deleteDiskButton'] = 'Delete';
-$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['detailTab']['baseStandaloneFormExtSections']['generalSection']['swap']['description'] = 'generalSection swap description';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['detailTab']['baseStandaloneFormExtSections']['generalSection']['swap']['description'] = 'Allows the container to use additional swap memory from the host swap space. This corresponds to the memory.memsw.limit_in_bytes cgroup setting, which is set to the sum of both value (memory + swap)';
 $_LANG['Disk :id:'] = 'Disk :id:';
 $_LANG['Disk :id:'] = 'Disk :id:';
 //MP
 //MP
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['mountPointDataTable']['Adding, editing or removing disk will reboot the virtual machine.'] = 'Adding, editing or removing disk will reboot the virtual machine.';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['mountPointDataTable']['Adding, editing or removing disk will reboot the virtual machine.'] = 'Adding, editing or removing disk will reboot the virtual machine.';
@@ -1394,6 +1439,8 @@ $_LANG['serverCA']['vm']['createVirtualInterfaceModal']['createForm']['vn_id']['
 $_LANG['serverCA']['vm']['createVirtualInterfaceModal']['createForm']['ip']['ip'] = 'Select IP Address';
 $_LANG['serverCA']['vm']['createVirtualInterfaceModal']['createForm']['ip']['ip'] = 'Select IP Address';
 $_LANG['serverCA']['vm']['createVirtualInterfaceModal']['baseAcceptButton']['title'] = 'Add';
 $_LANG['serverCA']['vm']['createVirtualInterfaceModal']['baseAcceptButton']['title'] = 'Add';
 $_LANG['serverCA']['vm']['createVirtualInterfaceModal']['baseCancelButton']['title'] = 'Cancel';
 $_LANG['serverCA']['vm']['createVirtualInterfaceModal']['baseCancelButton']['title'] = 'Cancel';
+$_LANG['Select the Virtual Network'] = 'Select the Virtual Network';
+$_LANG['You are not able to set :virtual_interfaces: of the virtual inferfaces. The  available virtual interfec is: :max:'] = 'You are not able to set :virtual_interfaces: of the virtual interfaces. The available number of virtual interfaces is: :max:';
 //delete
 //delete
 $_LANG['serverCA']['vm']['deletevirtualInterfaceModal']['modal']['deletevirtualInterfaceModal'] = 'Delete Virtual Network';
 $_LANG['serverCA']['vm']['deletevirtualInterfaceModal']['modal']['deletevirtualInterfaceModal'] = 'Delete Virtual Network';
 $_LANG['serverCA']['vm']['deletevirtualInterfaceModal']['deleteForm']['confirmDelete'] = 'Are you sure that you want to remove this virtual network?';
 $_LANG['serverCA']['vm']['deletevirtualInterfaceModal']['deleteForm']['confirmDelete'] = 'Are you sure that you want to remove this virtual network?';
@@ -1448,6 +1495,89 @@ $_LANG['serverCA']['vm']['deleteMassModal']['deleteMassForm']['confirmDeleteMass
 $_LANG['serverCA']['vm']['deleteMassModal']['baseAcceptButton']['title'] = 'Confirm';
 $_LANG['serverCA']['vm']['deleteMassModal']['baseAcceptButton']['title'] = 'Confirm';
 $_LANG['serverCA']['vm']['deleteMassModal']['baseCancelButton']['title']  = 'Cancel';
 $_LANG['serverCA']['vm']['deleteMassModal']['baseCancelButton']['title']  = 'Cancel';
 $_LANG['The snapshots have been deleted successfully'] = 'The selected snapshots have been deleted successfully';
 $_LANG['The snapshots have been deleted successfully'] = 'The selected snapshots have been deleted successfully';
+//snapshot jobs
+
+
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTabTitle'] = 'Snapshots';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['snapshotTabTitle'] = 'Snapshots';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['snapshotDataTable'] = 'Snapshots';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['jobDataTable'] = 'Jobs';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['createSnapshotButton']['button']['createSnapshotButton'] = 'Take Snapshot';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['deleteMassButton']['button']['deleteMassButton'] = 'Delete';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['table']['status'] = 'Status';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['table']['vmstate'] = 'RAM';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['table']['snaptime'] = 'Data/Status';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['table']['description'] = 'Description';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['rollbackButton ']['button']['rollbackButton'] = 'Rollback';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['updateButton']['button']['updateButton'] = 'Edit';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['deleteButton']['button']['deleteButton'] = 'Delete';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['createJobButton']['button']['createJobButton'] = 'New Job';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['deleteJobMassButton']['button']['deleteJobMassButton'] = 'Delete';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['table']['days'] = 'Days';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['table']['created_at'] = 'Created At';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['updateJobButton']['button']['updateJobButton'] = 'Edit';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['deleteJobButton']['button']['deleteJobButton'] = 'Delete';
+$_LANG['serverCA']['vm']['The maximum number of snapshot jobs has been exceeded. Please remove the old snapshot jobs.'] = 'The maximum number of snapshot jobs has been exceeded. Please remove the old snapshot jobs.';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['snapshotTab']['dataTable']['table']['name'] = 'Name';
+$_LANG['serverCA']['vm']['Your snapshot limit is :snapshotFilesLimit:. When you exceed this limit, the last snapshot will be replaced with a new one.'] = 'Your snapshot limit is :snapshotFilesLimit:. When you exceed this limit, the last snapshot will be replaced with a new one.';
+$_LANG['serverCA']['vm']['hourly'] = 'Hourly';
+$_LANG['serverCA']['vm']['daily'] = 'Daily';
+$_LANG['serverCA']['vm']['Monday'] = 'Monday';
+$_LANG['serverCA']['vm']['Tuesday'] = 'Tuesday';
+$_LANG['serverCA']['vm']['Wednesday'] = 'Wednesday';
+$_LANG['serverCA']['vm']['Thursday'] = 'Thursday';
+$_LANG['serverCA']['vm']['Friday'] = 'Friday';
+$_LANG['serverCA']['vm']['Saturday'] = 'Saturday';
+$_LANG['serverCA']['vm']['Sunday'] = 'Sunday';
+$_LANG['serverCA']['vm']['createJobModal']['hourly'] = 'Hourly';
+$_LANG['serverCA']['vm']['createJobModal']['daily'] = 'Daily';
+$_LANG['serverCA']['vm']['createJobModal']['Monday'] = 'Monday';
+$_LANG['serverCA']['vm']['createJobModal']['Tuesday'] = 'Tuesday';
+$_LANG['serverCA']['vm']['createJobModal']['Wednesday'] = 'Wednesday';
+$_LANG['serverCA']['vm']['createJobModal']['Thursday'] = 'Thursday';
+$_LANG['serverCA']['vm']['createJobModal']['Friday'] = 'Friday';
+$_LANG['serverCA']['vm']['createJobModal']['Saturday'] = 'Saturday';
+$_LANG['serverCA']['vm']['createJobModal']['Sunday'] = 'Sunday';
+$_LANG['serverCA']['vm']['createJobModal']['createJobForm']['days']['days'] = 'Days';
+$_LANG['serverCA']['vm']['createJobModal']['createJobForm']['start_time']['start_time'] = 'Start Time';
+$_LANG['serverCA']['vm']['createJobModal']['modal']['createJobModal'] = 'New Snapshot Job';
+$_LANG['serverCA']['vm']['createJobModal']['createJobForm']['period']['period'] = 'Period';
+$_LANG['serverCA']['vm']['createJobModal']['createJobForm']['run_every']['run_every'] = 'Run Every';
+$_LANG['serverCA']['vm']['createJobModal']['createJobForm']['name']['name'] = 'Name';
+$_LANG['serverCA']['vm']['createJobModal']['createJobForm']['vmstate']['vmstate'] = 'Include RAM';
+$_LANG['serverCA']['vm']['createJobModal']['createJobForm']['description']['description'] = 'Description';
+$_LANG['serverCA']['vm']['createJobModal']['baseAcceptButton']['title'] = 'Confirm';
+$_LANG['serverCA']['vm']['createJobModal']['baseCancelButton']['title'] = 'Cancel';
+//update
+$_LANG['serverCA']['vm']['updateJobModal']['modal']['updateJobModal'] = 'Edit Snapshot Job';
+$_LANG['serverCA']['vm']['updateJobModal']['updateJobForm']['days']['days'] = 'Days';
+$_LANG['serverCA']['vm']['updateJobModal']['updateJobForm']['start_time']['start_time'] = 'Start Time';
+$_LANG['serverCA']['vm']['updateJobModal']['updateJobForm']['period']['period'] = 'Period';
+$_LANG['serverCA']['vm']['updateJobModal']['updateJobForm']['run_every']['run_every'] = 'Run Every';
+$_LANG['serverCA']['vm']['updateJobModal']['updateJobForm']['name']['name'] = 'Name';
+$_LANG['serverCA']['vm']['updateJobModal']['updateJobForm']['vmstate']['vmstate'] = 'Include RAM';
+$_LANG['serverCA']['vm']['updateJobModal']['updateJobForm']['description']['description'] = 'Description';
+$_LANG['serverCA']['vm']['updateJobModal']['baseAcceptButton']['title'] = 'Save Changes';
+$_LANG['serverCA']['vm']['updateJobModal']['baseCancelButton']['title'] = 'Cancel';
+$_LANG['serverCA']['vm']['Every :run_every: hour']='Every :run_every: hour';
+$_LANG['serverCA']['vm']['Every :run_every: hours']='Every :run_every: hours';
+//delete
+$_LANG['serverCA']['vm']['deleteJobModal']['modal']['deleteJobModal'] = 'Delete Snapshot Job';
+$_LANG['serverCA']['vm']['deleteJobModal']['deleteJobForm']['conforimJobDelete'] = 'Are you sure that you want to delete the :name: snapshot job?';
+$_LANG['serverCA']['vm']['deleteJobModal']['baseAcceptButton']['title'] =  'Confirm';
+$_LANG['serverCA']['vm']['deleteJobModal']['baseCancelButton']['title'] = 'Cancel';
+//delete mass
+$_LANG['serverCA']['vm']['deleteJobMassModal']['modal']['deleteJobMassModal'] = 'Delete Jobs';
+$_LANG['serverCA']['vm']['deleteJobMassModal']['deleteJobMassForm']['confirmDeleteJobMass']  = 'Are you sure that you want to delete the selected snapshot jobs?';
+$_LANG['serverCA']['vm']['deleteJobMassModal']['baseAcceptButton']['title'] =  'Confirm';
+$_LANG['serverCA']['vm']['deleteJobMassModal']['baseCancelButton']['title'] =  'Cancel';
+//messages
+$_LANG['Snapshot Job :name: has been created successfully']='Snapshot Job :name: has been created successfully';
+$_LANG['Snapshot Job :name: has updated successfully']='Snapshot Job :name: has updated successfully';
+$_LANG['Snapshot Job :name: has been deleted successfully']='Snapshot Job :name: has been deleted successfully';
+$_LANG['The selected snapshot jobs have been deleted successfully']='The selected snapshot jobs have been deleted successfully';
+
+$_LANG['serverCA']['vm']['Every :run_every: hours']='Every :run_every: hour';
 /**********************************************************************************************************************
 /**********************************************************************************************************************
  *                                                 VM Backups                                          *
  *                                                 VM Backups                                          *
  ********************************************************************************************************************* */
  ********************************************************************************************************************* */
@@ -1544,6 +1674,10 @@ $_LANG['serverCA']['vm']['deleteBackupJobModal']['deleteForm']['confirmDelete']
 $_LANG['serverCA']['vm']['deleteBackupJobModal']['baseAcceptButton']['title'] = 'Confirm';
 $_LANG['serverCA']['vm']['deleteBackupJobModal']['baseAcceptButton']['title'] = 'Confirm';
 $_LANG['serverCA']['vm']['deleteBackupJobModal']['baseCancelButton']['title'] = 'Cancel';
 $_LANG['serverCA']['vm']['deleteBackupJobModal']['baseCancelButton']['title'] = 'Cancel';
 $_LANG['The backup job has been deleted successfully'] = 'The backup job has been deleted successfully';
 $_LANG['The backup job has been deleted successfully'] = 'The backup job has been deleted successfully';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['backupTabName']['resourcesContainer'] = 'Available Resources';
+$_LANG['serverCA']['vm']['backupSize'] = 'Backup Size:';
+$_LANG['serverCA']['vm']['backupFiles']= 'Backup Files:';
+$_LANG['The maximum number of backup files has been exceeded. Please remove the old backup files.'] = 'The maximum number of backup files has been exceeded. Please remove the old backup files.';
 /**********************************************************************************************************************
 /**********************************************************************************************************************
  *                                                 VM Firewall                                         *
  *                                                 VM Firewall                                         *
  ********************************************************************************************************************* */
  ********************************************************************************************************************* */
@@ -1561,6 +1695,9 @@ $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['dataTabl
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['dataTable']['table']['comment'] = 'Comment';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['dataTable']['table']['comment'] = 'Comment';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['dataTable']['updateButton']['button']['updateButton'] = 'Update';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['dataTable']['updateButton']['button']['updateButton'] = 'Update';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['dataTable']['deleteButton']['button']['deleteButton'] = 'Delete';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['dataTable']['deleteButton']['button']['deleteButton'] = 'Delete';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['firewallDataTable']['table']['pos'] = 'Position';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['firewallDataTable']['upRuleButton']['button']['upRuleButton'] = 'Move Up';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['firewallDataTable']['downRuleButton']['button']['downRuleButton'] = 'Move Down';
 //options
 //options
 $_LANG['serverCA']['vm']['log_level_in'] = 'Log Level In';
 $_LANG['serverCA']['vm']['log_level_in'] = 'Log Level In';
 $_LANG['serverCA']['vm']['log_level_out'] = 'Log Level Out';
 $_LANG['serverCA']['vm']['log_level_out'] = 'Log Level Out';
@@ -1613,6 +1750,15 @@ $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['firewall
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['firewallDataTable']['table']['comment'] = 'Comment';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['firewallDataTable']['table']['comment'] = 'Comment';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['firewallDataTable']['updateButton']['button']['updateButton'] = 'Edit';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['firewallDataTable']['updateButton']['button']['updateButton'] = 'Edit';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['firewallDataTable']['deleteButton']['button']['deleteButton'] = 'Delete';
 $_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['firewallDataTable']['deleteButton']['button']['deleteButton'] = 'Delete';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['firewallDataTable']['buttonBase']['downloadButton']['button']['downloadButton'] = 'Download Rules';
+$_LANG['serverCA']['vm']['mainContainer']['tabsWidget']['firewallTab']['firewallDataTable']['buttonBase']['restoreButton']['button']['restoreButton'] = 'Restore Rules';
+$_LANG['serverCA']['vm']['restoreModal']['modal']['restoreModal'] = 'Restore Firewall Rules';
+$_LANG['serverCA']['vm']['restoreModal']['restoreForm']['rules']['rules'] = 'Backup File';
+$_LANG['serverCA']['vm']['restoreModal']['baseAcceptButton']['title'] = 'Save Changes';
+$_LANG['serverCA']['vm']['restoreModal']['baseCancelButton']['title'] = 'Cancel';
+$_LANG['The file with firewall rules is empty or invalid']= 'The file with firewall rules is empty or invalid';
+$_LANG['The firewall rules have been restored successfully'] = 'The firewall rules have been restored successfully';
+$_LANG['errorCodeMessage']['The maximum number of firewall rules has been exceeded. Please remove the old firewall rules.'] ='The maximum number of firewall rules has been exceeded. Please remove the old firewall rules.';
 //create
 //create
 $_LANG['serverCA']['vm']['venet'] = 'Venet';
 $_LANG['serverCA']['vm']['venet'] = 'Venet';
 $_LANG['serverCA']['vm']['Microsoft Remote Desktop Protocol traffic'] = 'Microsoft Remote Desktop Protocol traffic';
 $_LANG['serverCA']['vm']['Microsoft Remote Desktop Protocol traffic'] = 'Microsoft Remote Desktop Protocol traffic';
@@ -1908,3 +2054,10 @@ $_LANG['serverCA']['customTemplate']['deleteModal']['deleteForm']['confirmDelete
 $_LANG['serverCA']['customTemplate']['deleteModal']['baseAcceptButton']['title'] = 'Confirm';
 $_LANG['serverCA']['customTemplate']['deleteModal']['baseAcceptButton']['title'] = 'Confirm';
 $_LANG['serverCA']['customTemplate']['deleteModal']['baseCancelButton']['title'] = 'Cancel';
 $_LANG['serverCA']['customTemplate']['deleteModal']['baseCancelButton']['title'] = 'Cancel';
 $_LANG['The Template has been deleted successfully']='The selected template has been deleted successfully';
 $_LANG['The Template has been deleted successfully']='The selected template has been deleted successfully';
+$_LANG['VM not running']='VM not running';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['leftSection']['customconfigoption[serverGroup][]']['customconfigoption[serverGroup][]'] = 'Group';
+$_LANG['serverAA']['product']['mainContainer']['mainForm']['loadBalancerSection']['leftSection']['customconfigoption[serverGroup][]']['tip'] = 'Select a preferred group or groups of nodes. If you do not have any groups created, proceed to Proxmox Addon -> Servers List -> Details ->Node Groups and add a new group.';
+$_LANG['gb'] = 'GB';
+$_LANG['tb'] = 'TB';
+$_LANG['serverCA']['vm']['OpenPGP HTTP key server protocol traffic'] = 'OpenPGP HTTP key server protocol traffic';
+$_LANG['serverCA']['vm']['Ceph Storage Cluster traffic (Ceph Monitors, OSD & MDS Daemons)'] = 'Ceph Storage Cluster traffic (Ceph Monitors, OSD & MDS Daemons)';

+ 2 - 2
logo.png


+ 4 - 1
packages/Provisioning/Config/PackageConfiguration.php

@@ -360,4 +360,7 @@
 #layers .selectize-control.single .selectize-dropdown.single .option {
 #layers .selectize-control.single .selectize-dropdown.single .option {
     white-space: normal;
     white-space: normal;
 }
 }
-/* end of add multiline for long selectize option values(dropdown)*/
+/* end of add multiline for long selectize option values(dropdown)*/
+form[name='frm2'] .selectize-control {
+    height: inherit!important;
+}

+ 1 - 1
templates/admin/assets/fonts/icons/Material-Design-Iconic-Font.eot

@@ -24553,6 +24553,6 @@ table.lu-dataTable {
     width: 56px;
     width: 56px;
     border-width: 4px;
     border-width: 4px;
 }
 }
-#layers .table.dataTable>thead .sorting:before, table.dataTable>thead .sorting_asc:before, table.dataTable>thead .sorting_asc_disabled:before, table.dataTable>thead .sorting_desc:before, table.dataTable>thead .sorting_desc_disabled:before {
+#layers .lu-table.dataTable>thead .sorting:before, table.dataTable>thead .sorting_asc:before, table.dataTable>thead .sorting_asc_disabled:before, table.dataTable>thead .sorting_desc:before, table.dataTable>thead .sorting_desc_disabled:before {
   content: "" !important;
   content: "" !important;
 }
 }

+ 9 - 3
templates/client/default/assets/css/mg_styles.css

@@ -465,7 +465,7 @@ var mgDefauleVueObject = {
                         console.log('Action Failed');
                         console.log('Action Failed');
                     }
                     }
                 },
                 },
-                ajaxAction : function(event, targetId, namespace, index, postData) {
+                ajaxAction : function(event, targetId, namespace, index, postData, addSpinner=false) {
                     var self = this;
                     var self = this;
                     self.refreshUrl();
                     self.refreshUrl();
                     self.initRefreshActions(event, targetId);
                     self.initRefreshActions(event, targetId);
@@ -474,8 +474,14 @@ var mgDefauleVueObject = {
                     self.addUrlComponent('index', index);
                     self.addUrlComponent('index', index);
                     self.getActionId(event);
                     self.getActionId(event);
                     self.addUrlComponent('ajax', '1');
                     self.addUrlComponent('ajax', '1');
+                    if (addSpinner) {
+                        self.showSpinner(event);
+                    }
                     $.post(self.targetUrl, postData)
                     $.post(self.targetUrl, postData)
                         .done(function( data ) {
                         .done(function( data ) {
+                            if (addSpinner) {
+                                self.hideSpinner(event);
+                            }
                             data = data.data;
                             data = data.data;
                             self.addAlert(data.status, data.message);
                             self.addAlert(data.status, data.message);
                             self.$nextTick(function() {
                             self.$nextTick(function() {
@@ -483,8 +489,8 @@ var mgDefauleVueObject = {
                                     window[data.callBackFunction](data, targetId, event);
                                     window[data.callBackFunction](data, targetId, event);
                                 }
                                 }
                             });
                             });
-                            if(data.status === 'success'){
-
+                            if(data.status === 'success'  &&  data.refreshIds !== undefined ){
+                                self.runRefreshActions((data && typeof data.refreshIds !== undefined) ? data.refreshIds : null, data);
                             }
                             }
                     }, 'json');
                     }, 'json');
                     self.refreshUrl();               
                     self.refreshUrl();               

+ 3 - 1
templates/client/default/assets/js/defaultComponents/ajaxFieldForDataTable.js

@@ -92,7 +92,6 @@ mgJsComponentHandler.addDefaultComponent('mg-datatable', {
             }
             }
         },
         },
         updateProjects: function(){
         updateProjects: function(){
-            console.log('Update!');
             this.loaded = true;
             this.loaded = true;
             if (this.searchEnabled === false) {
             if (this.searchEnabled === false) {
                 return;
                 return;
@@ -305,6 +304,9 @@ mgJsComponentHandler.addDefaultComponent('mg-datatable', {
         },
         },
         getFilters: function () {
         getFilters: function () {
             return this.$store.getters.getComponentData(this.component_id, 'filters');
             return this.$store.getters.getComponentData(this.component_id, 'filters');
+        },
+        buttonAction: function(event, targetId){
+            mgPageControler.vueLoader.ajaxAction(event, targetId, getItemNamespace(targetId), getItemIndex(targetId),null,true);
         }
         }
     }
     }
 });
 });

+ 36 - 0
templates/client/default/assets/js/defaultComponents/dataTableSelectFilter.js

@@ -0,0 +1,36 @@
+{**********************************************************************
+* ProxmoxVps product developed. (2017-10-30)
+* *
+*
+*  CREATED BY MODULESGARDEN       ->       http://modulesgarden.com
+*  CONTACT                        ->       contact@modulesgarden.com
+*
+*
+* This software is furnished under a license and may be used and copied
+* only  in  accordance  with  the  terms  of such  license and with the
+* inclusion of the above copyright notice.  This software  or any other
+* copies 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-form-group">
+    <label class="lu-form-label">
+        {if $rawObject->isRawTitle()}{$rawObject->getRawTitle()}{elseif $rawObject->getTitle()}{$MGLANG->T($rawObject->getTitle())}{/if}
+        {if $rawObject->getDescription()}
+            <i data-title="{$MGLANG->T($rawObject->getDescription())}" data-toggle="lu-tooltip" class="lu-i-c-2x lu-zmdi lu-zmdi-help-outline lu-form-tooltip-helper"></i>
+        {/if}
+    </label>
+    <input class="lu-form-control" type="file" placeholder="{$rawObject->getPlaceholder()}" name="{$rawObject->getName()}"
+           id="{$rawObject->getId()}"
+           value="{$rawObject->getValue()}" {if $rawObject->isDisabled()}disabled="disabled"{/if}
+           {foreach $htmlAttributes as $aValue} {$aValue@key}="{$aValue}" {/foreach}>
+    <div class="lu-form-feedback lu-form-feedback--icon" hidden="hidden">
+    </div>    
+</div>

+ 2 - 2
templates/client/default/ui/core/default/widget/forms/fields/hidden.tpl

@@ -5,10 +5,10 @@
   "license": "proprietary",
   "license": "proprietary",
   "category": "provisioning",
   "category": "provisioning",
   "description": {
   "description": {
-    "name": "Proxmox Cloud VPS",
+    "name": "Proxmox VE Cloud  VPS",
     "tagline": "Grant your clients permission to create and modify multiple virtual servers plus enable them to manage all server components remotely.",
     "tagline": "Grant your clients permission to create and modify multiple virtual servers plus enable them to manage all server components remotely.",
     "short": "Grant your clients permission to create and modify multiple virtual servers plus enable them to manage all server components remotely.",
     "short": "Grant your clients permission to create and modify multiple virtual servers plus enable them to manage all server components remotely.",
-    "long": "Proxmox Cloud VPS For WHMCS enables your customers to create and manage multiple virtual servers at virtual data centers in your WHMCS. You simply set the resource limits as ready products, and offer them to your clients who can then create any number of servers within the purchased limit. In the client area, where the real magic of Proxmox Cloud VPS For WHMCS happens, your customers can find all essential tools to freely create, modify and remove virtual machines. With the same set of resources, they will be able to create either one powerful server, or multiple smaller ones - the way resources are used is entirely up to a client, restricted only by the limits of products you offer. Along with it, your customers will be granted permission to manage private networks, backups and firewall, access noVNC, SPICE, or Xterm.js console, as well as inspect usage graphs and statistics - all these directly on your website. Another detail to be valued highly is support for Cloud-Init for the KVM virtualization type, providing utilities for early initialization of your cloud instances. What is more, the module includes an amazing Proxmox Addon owing to which you can carefully handle your servers, IP addresses and clusters. Eager to bring even greater automation into your business? You can boost the module's potential with Proxmox Cloud VPS Autoscaling For WHMCS to introduce a completely automated mechanism of servers' resizing and cloning adjusted to their current load."
+    "long": "Proxmox VE Cloud VPS For WHMCS enables your customers to create and manage multiple virtual servers at virtual data centers in your WHMCS. You simply set the resource limits as ready products, and offer them to your clients who can then create any number of servers within the purchased limit. In the client area, where the real magic of Proxmox VE Cloud VPS For WHMCS happens, your customers can find all essential tools to freely create, modify and remove virtual machines. With the same set of resources, they will be able to create either one powerful server, or multiple smaller ones - the way resources are used is entirely up to a client, restricted only by the limits of products you offer. Along with it, your customers will be granted permission to manage private networks, backups and firewall, access noVNC, SPICE, or Xterm.js console, as well as inspect usage graphs and statistics - all these directly on your website. Another detail to be valued highly is support for Cloud-Init for the KVM virtualization type, providing utilities for early initialization of your cloud instances. What is more, the module includes an amazing Proxmox Addon owing to which you can carefully handle your servers, IP addresses and clusters. Eager to bring even greater automation into your business? You can boost the module's potential with Proxmox VE Cloud  VPS Autoscaling For WHMCS to introduce a completely automated mechanism of servers' resizing and cloning adjusted to their current load."
   },
   },
   "logo": {
   "logo": {
     "filename": "logo.png"
     "filename": "logo.png"