Skip to content

Commit ca41556

Browse files
committed
Merge remote-tracking branch 'apache/main'
2 parents 71720b3 + f07b7d8 commit ca41556

7 files changed

Lines changed: 70 additions & 46 deletions

File tree

agent/conf/agent.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ iscsi.session.cleanup.enabled=false
316316
#vm.migrate.domain.retrieve.timeout=10
317317

318318
# This parameter specifies if the host must be rebooted when something goes wrong with the heartbeat.
319-
#reboot.host.and.alert.management.on.heartbeat.timeout=true
319+
#reboot.host.and.alert.management.on.heartbeat.timeout=false
320320

321321
# Enables manually setting CPU's topology on KVM's VM.
322322
#enable.manually.setting.cpu.topology.on.kvm.vm=true

agent/src/main/java/com/cloud/agent/properties/AgentProperties.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -616,10 +616,10 @@ public class AgentProperties{
616616
/**
617617
* This parameter specifies if the host must be rebooted when something goes wrong with the heartbeat.<br>
618618
* Data type: Boolean.<br>
619-
* Default value: <code>true</code>
619+
* Default value: <code>false</code>
620620
*/
621621
public static final Property<Boolean> REBOOT_HOST_AND_ALERT_MANAGEMENT_ON_HEARTBEAT_TIMEOUT
622-
= new Property<>("reboot.host.and.alert.management.on.heartbeat.timeout", true);
622+
= new Property<>("reboot.host.and.alert.management.on.heartbeat.timeout", false);
623623

624624
/**
625625
* Enables manually setting CPU's topology on KVM's VM. <br>

engine/schema/src/main/resources/META-INF/db/schema-42210to42300.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ CREATE TABLE `cloud`.`backup_offering_details` (
3434
UPDATE `cloud`.`configuration` SET value='random' WHERE name IN ('vm.allocation.algorithm', 'volume.allocation.algorithm') AND value='userconcentratedpod_random';
3535
UPDATE `cloud`.`configuration` SET value='firstfit' WHERE name IN ('vm.allocation.algorithm', 'volume.allocation.algorithm') AND value='userconcentratedpod_firstfit';
3636

37+
-- Add Windows Server 2025 guest OS and mappings
38+
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2025 (64-bit)', 'VMware', '7.0', 'windows2022srvNext_64Guest');
39+
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2025 (64-bit)', 'VMware', '7.0.1.0', 'windows2022srvNext_64Guest');
40+
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2025 (64-bit)', 'VMware', '7.0.2.0', 'windows2022srvNext_64Guest');
41+
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2025 (64-bit)', 'VMware', '7.0.3.0', 'windows2022srvNext_64Guest');
42+
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2025 (64-bit)', 'VMware', '8.0', 'windows2022srvNext_64Guest');
43+
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2025 (64-bit)', 'VMware', '8.0.0.1', 'windows2022srvNext_64Guest');
44+
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2025 (64-bit)', 'VMware', '8.0.0.2', 'windows2022srvNext_64Guest');
45+
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2025 (64-bit)', 'VMware', '8.0.0.3', 'windows2022srvNext_64Guest');
46+
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2025 (64-bit)', 'VMware', '8.0.1', 'windows2022srvNext_64Guest');
47+
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2025 (64-bit)', 'VMware', '8.0.2', 'windows2022srvNext_64Guest');
48+
CALL ADD_GUEST_OS_AND_HYPERVISOR_MAPPING (6, 'Windows Server 2025 (64-bit)', 'VMware', '8.0.3', 'windows2022srvNext_64Guest');
49+
3750
-- Create kubernetes_cluster_affinity_group_map table for CKS per-node-type affinity groups
3851
CREATE TABLE IF NOT EXISTS `cloud`.`kubernetes_cluster_affinity_group_map` (
3952
`id` bigint unsigned NOT NULL AUTO_INCREMENT,

plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/request/ListQuery.java

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.util.List;
2323
import java.util.Map;
2424
import java.util.stream.Collectors;
25+
import java.util.regex.Matcher;
26+
import java.util.regex.Pattern;
2527

2628
import javax.servlet.http.HttpServletRequest;
2729

@@ -31,6 +33,8 @@
3133
import org.jetbrains.annotations.NotNull;
3234

3335
public class ListQuery {
36+
private static final Pattern PAGE_CLAUSE_PATTERN = Pattern.compile("(?i)\\bpage\\s+(\\d+)\\b");
37+
3438
boolean allContent;
3539
Long max;
3640
Long page;
@@ -53,6 +57,14 @@ public void setMax(Long max) {
5357
this.max = max;
5458
}
5559

60+
public Long getPage() {
61+
return page;
62+
}
63+
64+
public void setPage(Long page) {
65+
this.page = page;
66+
}
67+
5668
public void setSearch(Map<String, String> search) {
5769
this.search = search;
5870
}
@@ -108,50 +120,33 @@ public static ListQuery fromRequest(HttpServletRequest request) {
108120
query.setFollow(follow);
109121
Map<String, String> searchItems = getSearchMap(request.getParameter("search"));
110122
if (!searchItems.isEmpty()) {
111-
try {
112-
query.setMax(Long.parseLong(searchItems.get("page")));
113-
} catch (NumberFormatException e) {
114-
// Ignore invalid page and keep default null value.
123+
String pageValue = searchItems.get("page");
124+
if (StringUtils.isNotBlank(pageValue)) {
125+
try {
126+
query.setPage(Long.parseLong(pageValue));
127+
} catch (NumberFormatException e) {
128+
// Ignore invalid page and keep default null value.
129+
}
115130
}
116131
query.setSearch(searchItems);
117132
}
118133

119134
return query;
120135
}
121136

122-
// Parse search clause. Only keep items which use simple '=' operator, and ignore others. For example:
123-
// name=myvm and status=up --> {name=myvm, status=up}
124-
// name=myvm and status!=down --> {name=myvm} (ignore status!=down because it uses '!=' operator)
137+
// Parse search clause. For now, only extract the oVirt paging clause.
138+
// Examples:
139+
// page 3 --> {page=3}
140+
// sortby name page 2 --> {page=2}
125141
@NotNull
126142
private static Map<String, String> getSearchMap(String searchClause) {
127143
Map<String, String> searchItems = new LinkedHashMap<>();
128144
if (StringUtils.isBlank(searchClause)) {
129145
return searchItems;
130146
}
131-
String[] terms = searchClause.trim().split("(?i)\\s+and\\s+");
132-
for (String term : terms) {
133-
if (term == null) {
134-
continue;
135-
}
136-
String trimmedTerm = term.trim();
137-
if (trimmedTerm.isEmpty()) {
138-
continue;
139-
}
140-
141-
int eqIdx = trimmedTerm.indexOf('=');
142-
if (eqIdx <= 0 || eqIdx != trimmedTerm.lastIndexOf('=')) {
143-
continue;
144-
}
145-
char prev = trimmedTerm.charAt(eqIdx - 1);
146-
if (prev == '!' || prev == '<' || prev == '>') {
147-
continue;
148-
}
149-
150-
String key = trimmedTerm.substring(0, eqIdx).trim();
151-
String value = trimmedTerm.substring(eqIdx + 1).trim();
152-
if (!key.isEmpty() && !value.isEmpty()) {
153-
searchItems.put(key, value);
154-
}
147+
Matcher matcher = PAGE_CLAUSE_PATTERN.matcher(searchClause);
148+
if (matcher.find()) {
149+
searchItems.put("page", matcher.group(1));
155150
}
156151
return searchItems;
157152
}

plugins/integrations/veeam-control-service/src/test/java/org/apache/cloudstack/veeam/api/request/ListQueryTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,18 @@ public void testFromRequest_ParsesAllContentMaxAndFollow() {
6767
}
6868

6969
@Test
70-
public void testFromRequest_SearchParserIgnoresNonEqualsAndUsesPageValueAsMaxCurrentBehavior() {
70+
public void testFromRequest_SearchParserExtractsPageOnly() {
7171
final HttpServletRequest request = mock(HttpServletRequest.class);
72-
when(request.getParameterMap()).thenReturn(Map.of("search", new String[]{"name=vm and page=3 and status!=down and x>=1"}));
72+
when(request.getParameterMap()).thenReturn(Map.of("search", new String[]{"sortby name page 3"}));
7373
when(request.getParameter("all_content")).thenReturn(null);
7474
when(request.getParameter("max")).thenReturn(null);
7575
when(request.getParameter("follow")).thenReturn(null);
76-
when(request.getParameter("search")).thenReturn("name=vm and page=3 and status!=down and x>=1");
76+
when(request.getParameter("search")).thenReturn("sortby name page 3");
7777

7878
final ListQuery query = ListQuery.fromRequest(request);
7979

80-
// Document existing behavior: when search contains page=..., max is set from it.
81-
org.junit.Assert.assertEquals(Long.valueOf(3L), query.getLimit());
80+
// Only page key is extracted from search clause in oVirt format "page N"
81+
org.junit.Assert.assertEquals(Long.valueOf(3L), query.getPage());
8282
}
8383

8484
@Test

scripts/vm/hypervisor/kvm/nasbackup.sh

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ BACKUP_DIR=""
3434
DISK_PATHS=""
3535
QUIESCE=""
3636
logFile="/var/log/cloudstack/agent/agent.log"
37-
37+
UNMOUNT_TIMEOUT=60
3838
EXIT_CLEANUP_FAILED=20
3939

4040
log() {
@@ -167,7 +167,8 @@ backup_running_vm() {
167167
break ;;
168168
Failed)
169169
echo "Virsh backup job failed"
170-
cleanup ;;
170+
cleanup
171+
exit 1 ;;
171172
esac
172173
sleep 5
173174
done
@@ -196,10 +197,10 @@ backup_running_vm() {
196197

197198
# Print statistics
198199
virsh -c qemu:///system domjobinfo $VM --completed
199-
du -sb $dest | cut -f1
200-
201-
umount $mount_point
202-
rmdir $mount_point
200+
backup_size=$(du -sb "$dest" 2>>"$logFile" | cut -f1) || { log -ne "WARNING: du failed for $dest, reporting size as 0"; backup_size=0; }
201+
timeout "$UNMOUNT_TIMEOUT" umount "$mount_point" 2>>"$logFile" || { log "WARNING: umount of $mount_point failed or timed out"; true; }
202+
rmdir "$mount_point" 2>>"$logFile" || { log "WARNING: rmdir of $mount_point failed"; true; }
203+
echo "$backup_size"
203204
}
204205

205206
backup_stopped_vm() {
@@ -221,6 +222,7 @@ backup_stopped_vm() {
221222
if ! qemu-img convert -O qcow2 "$disk" "$output" > "$logFile" 2> >(cat >&2); then
222223
echo "qemu-img convert failed for $disk $output"
223224
cleanup
225+
exit 1
224226
fi
225227
name="datadisk"
226228
done
@@ -265,6 +267,19 @@ mount_operation() {
265267
cleanup() {
266268
local status=0
267269

270+
# Resume the VM if it was paused during backup to prevent it from
271+
# remaining indefinitely paused when the backup job fails (e.g. due
272+
# to storage full or I/O errors on the backup target)
273+
local vm_state
274+
vm_state=$(virsh -c qemu:///system domstate "$VM" 2>/dev/null || true)
275+
if [[ "$vm_state" == "paused" ]]; then
276+
log -ne "Resuming paused VM $VM during backup cleanup"
277+
if ! virsh -c qemu:///system resume "$VM" > /dev/null 2>&1; then
278+
echo "Failed to resume VM $VM"
279+
status=1
280+
fi
281+
fi
282+
268283
rm -rf "$dest" || { echo "Failed to delete $dest"; status=1; }
269284
umount "$mount_point" || { echo "Failed to unmount $mount_point"; status=1; }
270285
rmdir "$mount_point" || { echo "Failed to remove mount point $mount_point"; status=1; }

ui/tests/mockData/Status.mock.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@
9797
"message.guestnetwork.state.disabled": "message.guestnetwork.state.disabled",
9898
"message.guestnetwork.state.migrating": "message.guestnetwork.state.migrating",
9999
"message.guestnetwork.state.alert": "message.guestnetwork.state.alert",
100-
"message.guestnetwork.state.allocated": "message.guestnetwork.state.allocated"
100+
"message.guestnetwork.state.allocated": "message.guestnetwork.state.allocated",
101+
"label.allocated": "Allocated"
101102
}
102103
},
103104
"routes": [

0 commit comments

Comments
 (0)