From 5cb279b6f105e687166788b563c302df7735276f Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 30 Dec 2025 15:37:32 +0530 Subject: [PATCH 1/7] ui: fix test delivery params in create webhook form (#12318) Signed-off-by: Abhishek Kumar --- ui/src/components/view/TestWebhookDeliveryView.vue | 2 +- ui/src/views/tools/CreateWebhook.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/components/view/TestWebhookDeliveryView.vue b/ui/src/components/view/TestWebhookDeliveryView.vue index ebebe722e99..2bb154f3900 100644 --- a/ui/src/components/view/TestWebhookDeliveryView.vue +++ b/ui/src/components/view/TestWebhookDeliveryView.vue @@ -186,7 +186,7 @@ export default { params.payloadUrl = this.payloadUrl } if (this.sslVerification) { - params.payload = this.sslVerification + params.sslVerification = this.sslVerification } if (this.secretKey) { params.secretKey = this.secretKey diff --git a/ui/src/views/tools/CreateWebhook.vue b/ui/src/views/tools/CreateWebhook.vue index 7d687c7d983..2b437471977 100644 --- a/ui/src/views/tools/CreateWebhook.vue +++ b/ui/src/views/tools/CreateWebhook.vue @@ -135,7 +135,7 @@ From 7a11bd2f987c8b1e50f84e67ef1f4185773a2ed0 Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 30 Dec 2025 07:08:13 -0500 Subject: [PATCH 2/7] CKS: Fix issue with scaling down CKS Nodes when deployed in HA mode (#12302) --- .../KubernetesClusterScaleWorker.java | 24 +++++-- .../KubernetesClusterScaleWorkerTest.java | 66 ++++++++++++++++++- 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java index dba858ed809..6d22a1a3a03 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java @@ -441,16 +441,30 @@ public class KubernetesClusterScaleWorker extends KubernetesClusterResourceModif if (this.nodeIds != null) { vmList = getKubernetesClusterVMMapsForNodes(this.nodeIds).stream().filter(vm -> !vm.isExternalNode()).collect(Collectors.toList()); } else { - vmList = getKubernetesClusterVMMaps(); - vmList = vmList.stream() - .filter(vm -> !vm.isExternalNode() && !vm.isControlNode() && !vm.isEtcdNode()) - .collect(Collectors.toList()); - vmList = vmList.subList((int) (kubernetesCluster.getControlNodeCount() + clusterSize - 1), vmList.size()); + vmList = getWorkerNodesToRemove(); + if (vmList.isEmpty()) { + logger.info("No nodes to remove from Kubernetes cluster: {}", kubernetesCluster); + return; + } } Collections.reverse(vmList); removeNodesFromCluster(vmList); } + public List getWorkerNodesToRemove() { + List workerVMsMap = getKubernetesClusterVMMaps().stream() + .filter(vm -> !vm.isExternalNode() && !vm.isControlNode() && !vm.isEtcdNode()) + .collect(Collectors.toList()); + int totalWorkerNodes = workerVMsMap.size(); + int desiredWorkerNodes = clusterSize == null ? (int) kubernetesCluster.getNodeCount() : clusterSize.intValue(); + int toRemoveCount = Math.max(0, totalWorkerNodes - desiredWorkerNodes); + if (toRemoveCount == 0) { + return new ArrayList<>(); + } + int startIndex = Math.max(0, totalWorkerNodes - toRemoveCount); + return new ArrayList<>(workerVMsMap.subList(startIndex, totalWorkerNodes)); + } + private void scaleUpKubernetesClusterSize(final long newVmCount) throws CloudRuntimeException { if (!kubernetesCluster.getState().equals(KubernetesCluster.State.Scaling)) { stateTransitTo(kubernetesCluster.getId(), KubernetesCluster.Event.ScaleUpRequested); diff --git a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorkerTest.java b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorkerTest.java index 847c8bd6d29..c9299bdbaa6 100644 --- a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorkerTest.java +++ b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorkerTest.java @@ -17,8 +17,8 @@ package com.cloud.kubernetes.cluster.actionworkers; import com.cloud.kubernetes.cluster.KubernetesCluster; -import com.cloud.kubernetes.cluster.KubernetesClusterManagerImpl; import com.cloud.kubernetes.cluster.KubernetesClusterVmMapVO; +import com.cloud.kubernetes.cluster.KubernetesClusterManagerImpl; import com.cloud.kubernetes.cluster.dao.KubernetesClusterVmMapDao; import com.cloud.offering.ServiceOffering; import com.cloud.service.ServiceOfferingVO; @@ -29,15 +29,17 @@ import com.cloud.vm.dao.UserVmDao; import org.junit.Assert; import org.junit.Before; import org.junit.Test; + import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; +import java.util.Arrays; import java.util.List; -import static com.cloud.kubernetes.cluster.KubernetesServiceHelper.KubernetesClusterNodeType.DEFAULT; import static com.cloud.kubernetes.cluster.KubernetesServiceHelper.KubernetesClusterNodeType.CONTROL; +import static com.cloud.kubernetes.cluster.KubernetesServiceHelper.KubernetesClusterNodeType.DEFAULT; @RunWith(MockitoJUnitRunner.class) public class KubernetesClusterScaleWorkerTest { @@ -125,4 +127,64 @@ public class KubernetesClusterScaleWorkerTest { Assert.assertEquals(expectedCores, newClusterCapacity.first().longValue()); Assert.assertEquals(expectedMemory, newClusterCapacity.second().longValue()); } + + + @Test + public void testGetWorkerNodesToRemoveForDownsize_singleRemoval() { + KubernetesCluster kubernetesCluster = Mockito.mock(KubernetesCluster.class); + KubernetesClusterManagerImpl clusterManager = Mockito.mock(KubernetesClusterManagerImpl.class); + KubernetesClusterScaleWorker worker = new KubernetesClusterScaleWorker(kubernetesCluster, new java.util.HashMap<>(), 2L, null, false, null, null, clusterManager); + KubernetesClusterScaleWorker spyWorker = Mockito.spy(worker); + + KubernetesClusterVmMapVO vm1 = Mockito.mock(KubernetesClusterVmMapVO.class); + Mockito.when(vm1.isExternalNode()).thenReturn(false); + Mockito.when(vm1.isControlNode()).thenReturn(false); + Mockito.when(vm1.isEtcdNode()).thenReturn(false); + + KubernetesClusterVmMapVO vm2 = Mockito.mock(KubernetesClusterVmMapVO.class); + Mockito.when(vm2.isExternalNode()).thenReturn(false); + Mockito.when(vm2.isControlNode()).thenReturn(false); + Mockito.when(vm2.isEtcdNode()).thenReturn(false); + + KubernetesClusterVmMapVO vm3 = Mockito.mock(KubernetesClusterVmMapVO.class); + Mockito.when(vm3.isExternalNode()).thenReturn(false); + Mockito.when(vm3.isControlNode()).thenReturn(false); + Mockito.when(vm3.isEtcdNode()).thenReturn(false); + + Mockito.doReturn(Arrays.asList(vm1, vm2, vm3)).when(spyWorker).getKubernetesClusterVMMaps(); + + List toRemove = spyWorker.getWorkerNodesToRemove(); + + Assert.assertEquals(1, toRemove.size()); + Assert.assertSame(vm3, toRemove.get(0)); + } + + @Test + public void testGetWorkerNodesToRemoveForDownsize_noRemoval() { + KubernetesCluster kubernetesCluster = Mockito.mock(KubernetesCluster.class); + + KubernetesClusterScaleWorker worker = new KubernetesClusterScaleWorker(kubernetesCluster, new java.util.HashMap<>(), 3L, null, false, null, null, clusterManager); + KubernetesClusterScaleWorker spyWorker = Mockito.spy(worker); + + KubernetesClusterVmMapVO vm1 = Mockito.mock(KubernetesClusterVmMapVO.class); + Mockito.when(vm1.isExternalNode()).thenReturn(false); + Mockito.when(vm1.isControlNode()).thenReturn(false); + Mockito.when(vm1.isEtcdNode()).thenReturn(false); + + KubernetesClusterVmMapVO vm2 = Mockito.mock(KubernetesClusterVmMapVO.class); + Mockito.when(vm2.isExternalNode()).thenReturn(false); + Mockito.when(vm2.isControlNode()).thenReturn(false); + Mockito.when(vm2.isEtcdNode()).thenReturn(false); + + KubernetesClusterVmMapVO vm3 = Mockito.mock(KubernetesClusterVmMapVO.class); + Mockito.when(vm3.isExternalNode()).thenReturn(false); + Mockito.when(vm3.isControlNode()).thenReturn(false); + Mockito.when(vm3.isEtcdNode()).thenReturn(false); + + Mockito.doReturn(Arrays.asList(vm1, vm2, vm3)).when(spyWorker).getKubernetesClusterVMMaps(); + + List toRemove = spyWorker.getWorkerNodesToRemove(); + + Assert.assertTrue(toRemove.isEmpty()); + } } From 7ff76cb2d7b8aea0e361c2f8728f1f5e0e8a2e6b Mon Sep 17 00:00:00 2001 From: Pearl Dsilva Date: Tue, 30 Dec 2025 15:46:04 -0500 Subject: [PATCH 3/7] Protect upgrades from failures (#12319) --- .../cloud.idempotent_drop_column.sql | 28 +++++++++++++++++++ .../META-INF/db/schema-42010to42100.sql | 8 +++--- 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 engine/schema/src/main/resources/META-INF/db/procedures/cloud.idempotent_drop_column.sql diff --git a/engine/schema/src/main/resources/META-INF/db/procedures/cloud.idempotent_drop_column.sql b/engine/schema/src/main/resources/META-INF/db/procedures/cloud.idempotent_drop_column.sql new file mode 100644 index 00000000000..31d5b9f500f --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/procedures/cloud.idempotent_drop_column.sql @@ -0,0 +1,28 @@ +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. + +-- in cloud +DROP PROCEDURE IF EXISTS `cloud`.`IDEMPOTENT_DROP_COLUMN`; + +-- Error 1091: Can't DROP column; check that column/key exists +CREATE PROCEDURE `cloud`.`IDEMPOTENT_DROP_COLUMN` ( + IN in_table_name VARCHAR(200), + IN in_column_name VARCHAR(200) +) +BEGIN + + DECLARE CONTINUE HANDLER FOR 1091 BEGIN END; SET @ddl = CONCAT('ALTER TABLE ', in_table_name, ' DROP COLUMN ', in_column_name); PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; END; diff --git a/engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql b/engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql index 167dd92730c..4c65f37e0fe 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql @@ -301,7 +301,7 @@ CALL `cloud`.`IDEMPOTENT_DROP_FOREIGN_KEY`('cloud.service_offering','fk_service_ CALL `cloud`.`IDEMPOTENT_ADD_FOREIGN_KEY`('cloud.service_offering', 'fk_service_offering__vgpu_profile_id', '(vgpu_profile_id)', '`vgpu_profile`(`id`)'); -- Netris Plugin -CREATE TABLE `cloud`.`netris_providers` ( +CREATE TABLE IF NOT EXISTS `cloud`.`netris_providers` ( `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', `uuid` varchar(40), `zone_id` bigint unsigned NOT NULL COMMENT 'Zone ID', @@ -321,11 +321,11 @@ CREATE TABLE `cloud`.`netris_providers` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- Drop the Tungsten and NSX columns from the network offerings (replaced by checking the provider on the ntwk_offering_service_map table) -ALTER TABLE `cloud`.`network_offerings` DROP COLUMN `for_tungsten`; -ALTER TABLE `cloud`.`network_offerings` DROP COLUMN `for_nsx`; +CALL `cloud`.`IDEMPOTENT_DROP_COLUMN`('cloud.network_offerings', 'for_tungsten'); +CALL `cloud`.`IDEMPOTENT_DROP_COLUMN`('cloud.network_offerings', 'for_nsx'); -- Drop the Tungsten and NSX columns from the VPC offerings (replaced by checking the provider on the vpc_offering_service_map table) -ALTER TABLE `cloud`.`vpc_offerings` DROP COLUMN `for_nsx`; +CALL `cloud`.`IDEMPOTENT_DROP_COLUMN`('cloud.vpc_offerings', 'for_nsx'); -- Add next_hop to the static_routes table CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.static_routes', 'next_hop', 'varchar(50) COMMENT "next hop of the static route" AFTER `vpc_gateway_id`'); From 10dcbd76f0fdd2e0eb0674e04e211a3788c8ad89 Mon Sep 17 00:00:00 2001 From: Rene Peinthor Date: Wed, 31 Dec 2025 10:55:54 +0100 Subject: [PATCH 4/7] linstor: Provide /dev/drbd/by-res/ resource paths to CloudStack (#12300) --- plugins/storage/volume/linstor/CHANGELOG.md | 17 +++------ .../kvm/storage/LinstorStorageAdaptor.java | 7 ++-- .../storage/datastore/util/LinstorUtil.java | 35 +++++++++++++++---- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/plugins/storage/volume/linstor/CHANGELOG.md b/plugins/storage/volume/linstor/CHANGELOG.md index 7da3516955d..47d1ddeb06c 100644 --- a/plugins/storage/volume/linstor/CHANGELOG.md +++ b/plugins/storage/volume/linstor/CHANGELOG.md @@ -5,22 +5,24 @@ All notable changes to Linstor CloudStack plugin will be documented in this file The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2025-12-18] + +### Changed +- Provide /dev/drbd/by-res/ resource paths to CloudStack for usage. + ## [2025-10-03] ### Changed - - Revert qcow2 snapshot now use sparse/discard options to convert on thin devices. ## [2025-08-05] ### Fixed - - getVolumeStats wasn't correctly working if multiple Linstor clusters/primary storages are used. ## [2025-07-01] ### Fixed - - Regression in 4.19.3 and 4.21.0 with templates from snapshots ## [2025-05-07] @@ -31,25 +33,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2025-03-13] ### Fixed - - Implemented missing delete datastore, to correctly cleanup on datastore removal ## [2025-02-21] ### Fixed - - Always try to delete cs-...-rst resource before doing a snapshot backup ## [2025-01-27] ### Fixed - - Use of multiple primary storages on the same linstor controller ## [2025-01-20] ### Fixed - - Volume snapshots on zfs used the wrong dataset path to hide/unhide snapdev ## [2024-12-19] @@ -60,13 +58,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2024-12-13] ### Fixed - - Linstor heartbeat check now also ask linstor-controller if there is no connection between nodes ## [2024-12-11] ### Fixed - - Only set allow-two-primaries if a live migration is performed ## [2024-10-28] @@ -79,17 +75,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2024-10-14] ### Added - - Support for ISO direct download to primary storage ## [2024-10-04] ### Added - - Enable qemu discard="unmap" for Linstor block disks ## [2024-08-27] ### Changed - - Allow two primaries(+protocol c) is now set on resource-connection level instead of rd diff --git a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java index a664e7ed03b..1fe318e5163 100644 --- a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java +++ b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java @@ -232,7 +232,7 @@ public class LinstorStorageAdaptor implements StorageAdaptor { makeResourceAvailable(api, foundRscName, false); if (!resources.isEmpty() && !resources.get(0).getVolumes().isEmpty()) { - final String devPath = resources.get(0).getVolumes().get(0).getDevicePath(); + final String devPath = LinstorUtil.getDevicePathFromResource(resources.get(0)); logger.info("Linstor: Created drbd device: " + devPath); final KVMPhysicalDisk kvmDisk = new KVMPhysicalDisk(devPath, name, pool); kvmDisk.setFormat(QemuImg.PhysicalDiskFormat.RAW); @@ -455,8 +455,9 @@ public class LinstorStorageAdaptor implements StorageAdaptor { private Optional getResourceByPathOrName( final List resources, String path) { return resources.stream() - .filter(rsc -> getLinstorRscName(path).equalsIgnoreCase(rsc.getName()) || rsc.getVolumes().stream() - .anyMatch(v -> path.equals(v.getDevicePath()))) + .filter(rsc -> getLinstorRscName(path).equalsIgnoreCase(rsc.getName()) || + path.equals(LinstorUtil.formatDrbdByResDevicePath(rsc.getName())) || + rsc.getVolumes().stream().anyMatch(v -> path.equals(v.getDevicePath()))) .findFirst(); } diff --git a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java index 9c3c9d32611..4196c12b116 100644 --- a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java +++ b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java @@ -264,6 +264,16 @@ public class LinstorUtil { return false; } + /** + * Format the device path for DRBD resources. + * @param rscName + * @return + */ + public static String formatDrbdByResDevicePath(String rscName) + { + return String.format("/dev/drbd/by-res/%s/0", rscName); + } + /** * Try to get the device path for the given resource name. * This could be made a bit more direct after java-linstor api is fixed for layer data subtypes. @@ -283,12 +293,7 @@ public class LinstorUtil { null); for (ResourceWithVolumes rsc : resources) { if (!rsc.getVolumes().isEmpty()) { - // CloudStack resource always only have 1 volume - String devicePath = rsc.getVolumes().get(0).getDevicePath(); - if (devicePath != null && !devicePath.isEmpty()) { - LOGGER.debug("getDevicePath: {} -> {}", rscName, devicePath); - return devicePath; - } + return LinstorUtil.getDevicePathFromResource(rsc); } } @@ -297,6 +302,24 @@ public class LinstorUtil { throw new CloudRuntimeException("Linstor: " + errMsg); } + /** + * Check if the resource has DRBD or not and deliver the correct device path. + * @param rsc + * @return + */ + public static String getDevicePathFromResource(ResourceWithVolumes rsc) { + if (!rsc.getVolumes().isEmpty()) { + // CloudStack resource always only have 1 volume + if (rsc.getLayerObject().getDrbd() != null) { + return formatDrbdByResDevicePath(rsc.getName()); + } else { + return rsc.getVolumes().get(0).getDevicePath(); + } + } + throw new CloudRuntimeException( + String.format("getDevicePath: Resource %s/%s doesn't have volumes", rsc.getNodeName(), rsc.getName())); + } + public static ApiCallRcList applyAuxProps(DevelopersApi api, String rscName, String dispName, String vmName) throws ApiException { From 4f749378551b3035ff0617f6f8df1fe3618b9c27 Mon Sep 17 00:00:00 2001 From: Suresh Kumar Anaparti Date: Fri, 2 Jan 2026 14:04:59 +0530 Subject: [PATCH 5/7] Event typo fix (#12350) --- .../ObjectInDataStoreStateMachine.java | 6 +-- .../manager/StorageCacheManagerImpl.java | 2 +- .../motion/AncientDataMotionStrategy.java | 4 +- .../StorageSystemDataMotionStrategy.java | 12 ++--- .../image/SecondaryStorageServiceImpl.java | 4 +- .../storage/image/TemplateServiceImpl.java | 14 +++--- .../snapshot/DefaultSnapshotStrategy.java | 2 +- .../storage/snapshot/SnapshotServiceImpl.java | 12 ++--- .../datastore/DataObjectManagerImpl.java | 8 ++-- .../ObjectInDataStoreManagerImpl.java | 16 +++---- .../storage/volume/VolumeObject.java | 2 +- .../storage/volume/VolumeServiceImpl.java | 48 +++++++++---------- .../storage/volume/VolumeObjectTest.java | 4 +- .../motion/StorPoolDataMotionStrategy.java | 4 +- .../snapshot/StorPoolSnapshotStrategy.java | 2 +- 15 files changed, 68 insertions(+), 72 deletions(-) diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java index a8e80313768..d4ca163e4e6 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java @@ -33,9 +33,9 @@ public interface ObjectInDataStoreStateMachine extends StateObject entry : volumeToPool.entrySet()) { VolumeInfo volume = entry.getKey(); snapshotMgr.cleanupSnapshotsByVolume(volume.getId()); - volume.processEvent(Event.OperationSuccessed); + volume.processEvent(Event.OperationSucceeded); } future.complete(res); } @@ -2431,7 +2431,7 @@ public class VolumeServiceImpl implements VolumeService { } } else { - vo.processEvent(Event.OperationSuccessed, result.getAnswer()); + vo.processEvent(Event.OperationSucceeded, result.getAnswer()); if (vo.getSize() != null) { // publish usage events @@ -2551,7 +2551,7 @@ public class VolumeServiceImpl implements VolumeService { } try { - volume.processEvent(Event.OperationSuccessed); + volume.processEvent(Event.OperationSucceeded); } catch (Exception e) { logger.debug("Failed to change volume state (after resize success)", e); } @@ -2640,7 +2640,7 @@ public class VolumeServiceImpl implements VolumeService { if (volume.getState() == State.NotUploaded || volume.getState() == State.UploadInProgress) { VolumeObject volObj = (VolumeObject)volFactory.getVolume(volume.getId()); - volObj.processEvent(Event.OperationSuccessed); + volObj.processEvent(Event.OperationSucceeded); } if (volInfo.getSize() > 0) { diff --git a/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeObjectTest.java b/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeObjectTest.java index 58f47a5db64..5701bc49e15 100644 --- a/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeObjectTest.java +++ b/engine/storage/volume/src/test/java/org/apache/cloudstack/storage/volume/VolumeObjectTest.java @@ -147,7 +147,7 @@ public class VolumeObjectTest extends TestCase{ expectedResult.put(ObjectInDataStoreStateMachine.Event.MigrationRequested, Volume.Event.CopyRequested); expectedResult.put(ObjectInDataStoreStateMachine.Event.DestroyRequested, Volume.Event.DestroyRequested); expectedResult.put(ObjectInDataStoreStateMachine.Event.ExpungeRequested, Volume.Event.ExpungingRequested); - expectedResult.put(ObjectInDataStoreStateMachine.Event.OperationSuccessed, Volume.Event.OperationSucceeded); + expectedResult.put(ObjectInDataStoreStateMachine.Event.OperationSucceeded, Volume.Event.OperationSucceeded); expectedResult.put(ObjectInDataStoreStateMachine.Event.MigrationCopySucceeded, Volume.Event.MigrationCopySucceeded); expectedResult.put(ObjectInDataStoreStateMachine.Event.OperationFailed, Volume.Event.OperationFailed); expectedResult.put(ObjectInDataStoreStateMachine.Event.MigrationCopyFailed, Volume.Event.MigrationCopyFailed); @@ -168,7 +168,7 @@ public class VolumeObjectTest extends TestCase{ expectedResult.put(ObjectInDataStoreStateMachine.Event.MigrationCopyRequested, Volume.Event.MigrationCopyRequested); expectedResult.put(ObjectInDataStoreStateMachine.Event.DestroyRequested, Volume.Event.DestroyRequested); expectedResult.put(ObjectInDataStoreStateMachine.Event.ExpungeRequested, Volume.Event.ExpungingRequested); - expectedResult.put(ObjectInDataStoreStateMachine.Event.OperationSuccessed, Volume.Event.OperationSucceeded); + expectedResult.put(ObjectInDataStoreStateMachine.Event.OperationSucceeded, Volume.Event.OperationSucceeded); expectedResult.put(ObjectInDataStoreStateMachine.Event.MigrationCopySucceeded, Volume.Event.MigrationCopySucceeded); expectedResult.put(ObjectInDataStoreStateMachine.Event.OperationFailed, Volume.Event.OperationFailed); expectedResult.put(ObjectInDataStoreStateMachine.Event.MigrationCopyFailed, Volume.Event.MigrationCopyFailed); diff --git a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/motion/StorPoolDataMotionStrategy.java b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/motion/StorPoolDataMotionStrategy.java index aa972d44343..5a4802ab264 100644 --- a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/motion/StorPoolDataMotionStrategy.java +++ b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/motion/StorPoolDataMotionStrategy.java @@ -453,8 +453,8 @@ public class StorPoolDataMotionStrategy implements DataMotionStrategy { VolumeInfo destVolumeInfo = entry.getValue(); if (success) { - srcVolumeInfo.processEvent(Event.OperationSuccessed); - destVolumeInfo.processEvent(Event.OperationSuccessed); + srcVolumeInfo.processEvent(Event.OperationSucceeded); + destVolumeInfo.processEvent(Event.OperationSucceeded); _volumeDao.updateUuid(srcVolumeInfo.getId(), destVolumeInfo.getId()); diff --git a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/snapshot/StorPoolSnapshotStrategy.java b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/snapshot/StorPoolSnapshotStrategy.java index 5ec86df91e1..8a51e2672ea 100644 --- a/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/snapshot/StorPoolSnapshotStrategy.java +++ b/plugins/storage/volume/storpool/src/main/java/org/apache/cloudstack/storage/snapshot/StorPoolSnapshotStrategy.java @@ -201,7 +201,7 @@ public class StorPoolSnapshotStrategy implements SnapshotStrategy { if (parent.getPath() != null && parent.getPath().equalsIgnoreCase(snapshot.getPath())) { logger.debug("for empty delta snapshot, only mark it as destroyed in db"); snapshot.processEvent(Event.DestroyRequested); - snapshot.processEvent(Event.OperationSuccessed); + snapshot.processEvent(Event.OperationSucceeded); deleted = true; if (!resultIsSet) { result = true; From 77cb0827d354af69766de2052715410201684b95 Mon Sep 17 00:00:00 2001 From: YoulongChen <30854794+YLChen-007@users.noreply.github.com> Date: Mon, 5 Jan 2026 14:58:34 +0800 Subject: [PATCH 6/7] Refactor XML parsing to use safer document builders in multiple classes (#12129) Co-authored-by: chenyoulong20g@ict.ac.cn --- .../LibvirtMigrateVolumeCommandWrapper.java | 5 ++-- .../java/com/cloud/test/DatabaseConfig.java | 2 +- .../utils/cisco/n1kv/vsm/VsmCommand.java | 23 ++++++++++--------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java index c0630f97886..22e35f53c05 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java @@ -42,6 +42,7 @@ import org.apache.cloudstack.storage.datastore.client.ScaleIOGatewayClient; import org.apache.cloudstack.storage.datastore.util.ScaleIOUtil; import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.cloudstack.utils.security.ParserUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.libvirt.Connect; @@ -216,7 +217,7 @@ public class LibvirtMigrateVolumeCommandWrapper extends CommandWrapper> params) { try { // Create the document and root element. - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory docFactory = ParserUtils.getSaferDocumentBuilderFactory(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); DOMImplementation domImpl = docBuilder.getDOMImplementation(); Document doc = createDocument(domImpl); @@ -166,7 +167,7 @@ public class VsmCommand { public static String getDeletePortProfile(String portName) { try { // Create the document and root element. - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory docFactory = ParserUtils.getSaferDocumentBuilderFactory(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); DOMImplementation domImpl = docBuilder.getDOMImplementation(); Document doc = createDocument(domImpl); @@ -199,7 +200,7 @@ public class VsmCommand { public static String getAddPolicyMap(String name, int averageRate, int maxRate, int burstRate) { try { // Create the document and root element. - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory docFactory = ParserUtils.getSaferDocumentBuilderFactory(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); DOMImplementation domImpl = docBuilder.getDOMImplementation(); Document doc = createDocument(domImpl); @@ -232,7 +233,7 @@ public class VsmCommand { public static String getDeletePolicyMap(String name) { try { // Create the document and root element. - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory docFactory = ParserUtils.getSaferDocumentBuilderFactory(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); DOMImplementation domImpl = docBuilder.getDOMImplementation(); Document doc = createDocument(domImpl); @@ -265,7 +266,7 @@ public class VsmCommand { public static String getServicePolicy(String policyMap, String portProfile, boolean attach) { try { // Create the document and root element. - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory docFactory = ParserUtils.getSaferDocumentBuilderFactory(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); DOMImplementation domImpl = docBuilder.getDOMImplementation(); Document doc = createDocument(domImpl); @@ -297,7 +298,7 @@ public class VsmCommand { public static String getPortProfile(String name) { try { - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory docFactory = ParserUtils.getSaferDocumentBuilderFactory(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); DOMImplementation domImpl = docBuilder.getDOMImplementation(); Document doc = createDocument(domImpl); @@ -334,7 +335,7 @@ public class VsmCommand { public static String getPolicyMap(String name) { try { - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory docFactory = ParserUtils.getSaferDocumentBuilderFactory(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); DOMImplementation domImpl = docBuilder.getDOMImplementation(); Document doc = createDocument(domImpl); @@ -367,7 +368,7 @@ public class VsmCommand { public static String getHello() { try { - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory docFactory = ParserUtils.getSaferDocumentBuilderFactory(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); DOMImplementation domImpl = docBuilder.getDOMImplementation(); @@ -395,7 +396,7 @@ public class VsmCommand { public static String getVServiceNode(String vlanId, String ipAddr) { try { // Create the document and root element. - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory docFactory = ParserUtils.getSaferDocumentBuilderFactory(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); DOMImplementation domImpl = docBuilder.getDOMImplementation(); Document doc = createDocument(domImpl); From ca64406a8805a9292641c49efe5443b080e73f6a Mon Sep 17 00:00:00 2001 From: Manoj Kumar Date: Mon, 5 Jan 2026 12:49:03 +0530 Subject: [PATCH 7/7] replace momentjs with dayjs and use watch instead of update (#12351) --- ui/src/components/view/DateTimeFilter.vue | 43 +++++++++++------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/ui/src/components/view/DateTimeFilter.vue b/ui/src/components/view/DateTimeFilter.vue index aca958f58f7..efac3b43eee 100644 --- a/ui/src/components/view/DateTimeFilter.vue +++ b/ui/src/components/view/DateTimeFilter.vue @@ -61,7 +61,7 @@