This is an automated email from the ASF dual-hosted git repository. sureshanaparti pushed a commit to branch 4.20 in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.20 by this push: new d72a05aa5ad Add special Icon to Shared FileSystem Instances (#10857) d72a05aa5ad is described below commit d72a05aa5adb29952a3eb7eeef0c95d535e09768 Author: Abhisar Sinha <63767682+abh1...@users.noreply.github.com> AuthorDate: Wed Jul 23 11:21:59 2025 +0530 Add special Icon to Shared FileSystem Instances (#10857) * Use special icon for sharedfs instance and prefix for sharedfs volumes * Give custom icon precedence over shared fs icon * Fix sharedfsvm icon size * Fix UT failure in StorageVmSharedFSLifeCycleTest --- .../lifecycle/StorageVmSharedFSLifeCycle.java | 25 +++++++++++++++++----- .../lifecycle/StorageVmSharedFSLifeCycleTest.java | 11 +++++++--- ui/src/components/view/InfoCard.vue | 7 +++++- ui/src/components/view/ListView.vue | 7 +++++- 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/plugins/storage/sharedfs/storagevm/src/main/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java b/plugins/storage/sharedfs/storagevm/src/main/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java index 31159e7d3d9..ed26963cf81 100644 --- a/plugins/storage/sharedfs/storagevm/src/main/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java +++ b/plugins/storage/sharedfs/storagevm/src/main/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java @@ -140,13 +140,18 @@ public class StorageVmSharedFSLifeCycle implements SharedFSLifeCycle { return fsVmConfig; } - private String getStorageVmName(String fileShareName) { + private String getStorageVmPrefix(String fileShareName) { String prefix = String.format("%s-%s", SharedFSVmNamePrefix, fileShareName); - String suffix = Long.toHexString(System.currentTimeMillis()); - if (!NetUtils.verifyDomainNameLabel(prefix, true)) { prefix = prefix.replaceAll("[^a-zA-Z0-9-]", ""); } + return prefix; + } + + private String getStorageVmName(String fileShareName) { + String prefix = getStorageVmPrefix(fileShareName); + String suffix = Long.toHexString(System.currentTimeMillis()); + int nameLength = prefix.length() + suffix.length() + SharedFSVmNamePrefix.length(); if (nameLength > 63) { int prefixLength = prefix.length() - (nameLength - 63); @@ -236,8 +241,18 @@ public class StorageVmSharedFSLifeCycle implements SharedFSLifeCycle { Account owner = accountMgr.getActiveAccountById(sharedFS.getAccountId()); UserVm vm = deploySharedFSVM(sharedFS.getDataCenterId(), owner, List.of(networkId), sharedFS.getName(), sharedFS.getServiceOfferingId(), diskOfferingId, sharedFS.getFsType(), size, minIops, maxIops); - List<VolumeVO> volumes = volumeDao.findByInstanceAndType(vm.getId(), Volume.Type.DATADISK); - return new Pair<>(volumes.get(0).getId(), vm.getId()); + List<VolumeVO> volumes = volumeDao.findByInstance(vm.getId()); + VolumeVO dataVol = null; + for (VolumeVO vol : volumes) { + String volumeName = vol.getName(); + String updatedVolumeName = SharedFSVmNamePrefix + "-" + volumeName; + vol.setName(updatedVolumeName); + volumeDao.update(vol.getId(), vol); + if (vol.getVolumeType() == Volume.Type.DATADISK) { + dataVol = vol; + } + } + return new Pair<>(dataVol.getId(), vm.getId()); } @Override diff --git a/plugins/storage/sharedfs/storagevm/src/test/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java b/plugins/storage/sharedfs/storagevm/src/test/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java index 4393b0565f8..2cc909ce0d7 100644 --- a/plugins/storage/sharedfs/storagevm/src/test/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java +++ b/plugins/storage/sharedfs/storagevm/src/test/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java @@ -260,9 +260,14 @@ public class StorageVmSharedFSLifeCycleTest { anyMap(), isNull(), isNull(), isNull(), isNull(), anyBoolean(), anyString(), isNull())).thenReturn(vm); - VolumeVO volume = mock(VolumeVO.class); - when(volume.getId()).thenReturn(s_volumeId); - when(volumeDao.findByInstanceAndType(s_vmId, Volume.Type.DATADISK)).thenReturn(List.of(volume)); + VolumeVO rootVol = mock(VolumeVO.class); + when(rootVol.getVolumeType()).thenReturn(Volume.Type.ROOT); + when(rootVol.getName()).thenReturn("ROOT-1"); + VolumeVO dataVol = mock(VolumeVO.class); + when(dataVol.getId()).thenReturn(s_volumeId); + when(dataVol.getName()).thenReturn("DATA-1"); + when(dataVol.getVolumeType()).thenReturn(Volume.Type.DATADISK); + when(volumeDao.findByInstance(s_vmId)).thenReturn(List.of(rootVol, dataVol)); Pair<Long, Long> result = lifeCycle.deploySharedFS(sharedFS, s_networkId, s_diskOfferingId, s_size, s_minIops, s_maxIops); Assert.assertEquals(Optional.ofNullable(result.first()), Optional.ofNullable(s_volumeId)); diff --git a/ui/src/components/view/InfoCard.vue b/ui/src/components/view/InfoCard.vue index 2ad7b96602f..d467665ed5f 100644 --- a/ui/src/components/view/InfoCard.vue +++ b/ui/src/components/view/InfoCard.vue @@ -34,6 +34,9 @@ <span v-if="(resource.icon && resource.icon.base64image || images.template || images.iso || resourceIcon) && !['router', 'systemvm', 'volume'].includes($route.path.split('/')[1])"> <resource-icon :image="getImage(resource.icon && resource.icon.base64image || images.template || images.iso || resourceIcon)" size="4x" style="margin-right: 5px"/> </span> + <span v-else-if="resource.vmtype === 'sharedfsvm'"> + <file-text-outlined style="font-size: 36px;" /> + </span> <span v-else> <os-logo v-if="resource.ostypeid || resource.ostypename || ['guestoscategory'].includes($route.path.split('/')[1])" :osId="resource.ostypeid" :osName="resource.ostypename || resource.name" size="3x" @update-osname="setResourceOsType"/> <render-icon v-else-if="typeof $route.meta.icon ==='string'" style="font-size: 36px" :icon="$route.meta.icon" /> @@ -876,6 +879,7 @@ import UploadResourceIcon from '@/components/view/UploadResourceIcon' import eventBus from '@/config/eventBus' import ResourceIcon from '@/components/view/ResourceIcon' import ResourceLabel from '@/components/widgets/ResourceLabel' +import { FileTextOutlined } from '@ant-design/icons-vue' export default { name: 'InfoCard', @@ -887,7 +891,8 @@ export default { TooltipButton, UploadResourceIcon, ResourceIcon, - ResourceLabel + ResourceLabel, + FileTextOutlined }, props: { resource: { diff --git a/ui/src/components/view/ListView.vue b/ui/src/components/view/ListView.vue index 3d41e01bb1c..eca99dc0346 100644 --- a/ui/src/components/view/ListView.vue +++ b/ui/src/components/view/ListView.vue @@ -44,6 +44,9 @@ <span v-if="record.icon && record.icon.base64image"> <resource-icon :image="record.icon.base64image" size="2x"/> </span> + <span v-else-if="record.vmtype === 'sharedfsvm'"> + <file-text-outlined style="font-size: 18px;" /> + </span> <os-logo v-else :osId="record.ostypeid" :osName="record.osdisplayname" size="xl" /> </span> <span style="min-width: 120px" > @@ -591,6 +594,7 @@ import { createPathBasedOnVmType } from '@/utils/plugins' import { validateLinks } from '@/utils/links' import cronstrue from 'cronstrue/i18n' import moment from 'moment-timezone' +import { FileTextOutlined } from '@ant-design/icons-vue' export default { name: 'ListView', @@ -601,7 +605,8 @@ export default { CopyLabel, TooltipButton, ResourceIcon, - ResourceLabel + ResourceLabel, + FileTextOutlined }, props: { columns: {