This is an automated email from the ASF dual-hosted git repository.

sureshanaparti pushed a commit to branch 4.22
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit b1f870ae833ed6a6bf32db622a2d0b5d2c8360a1
Merge: 036489b288c 8db7cab7ba4
Author: Suresh Kumar Anaparti <[email protected]>
AuthorDate: Thu Jan 22 13:23:21 2026 +0530

    Merge branch '4.20' into 4.22

 .../org/apache/cloudstack/api/ApiConstants.java    |  1 +
 .../wrapper/LibvirtMigrateCommandWrapper.java      | 70 ++++++++++-----
 .../wrapper/LibvirtStartCommandWrapper.java        |  5 +-
 .../wrapper/LibvirtMigrateCommandWrapperTest.java  | 26 +++++-
 .../version/KubernetesVersionManagerImpl.java      | 52 ++++++++++--
 .../KubernetesSupportedVersionResponse.java        | 12 +++
 .../version/KubernetesVersionManagerImplTest.java  | 78 ++++++++++++++++-
 .../version/KubernetesVersionServiceTest.java      | 99 +++++++++++++++++-----
 .../java/com/cloud/storage/StorageManagerImpl.java |  8 +-
 .../cloud/storage/listener/StoragePoolMonitor.java | 28 ++++--
 .../SecondaryStorageManagerImpl.java               |  6 +-
 ui/public/locales/en.json                          |  1 +
 ui/public/locales/pt_BR.json                       |  1 +
 ui/src/config/section/image.js                     |  6 +-
 ui/src/views/auth/ForgotPassword.vue               |  2 +-
 15 files changed, 329 insertions(+), 66 deletions(-)

diff --cc 
plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java
index 81328d6ffb9,fe18a88fe1f..43607edc53a
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java
@@@ -287,15 -273,12 +288,15 @@@ public final class LibvirtMigrateComman
                      } catch (final LibvirtException e) {
                          logger.info("Couldn't get VM domain state after " + 
sleeptime + "ms: " + e.getMessage());
                      }
