This is an automated email from the ASF dual-hosted git repository. weizhou pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit 8089d32740320171f63d3f66d0abd429f455caf5 Merge: 3d6ec29c9bb 7044564bab1 Author: Wei Zhou <weiz...@apache.org> AuthorDate: Tue Sep 9 19:50:22 2025 +0200 Merge remote-tracking branch 'apache/4.20' .../snapshot/CreateSnapshotFromVMSnapshotCmd.java | 5 ++ .../hypervisor/kvm/resource/BridgeVifDriver.java | 27 ++++--- .../kvm/resource/LibvirtDomainXMLParser.java | 34 ++++++++ .../hypervisor/kvm/resource/LibvirtVMDef.java | 4 +- ...LibvirtGetUnmanagedInstancesCommandWrapper.java | 6 ++ .../kvm/resource/BridgeVifDriverTest.java | 58 ++++++++++++-- .../kvm/resource/LibvirtDomainXMLParserTest.java | 90 ++++++++++++++++++++++ .../cluster/KubernetesClusterManagerImpl.java | 35 ++++++--- .../lb/InternalLoadBalancerVMManagerImpl.java | 4 + .../internallbvmmgr/InternalLBVMServiceTest.java | 16 +++- .../datastore/adapter/primera/PrimeraAdapter.java | 38 +++++++++ .../auth/TotpUserTwoFactorAuthenticator.java | 4 +- .../cloud/api/query/dao/TemplateJoinDaoImpl.java | 6 +- .../configuration/ConfigurationManagerImpl.java | 4 - .../com/cloud/resource/ResourceManagerImpl.java | 6 ++ .../storage/snapshot/SnapshotManagerImpl.java | 2 + .../vm/schedule/VMScheduleManagerImpl.java | 54 ++++++++----- .../template-base_aarch64-target_aarch64.json | 2 +- .../template-base_x86_64-target_aarch64.json | 2 +- .../template-base_x86_64-target_x86_64.json | 2 +- ui/src/components/view/ListView.vue | 12 ++- ui/src/store/modules/user.js | 12 ++- ui/src/views/AutogenView.vue | 6 +- ui/src/views/compute/ScaleVM.vue | 4 +- ui/src/views/image/RegisterOrUploadIso.vue | 45 +++++++---- 25 files changed, 390 insertions(+), 88 deletions(-) diff --cc plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/BridgeVifDriver.java index 98107c8609e,3b66529ccaf..1635ab03837 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/BridgeVifDriver.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/BridgeVifDriver.java @@@ -295,9 -298,9 +302,9 @@@ public class BridgeVifDriver extends Vi return "brvx-" + vnetId; } - private String createVnetBr(String vNetId, String pifKey, String protocol) throws InternalErrorException { + protected String createVnetBr(String vNetId, String pifKey, String protocol) throws InternalErrorException { String nic = _pifs.get(pifKey); - if (nic == null || protocol.equals(Networks.BroadcastDomainType.Vxlan.scheme())) { + if (nic == null || isVxlanOrNetris(protocol)) { // if not found in bridge map, maybe traffic label refers to pif already? File pif = new File("/sys/class/net/" + pifKey); if (pif.isDirectory()) { diff --cc server/src/main/java/com/cloud/resource/ResourceManagerImpl.java index 27e7f27ae0e,2ef7f4b6637..c4983e871da --- a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java @@@ -1399,7 -1274,9 +1399,9 @@@ public class ResourceManagerImpl extend } @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_MAINTENANCE_CANCEL, eventDescription = "cancel maintenance for host", async = true) - public Host cancelMaintenance(final CancelMaintenanceCmd cmd) { + public Host cancelMaintenance(final CancelHostMaintenanceCmd cmd) { final Long hostId = cmd.getId(); // verify input parameters @@@ -1628,7 -1504,9 +1632,9 @@@ } @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_MAINTENANCE_PREPARE, eventDescription = "prepare maintenance for host", async = true) - public Host maintain(final PrepareForMaintenanceCmd cmd) { + public Host maintain(final PrepareForHostMaintenanceCmd cmd) { final Long hostId = cmd.getId(); final HostVO host = _hostDao.findById(hostId); diff --cc ui/src/components/view/ListView.vue index f4acba595b9,0109784047a..141dfd69530 --- a/ui/src/components/view/ListView.vue +++ b/ui/src/components/view/ListView.vue @@@ -656,17 -362,17 +656,21 @@@ </template> </template> <template v-if="column.key === 'resource'"> - <resource-label :resourceType="record.resourcetype" :resourceId="record.resourceid" :resourceName="record.resourcename" /> + <resource-label + :resourceType="record.resourcetype" + :resourceId="record.resourceid" + :resourceName="record.resourcename" + /> </template> <template v-if="column.key === 'domain'"> - <router-link - v-if="record.domainid && !record.domainid.toString().includes(',') && $store.getters.userInfo.roletype !== 'User'" - :to="{ path: '/domain/' + record.domainid, query: { tab: 'details' } }" - >{{ text }}</router-link> + <span v-if="record.domainid && $store.getters.userInfo.roletype !== 'User'"> + <template v-for="(id, idx) in record.domainid.split(',')" :key="id"> + <router-link :to="{ path: '/domain/' + id, query: { tab: 'details' } }"> + {{ record.domain.split(',')[idx] || id }} + </router-link> + <span v-if="idx < record.domainid.split(',').length - 1">, </span> + </template> + </span> <span v-else>{{ text }}</span> </template> <template v-if="column.key === 'domainpath'"> diff --cc ui/src/views/AutogenView.vue index 27d36cdf58a,6b57e0f6ea0..c77e732ec8c --- a/ui/src/views/AutogenView.vue +++ b/ui/src/views/AutogenView.vue @@@ -1879,11 -1723,12 +1879,13 @@@ export default const query = Object.assign({}, this.$route.query) delete query.templatefilter delete query.isofilter - delete query.account - delete query.domainid delete query.state delete query.annotationfilter + delete query.leased + if (!['publicip'].includes(this.$route.name)) { + delete query.account + delete query.domainid + } if (this.$route.name === 'template') { query.templatefilter = filter } else if (this.$route.name === 'iso') { diff --cc ui/src/views/compute/ScaleVM.vue index a040a81d32b,7113e3f2c09..ce8dca5b43a --- a/ui/src/views/compute/ScaleVM.vue +++ b/ui/src/views/compute/ScaleVM.vue @@@ -225,11 -223,11 +225,11 @@@ export default this.selectedOffering = this.offeringsMap[id] this.selectedDiskOffering = null if (this.selectedOffering.diskofferingid) { - api('listDiskOfferings', { + getAPI('listDiskOfferings', { id: this.selectedOffering.diskofferingid }).then(response => { - const diskOfferings = response.listdiskofferingsresponse.diskoffering || [] - if (this.diskOfferings) { + const diskOfferings = response?.listdiskofferingsresponse?.diskoffering || [] + if (diskOfferings?.length > 0) { this.selectedDiskOffering = diskOfferings[0] } }).catch(error => {