-                     if (state != null && state == 
DomainState.VIR_DOMAIN_RUNNING) {
+                     if (state != null && (state == 
DomainState.VIR_DOMAIN_RUNNING || state == DomainState.VIR_DOMAIN_PAUSED)) {
                          try {
                              DomainJobInfo job = dm.getJobInfo();
 -                            logger.info(String.format("Aborting migration of 
VM [%s] with domain job [%s] due to time out after %d seconds.", vmName, job, 
migrateWait));
 +                            logger.warn("Aborting migration of VM {} with 
domain job [{}] due to timeout after {} seconds. " +
 +                                    "Job stats: data processed={} bytes, data 
remaining={} bytes", vmName, job, migrateWait, job.getDataProcessed(), 
job.getDataRemaining());
                              dm.abortJob();
                              result = String.format("Migration of VM [%s] was 
cancelled by CloudStack due to time out after %d seconds.", vmName, 
migrateWait);
 +                            commandState = Command.State.FAILED;
 +                            
libvirtComputingResource.createOrUpdateLogFileForCommand(command, commandState);
                              logger.debug(result);
                              break;
                          } catch (final LibvirtException e) {
diff --cc 
plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java
index 0407ed8bbfd,05d89cc3d97..aa36fb89765
--- 
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java
+++ 
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java
@@@ -1089,153 -1020,27 +1089,177 @@@ public class LibvirtMigrateCommandWrapp
          Assert.assertTrue(finalXml.contains(newIsoVolumePath));
      }
  
+     @Test
+     public void testMaskVncPwdDomain() {
+         // Test case 1: Single quotes
+         String xml1 = "<graphics type='vnc' port='5900' passwd='secret123'/>";
+         String expected1 = "<graphics type='vnc' port='5900' 
passwd='*****'/>";
+         assertEquals(expected1, 
LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml1));
+ 
+         // Test case 2: Double quotes
+         String xml2 = "<graphics type=\"vnc\" port=\"5901\" 
passwd=\"mypassword\"/>";
+         String expected2 = "<graphics type=\"vnc\" port=\"5901\" 
passwd=\"*****\"/>";
+         assertEquals(expected2, 
LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml2));
+ 
+         // Test case 3: Non-VNC graphics (should remain unchanged)
+         String xml3 = "<graphics type='spice' port='5902' passwd='notvnc'/>";
+         assertEquals(xml3, 
LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml3));
+ 
+         // Test case 4: Multiple VNC entries in one string
+         String xml4 = "<graphics type='vnc' port='5900' passwd='a'/>\n" +
+                 "<graphics type='vnc' port='5901' passwd='b'/>";
+         String expected4 = "<graphics type='vnc' port='5900' 
passwd='*****'/>\n" +
+                 "<graphics type='vnc' port='5901' passwd='*****'/>";
+         assertEquals(expected4, 
LibvirtMigrateCommandWrapper.maskSensitiveInfoInXML(xml4));
+     }
++
 +    @Test
 +    public void updateGpuDevicesIfNeededTestNoGpuDevice() throws Exception {
 +        
Mockito.doReturn(virtualMachineTOMock).when(migrateCommandMock).getVirtualMachine();
 +        Mockito.doReturn(null).when(virtualMachineTOMock).getGpuDevice();
 +
 +        String result = 
libvirtMigrateCmdWrapper.updateGpuDevicesIfNeeded(migrateCommandMock, 
xmlWithoutGpuDevices, libvirtComputingResourceMock);
 +
 +        Assert.assertEquals("XML should remain unchanged when no GPU device 
is present", xmlWithoutGpuDevices, result);
 +    }
 +
 +    @Test
 +    public void updateGpuDevicesIfNeededTestNoDevicesSection() throws 
Exception {
 +        List<VgpuTypesInfo> gpuDevices = createTestMixedGpuDevices();
 +        GPUDeviceTO gpuDeviceTO = Mockito.mock(GPUDeviceTO.class);
 +        Mockito.doReturn(gpuDevices).when(gpuDeviceTO).getGpuDevices();
 +
 +        
Mockito.doReturn(virtualMachineTOMock).when(migrateCommandMock).getVirtualMachine();
 +        
Mockito.doReturn(gpuDeviceTO).when(virtualMachineTOMock).getGpuDevice();
 +
 +        String result = 
libvirtMigrateCmdWrapper.updateGpuDevicesIfNeeded(migrateCommandMock, 
xmlNoDevicesSection, libvirtComputingResourceMock);
 +
 +        Assert.assertEquals("XML should remain unchanged when no devices 
section is found", xmlNoDevicesSection, result);
 +    }
 +
 +    @Test
 +    public void updateGpuDevicesIfNeededTestWithPciDevice() throws Exception {
 +        List<VgpuTypesInfo> gpuDevices = createTestPciGpuDevice();
 +        GPUDeviceTO gpuDeviceTO = Mockito.mock(GPUDeviceTO.class);
 +        Mockito.doReturn(gpuDevices).when(gpuDeviceTO).getGpuDevices();
 +
 +        
Mockito.doReturn(virtualMachineTOMock).when(migrateCommandMock).getVirtualMachine();
 +        
Mockito.doReturn(gpuDeviceTO).when(virtualMachineTOMock).getGpuDevice();
 +
 +        String result = 
libvirtMigrateCmdWrapper.updateGpuDevicesIfNeeded(migrateCommandMock, 
xmlWithGpuDevices, libvirtComputingResourceMock);
 +
 +        // Verify that old GPU devices are removed and new ones are added
 +        Assert.assertFalse("Old PCI device should be removed", 
result.contains("bus='0x01' slot='0x00'"));
 +        Assert.assertFalse("Old MDEV device should be removed", 
result.contains("4b20d080-1b54-4048-85b3-a6a62d165c01"));
 +        Assert.assertTrue("New PCI device should be added", 
result.contains("bus=\"0x02\""));
 +        Assert.assertTrue("New PCI device should be added", 
result.contains("slot=\"0x00\""));
 +        Assert.assertTrue("PCI device should have vfio driver", 
result.contains("name=\"vfio\""));
 +    }
 +
 +    @Test
 +    public void updateGpuDevicesIfNeededTestWithMdevDevice() throws Exception 
{
 +        List<VgpuTypesInfo> gpuDevices = createTestMdevGpuDevice();
 +        GPUDeviceTO gpuDeviceTO = Mockito.mock(GPUDeviceTO.class);
 +        Mockito.doReturn(gpuDevices).when(gpuDeviceTO).getGpuDevices();
 +
 +        
Mockito.doReturn(virtualMachineTOMock).when(migrateCommandMock).getVirtualMachine();
 +        
Mockito.doReturn(gpuDeviceTO).when(virtualMachineTOMock).getGpuDevice();
 +
 +        String result = 
libvirtMigrateCmdWrapper.updateGpuDevicesIfNeeded(migrateCommandMock, 
xmlWithGpuDevices, libvirtComputingResourceMock);
 +
 +        // Verify that old GPU devices are removed and new ones are added
 +        Assert.assertFalse("Old PCI device should be removed", 
result.contains("bus='0x01' slot='0x00'"));
 +        Assert.assertFalse("Old MDEV device should be removed", 
result.contains("4b20d080-1b54-4048-85b3-a6a62d165c01"));
 +        Assert.assertTrue("New MDEV device should be added", 
result.contains("6f20d080-1b54-4048-85b3-a6a62d165c01"));
 +        Assert.assertTrue("MDEV device should have display=off", 
result.contains("display=\"off\""));
 +    }
 +
 +    @Test
 +    public void updateGpuDevicesIfNeededTestWithMixedDevices() throws 
Exception {
 +        List<VgpuTypesInfo> gpuDevices = createTestMixedGpuDevices();
 +        GPUDeviceTO gpuDeviceTO = Mockito.mock(GPUDeviceTO.class);
 +        Mockito.doReturn(gpuDevices).when(gpuDeviceTO).getGpuDevices();
 +
 +        
Mockito.doReturn(virtualMachineTOMock).when(migrateCommandMock).getVirtualMachine();
 +        
Mockito.doReturn(gpuDeviceTO).when(virtualMachineTOMock).getGpuDevice();
 +
 +        String result = 
libvirtMigrateCmdWrapper.updateGpuDevicesIfNeeded(migrateCommandMock, 
xmlWithGpuDevices, libvirtComputingResourceMock);
 +
 +        // Verify both PCI and MDEV devices are added
 +        Assert.assertTrue("PCI device should be added", 
result.contains("bus=\"0x02\""));
 +        Assert.assertTrue("PCI device should be added", 
result.contains("slot=\"0x00\""));
 +        Assert.assertTrue("MDEV device should be added", 
result.contains("6f20d080-1b54-4048-85b3-a6a62d165c01"));
 +
 +        // Count hostdev elements to ensure we have both
 +        long hostdevCount = result.lines().filter(line -> 
line.contains("<hostdev")).count();
 +        Assert.assertEquals("Should have 2 hostdev elements", 2, 
hostdevCount);
 +    }
 +
 +    @Test
 +    public void updateGpuDevicesIfNeededTestRemoveAllGpuDevices() throws 
Exception {
 +        List<VgpuTypesInfo> gpuDevices = new ArrayList<>(); // Empty list
 +        GPUDeviceTO gpuDeviceTO = Mockito.mock(GPUDeviceTO.class);
 +        Mockito.doReturn(gpuDevices).when(gpuDeviceTO).getGpuDevices();
 +
 +        
Mockito.doReturn(virtualMachineTOMock).when(migrateCommandMock).getVirtualMachine();
 +        
Mockito.doReturn(gpuDeviceTO).when(virtualMachineTOMock).getGpuDevice();
 +
 +        String result = 
libvirtMigrateCmdWrapper.updateGpuDevicesIfNeeded(migrateCommandMock, 
xmlWithoutGpuDevices, libvirtComputingResourceMock);
 +
 +        // Verify all GPU devices are removed
 +        Assert.assertFalse("Old PCI device should be removed", 
result.contains("bus=\"0x01\""));
 +        Assert.assertFalse("Old PCI device should be removed", 
result.contains("slot=\"0x00\""));
 +        Assert.assertFalse("Old MDEV device should be removed", 
result.contains("4b20d080-1b54-4048-85b3-a6a62d165c01"));
 +
 +        // Verify no hostdev elements remain
 +        long hostdevCount = result.lines().filter(line -> 
line.contains("<hostdev")).count();
 +        Assert.assertEquals("Should have no hostdev elements", 0, 
hostdevCount);
 +    }
 +
 +    // Helper methods for creating test GPU devices
 +    private List<VgpuTypesInfo> createTestPciGpuDevice() {
 +        List<VgpuTypesInfo> devices = new ArrayList<>();
 +        VgpuTypesInfo pciDevice = new VgpuTypesInfo(
 +                GpuDevice.DeviceType.PCI,
 +                "NVIDIA Corporation Tesla T4",
 +                "passthrough",
 +                "02:00.0", // New bus address for destination host
 +                "10de",
 +                "NVIDIA Corporation",
 +                "1eb8",
 +                "Tesla T4"
 +        );
 +        pciDevice.setDisplay(false);
 +        devices.add(pciDevice);
 +        return devices;
 +    }
 +
 +    private List<VgpuTypesInfo> createTestMdevGpuDevice() {
 +        List<VgpuTypesInfo> devices = new ArrayList<>();
 +        VgpuTypesInfo mdevDevice = new VgpuTypesInfo(
 +                GpuDevice.DeviceType.MDEV,
 +                "nvidia-63",
 +                "GRID T4-2Q",
 +                "6f20d080-1b54-4048-85b3-a6a62d165c01", // New UUID for 
destination host
 +                "10de",
 +                "NVIDIA Corporation",
 +                "1eb8",
 +                "Tesla T4"
 +        );
 +        mdevDevice.setDisplay(false);
 +        devices.add(mdevDevice);
 +        return devices;
 +    }
 +
 +    private List<VgpuTypesInfo> createTestMixedGpuDevices() {
 +        List<VgpuTypesInfo> devices = new ArrayList<>();
 +
 +        // Add PCI device
 +        devices.addAll(createTestPciGpuDevice());
 +
 +        // Add MDEV device
 +        devices.addAll(createTestMdevGpuDevice());
 +
 +        return devices;
 +    }
  }
diff --cc 
plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java
index 99f826402ce,8363f6f87e3..aef020335f2
--- 
a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java
+++ 
b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java
@@@ -347,8 -328,49 +359,34 @@@ public class KubernetesVersionManagerIm
          return createKubernetesSupportedVersionListResponse(versions, 
versionsAndCount.second());
      }
  
+     private void validateImageStoreForZone(Long zoneId, boolean 
directDownload) {
+         if (directDownload) {
+             return;
+         }
+         if (zoneId != null) {
+             List<ImageStoreVO> imageStores = 
imageStoreDao.listStoresByZoneId(zoneId);
+             if (CollectionUtils.isEmpty(imageStores)) {
+                 DataCenterVO zone = dataCenterDao.findById(zoneId);
+                 String zoneName = zone != null ? zone.getName() : 
String.valueOf(zoneId);
+                 throw new 
InvalidParameterValueException(String.format("Unable to register Kubernetes 
version ISO. No image store available in zone: %s", zoneName));
+             }
+         } else {
+             List<DataCenterVO> zones = dataCenterDao.listAllZones();
+             List<String> zonesWithoutStorage = new ArrayList<>();
+             for (DataCenterVO zone : zones) {
+                 List<ImageStoreVO> imageStores = 
imageStoreDao.listStoresByZoneId(zone.getId());
+                 if (CollectionUtils.isEmpty(imageStores)) {
+                     zonesWithoutStorage.add(zone.getName());
+                 }
+             }
+             if (!zonesWithoutStorage.isEmpty()) {
+                 throw new 
InvalidParameterValueException(String.format("Unable to register Kubernetes 
version ISO for all zones. The following zones have no image store: %s", 
String.join(", ", zonesWithoutStorage)));
+             }
+         }
+     }
+ 
 -    @Override
 -    @ActionEvent(eventType = 
KubernetesVersionEventTypes.EVENT_KUBERNETES_VERSION_ADD,
 -            eventDescription = "Adding Kubernetes supported version")
 -    public KubernetesSupportedVersionResponse 
addKubernetesSupportedVersion(final AddKubernetesSupportedVersionCmd cmd) {
 -        if (!KubernetesClusterService.KubernetesServiceEnabled.value()) {
 -            throw new CloudRuntimeException("Kubernetes Service plugin is 
disabled");
 -        }
 -        String name = cmd.getName();
 -        final String semanticVersion = cmd.getSemanticVersion();
 -        final Long zoneId = cmd.getZoneId();
 -        final String isoUrl = cmd.getUrl();
 -        final String isoChecksum = cmd.getChecksum();
 -        final Integer minimumCpu = cmd.getMinimumCpu();
 -        final Integer minimumRamSize = cmd.getMinimumRamSize();
 -        final boolean isDirectDownload = cmd.isDirectDownload();
 -        CPU.CPUArch arch = cmd.getArch();
 -
 +    private void validateKubernetesSupportedVersion(Long zoneId, String 
semanticVersion, Integer minimumCpu,
 +                                                    Integer minimumRamSize, 
boolean isDirectDownload) {
          if (minimumCpu == null || minimumCpu < 
KubernetesClusterService.MIN_KUBERNETES_CLUSTER_NODE_CPU) {
              throw new InvalidParameterValueException(String.format("Invalid 
value for %s parameter. Minimum %d vCPUs required.", 
ApiConstants.MIN_CPU_NUMBER, 
KubernetesClusterService.MIN_KUBERNETES_CLUSTER_NODE_CPU));
          }
@@@ -411,33 -414,9 +451,33 @@@
          supportedVersionVO = 
kubernetesSupportedVersionDao.persist(supportedVersionVO);
          
CallContext.current().putContextParameter(KubernetesSupportedVersion.class, 
supportedVersionVO.getUuid());
  
-         return createKubernetesSupportedVersionResponse(supportedVersionVO);
+         return createKubernetesSupportedVersionResponse(supportedVersionVO, 
true);
      }
  
 +    @Override
 +    public GetUploadParamsResponse 
registerKubernetesSupportedVersionForPostUpload(GetUploadParamsForKubernetesSupportedVersionCmd
 cmd) {
 +        if (!KubernetesClusterService.KubernetesServiceEnabled.value()) {
 +            throw new CloudRuntimeException("Kubernetes Service plugin is 
disabled");
 +        }
 +        String name = cmd.getName();
 +        final String semanticVersion = cmd.getSemanticVersion();
 +        final Long zoneId = cmd.getZoneId();
 +        final String isoChecksum = cmd.getChecksum();
 +        final Integer minimumCpu = cmd.getMinimumCpu();
 +        final Integer minimumRamSize = cmd.getMinimumRamSize();
 +
 +        validateKubernetesSupportedVersion(zoneId, semanticVersion, 
minimumCpu, minimumRamSize, false);
 +
 +        GetUploadParamsResponse response = 
registerKubernetesVersionIsoForUpload(zoneId, name, isoChecksum);
 +
 +        VMTemplateVO template = 
templateDao.findByUuid(response.getId().toString());
 +        KubernetesSupportedVersionVO supportedVersionVO = new 
KubernetesSupportedVersionVO(name, semanticVersion, template.getId(), zoneId, 
minimumCpu, minimumRamSize);
 +        supportedVersionVO = 
kubernetesSupportedVersionDao.persist(supportedVersionVO);
 +        
CallContext.current().putContextParameter(KubernetesSupportedVersion.class, 
supportedVersionVO.getUuid());
 +
 +        return response;
 +    }
 +
      @Override
      @ActionEvent(eventType = 
KubernetesVersionEventTypes.EVENT_KUBERNETES_VERSION_DELETE,
              eventDescription = "deleting Kubernetes supported version", async 
= true)
diff --cc 
server/src/main/java/com/cloud/storage/listener/StoragePoolMonitor.java
index b432858f2e0,6df3cbaeedf..2f9750edee2
--- a/server/src/main/java/com/cloud/storage/listener/StoragePoolMonitor.java
+++ b/server/src/main/java/com/cloud/storage/listener/StoragePoolMonitor.java
@@@ -21,12 -20,8 +21,13 @@@ import java.util.List
  
  import javax.inject.Inject;
  
 +import com.cloud.dc.dao.ClusterDao;
 +import com.cloud.dc.dao.HostPodDao;
 +import com.cloud.exception.StorageConflictException;
  import com.cloud.storage.StorageManager;
 +import com.cloud.storage.dao.StoragePoolHostDao;
 +import com.cloud.utils.exception.CloudRuntimeException;
+ import com.cloud.utils.Profiler;
  import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
  import 
org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
  import 
org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
diff --cc 
services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java
index 2ee1dcb37da,c9bcb911000..e26091f677e
--- 
a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java
+++ 
b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java
@@@ -1229,22 -1224,11 +1229,24 @@@ public class SecondaryStorageManagerImp
          if (dc.getDns2() != null) {
              buf.append(" dns2=").append(dc.getDns2());
          }
-         String nfsVersion = imageStoreDetailsUtil != null ? 
imageStoreDetailsUtil.getNfsVersion(secStores.get(0).getId()) : null;
-         buf.append(" nfsVersion=").append(nfsVersion);
+         String nfsVersion = 
imageStoreDetailsUtil.getNfsVersion(secStores.get(0).getId());
+         if (StringUtils.isNotBlank(nfsVersion)) {
+             buf.append(" nfsVersion=").append(nfsVersion);
+         }
          buf.append(" 
keystore_password=").append(VirtualMachineGuru.getEncodedString(PasswordGenerator.generateRandomPassword(16)));
 +
 +        if (SystemVmEnableUserData.valueIn(dc.getId())) {
 +            String userDataUuid = 
SecondaryStorageVmUserData.valueIn(dc.getId());
 +            try {
 +                String userData = 
userDataManager.validateAndGetUserDataForSystemVM(userDataUuid);
 +                if (StringUtils.isNotBlank(userData)) {
 +                    buf.append(" userdata=").append(userData);
 +                }
 +            } catch (Exception e) {
 +                logger.warn("Failed to load user data for the ssvm, ignored", 
e);
 +            }
 +        }
 +
          String bootArgs = buf.toString();
          if (logger.isDebugEnabled()) {
              logger.debug(String.format("Boot args for machine profile [%s]: 
[%s].", profile.toString(), bootArgs));
diff --cc ui/src/config/section/image.js
index 7172049d51e,3f8286c5fb1..d93e27c3f22
--- a/ui/src/config/section/image.js
+++ b/ui/src/config/section/image.js
@@@ -58,11 -58,11 +58,11 @@@ export default 
          return fields
        },
        details: () => {
 -        var fields = ['name', 'id', 'displaytext', 'checksum', 'hypervisor', 
'arch', 'format', 'ostypename', 'size', 'physicalsize', 'isready', 
'passwordenabled',
 +        var fields = ['name', 'id', 'displaytext', 'checksum', 'hypervisor', 
'arch', 'format', 'externalprovisioner', 'ostypename', 'size', 'physicalsize', 
'isready', 'passwordenabled',
            'crossZones', 'templatetype', 'directdownload', 'deployasis', 
'ispublic', 'isfeatured', 'isextractable', 'isdynamicallyscalable', 
'crosszones', 'type',
-           'account', 'domain', 'created', 'userdatadetails', 
'userdatapolicy', 'forcks']
 -          'account', 'domain', 'created', 'userdatadetails', 
'userdatapolicy', 'url']
++          'account', 'domain', 'created', 'userdatadetails', 
'userdatapolicy', 'url', 'forcks']
          if (['Admin'].includes(store.getters.userInfo.roletype)) {
-           fields.push('templatetag', 'templatetype', 'url')
+           fields.push('templatetag', 'templatetype')
          }
          return fields
        },
diff --cc ui/src/views/auth/ForgotPassword.vue
index 78af0c3d9f1,1e817e01a6e..a508934070a
--- a/ui/src/views/auth/ForgotPassword.vue
+++ b/ui/src/views/auth/ForgotPassword.vue
@@@ -159,10 -159,10 +159,10 @@@ export default 
          if (!loginParams.domain) {
            loginParams.domain = '/'
          }
 -        api('forgotPassword', {}, 'POST', loginParams)
 +        postAPI('forgotPassword', loginParams)
            .finally(() => {
              this.$message.success(this.$t('message.forgot.password.success'))
-             this.$router.push({ path: '/login' }).catch(() => {})
+             this.$router.replace({ path: '/user/login' })
            })
        }).catch(error => {
          this.formRef.value.scrollToField(error.errorFields[0].name)

Reply via email to