Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
09e5ce2
merge
Dajeong-Park Dec 15, 2025
61e5f3d
test
Dajeong-Park Dec 30, 2025
905bddc
Merge branch 'ablestack-europa' of https://github.com/Dajeong-Park/ab…
Dajeong-Park Dec 30, 2025
dc78df0
Update Status.vue
Dajeong-Park Dec 30, 2025
c6cbae3
Merge branch 'ablecloud-team:ablestack-europa' into ablestack-europa
Dajeong-Park Jan 7, 2026
572eaac
Merge branch 'ablecloud-team:ablestack-europa' into ablestack-europa
Dajeong-Park Jan 8, 2026
54b68d4
Update Agent.java
Dajeong-Park Jan 9, 2026
a0ad38d
Revert "Update Agent.java"
Dajeong-Park Jan 9, 2026
5f525fe
Merge branch 'ablecloud-team:ablestack-europa' into ablestack-europa
Dajeong-Park Jan 12, 2026
69bb30e
Fix regression in the listBackupSchedule API
Dajeong-Park Jan 15, 2026
311fa9e
빌드오류 수정
Dajeong-Park Jan 15, 2026
163dc88
백업 일정 생성 시 가상머신 선택 화면이 호출되지 않는 오류 수정
Dajeong-Park Jan 15, 2026
15f81d2
볼륨 연결 시 cacheMode 직접 주입 테스트
Dajeong-Park Jan 15, 2026
fa6c329
Revert "볼륨 연결 시 cacheMode 직접 주입 테스트"
Dajeong-Park Jan 15, 2026
d3e1011
복원시 rbd인 경우 xml파일에 cacheMode 추가 (테스트)
Dajeong-Park Jan 16, 2026
00afb77
Update NASBackupProvider.java
Dajeong-Park Jan 16, 2026
7b9c5bd
연결할 가상머신의 ROOT디스크와 동일한 캐시모드로 적용하도록 변경
Dajeong-Park Jan 16, 2026
3703229
null인 경우 None으로 주입 추가
Dajeong-Park Jan 16, 2026
3bd5518
Update NASBackupProvider.java
Dajeong-Park Jan 16, 2026
0ac4c23
Update ListBackupScheduleCmd.java
Dajeong-Park Jan 16, 2026
fc815ce
백업 관련 이벤트 항목 번역 추가
Dajeong-Park Jan 20, 2026
770dd47
백업 일정 생성 확인 버튼 누른 후 완료되면 모달 닫히며 리스트 refresh 추가
Dajeong-Park Jan 20, 2026
b8610a2
백업 실행시 메세지 오류 수정
Dajeong-Park Jan 21, 2026
6aafd39
백업 오퍼링 관련 이벤트 항목 번역 추가
Dajeong-Park Jan 21, 2026
ac3ddb9
재수정
Dajeong-Park Jan 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion agent/src/main/java/com/cloud/agent/Agent.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.SynchronousQueue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class RestoreBackupCommand extends Command {
private String restoreVolumeUUID;
private VirtualMachine.State vmState;
private Integer mountTimeout;
private String cacheMode;

protected RestoreBackupCommand() {
super();
Expand Down Expand Up @@ -155,4 +156,12 @@ public Integer getMountTimeout() {
public void setMountTimeout(Integer mountTimeout) {
this.mountTimeout = mountTimeout;
}

public String getCacheMode() {
return cacheMode;
}

public void setCacheMode(String cacheMode) {
this.cacheMode = cacheMode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.Type;
import com.cloud.storage.VolumeApiServiceImpl;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
Expand All @@ -39,6 +40,7 @@
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.snapshot.VMSnapshot;
import com.cloud.vm.snapshot.VMSnapshotDetailsVO;
Expand Down Expand Up @@ -370,6 +372,16 @@ private String getVolumePathPrefix(StoragePoolVO storagePool) {
public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, Backup.VolumeInfo backupVolumeInfo, String hostIp, String dataStoreUuid, Pair<String, VirtualMachine.State> vmNameAndState) {
final VolumeVO volume = volumeDao.findByUuid(backupVolumeInfo.getUuid());
final DiskOffering diskOffering = diskOfferingDao.findByUuid(backupVolumeInfo.getDiskOfferingId());
String cacheMode = null;
final VMInstanceVO vm = vmInstanceDao.findVMByInstanceName(vmNameAndState.first());
List<VolumeVO> listVolumes = volumeDao.findByInstanceAndType(vm.getId(), Type.ROOT);
if(CollectionUtils.isNotEmpty(listVolumes)) {
VolumeVO rootDisk = listVolumes.get(0);
DiskOffering baseDiskOffering = diskOfferingDao.findById(rootDisk.getDiskOfferingId());
if (baseDiskOffering.getCacheMode() != null) {
cacheMode = baseDiskOffering.getCacheMode().toString();
}
}
final StoragePoolVO pool = primaryDataStoreDao.findByUuid(dataStoreUuid);
final HostVO hostVO = hostDao.findByIp(hostIp);

Expand Down Expand Up @@ -413,6 +425,7 @@ public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, Backup.VolumeI
restoreCommand.setVmState(vmNameAndState.second());
restoreCommand.setRestoreVolumeUUID(backupVolumeInfo.getUuid());
restoreCommand.setMountTimeout(NASBackupRestoreMountTimeout.value());
restoreCommand.setCacheMode(cacheMode);

BackupAnswer answer;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public Answer execute(RestoreBackupCommand command, LibvirtComputingResource ser
String restoreVolumeUuid = command.getRestoreVolumeUUID();
Integer mountTimeout = command.getMountTimeout() * 1000;
int timeout = command.getWait();
String cacheMode = command.getCacheMode();
KVMStoragePoolManager storagePoolMgr = serverResource.getStoragePoolMgr();

String newVolumeId = null;
Expand All @@ -86,7 +87,7 @@ public Answer execute(RestoreBackupCommand command, LibvirtComputingResource ser
int lastIndex = volumePath.lastIndexOf("/");
newVolumeId = volumePath.substring(lastIndex + 1);
restoreVolume(storagePoolMgr, backupPath, volumePool, volumePath, diskType, restoreVolumeUuid,
new Pair<>(vmName, command.getVmState()), mountDirectory, timeout);
new Pair<>(vmName, command.getVmState()), mountDirectory, timeout, cacheMode);
} else if (Boolean.TRUE.equals(vmExists)) {
restoreVolumesOfExistingVM(storagePoolMgr, restoreVolumePools, restoreVolumePaths, backedVolumeUUIDs, backupPath, mountDirectory, timeout);
} else {
Expand Down Expand Up @@ -150,7 +151,7 @@ private void restoreVolumesOfDestroyedVMs(KVMStoragePoolManager storagePoolMgr,
}

private void restoreVolume(KVMStoragePoolManager storagePoolMgr, String backupPath, PrimaryDataStoreTO volumePool, String volumePath, String diskType, String volumeUUID,
Pair<String, VirtualMachine.State> vmNameAndState, String mountDirectory, int timeout) {
Pair<String, VirtualMachine.State> vmNameAndState, String mountDirectory, int timeout, String cacheMode) {
Pair<String, String> bkpPathAndVolUuid;
try {
bkpPathAndVolUuid = getBackupPath(mountDirectory, volumePath, backupPath, diskType, volumeUUID);
Expand All @@ -159,7 +160,7 @@ private void restoreVolume(KVMStoragePoolManager storagePoolMgr, String backupPa
throw new CloudRuntimeException(String.format("Unable to restore contents from the backup volume [%s].", bkpPathAndVolUuid.second()));
}
if (VirtualMachine.State.Running.equals(vmNameAndState.second())) {
if (!attachVolumeToVm(storagePoolMgr, vmNameAndState.first(), volumePool, volumePath)) {
if (!attachVolumeToVm(storagePoolMgr, vmNameAndState.first(), volumePool, volumePath, cacheMode)) {
throw new CloudRuntimeException(String.format("Failed to attach volume to VM: %s", vmNameAndState.first()));
}
}
Expand Down Expand Up @@ -284,13 +285,13 @@ private boolean replaceRbdVolumeWithBackup(KVMStoragePoolManager storagePoolMgr,
return true;
}

private boolean attachVolumeToVm(KVMStoragePoolManager storagePoolMgr, String vmName, PrimaryDataStoreTO volumePool, String volumePath) {
private boolean attachVolumeToVm(KVMStoragePoolManager storagePoolMgr, String vmName, PrimaryDataStoreTO volumePool, String volumePath, String cacheMode) {
String deviceToAttachDiskTo = getDeviceToAttachDisk(vmName);
int exitValue;
if (volumePool.getPoolType() != Storage.StoragePoolType.RBD) {
exitValue = Script.runSimpleBashScriptForExitValue(String.format(ATTACH_QCOW2_DISK_COMMAND, vmName, volumePath, deviceToAttachDiskTo));
} else {
String xmlForRbdDisk = getXmlForRbdDisk(storagePoolMgr, volumePool, volumePath, deviceToAttachDiskTo);
String xmlForRbdDisk = getXmlForRbdDisk(storagePoolMgr, volumePool, volumePath, deviceToAttachDiskTo, cacheMode);
logger.debug("RBD disk xml to attach: {}", xmlForRbdDisk);
exitValue = Script.runSimpleBashScriptForExitValue(String.format(ATTACH_RBD_DISK_XML_COMMAND, vmName, xmlForRbdDisk));
}
Expand All @@ -304,13 +305,19 @@ private String getDeviceToAttachDisk(String vmName) {
return currentDevice.substring(0, currentDevice.length() - 1) + incrementedChar;
}

private String getXmlForRbdDisk(KVMStoragePoolManager storagePoolMgr, PrimaryDataStoreTO volumePool, String volumePath, String deviceToAttachDiskTo) {
private String getXmlForRbdDisk(KVMStoragePoolManager storagePoolMgr, PrimaryDataStoreTO volumePool, String volumePath, String deviceToAttachDiskTo, String cacheMode) {
StringBuilder diskBuilder = new StringBuilder();
diskBuilder.append("\n<disk ");
diskBuilder.append(" device='disk'");
diskBuilder.append(" type='network'");
diskBuilder.append(">\n");

diskBuilder.append("<driver name='qemu' type='raw'");
if (StringUtils.isBlank(cacheMode)) {
cacheMode = "none";
}
diskBuilder.append(" cache='").append(cacheMode).append("'/> \n");

diskBuilder.append("<source ");
diskBuilder.append(" protocol='rbd'");
diskBuilder.append(" name='" + volumePath + "'");
Expand Down
2 changes: 2 additions & 0 deletions ui/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4830,6 +4830,8 @@
"backup.schedule.delete": "BACKUP.SCHEDULE.DELETE",
"backup.usage.metric": "BACKUP.USAGE.METRIC",
"backup.offering.edit": "BACKUP.OFFERING.EDIT",
"backup.repository.add": "BACKUP.REPOSITORY.ADD",
"backup.repository.update": "BACKUP.REPOSITORY.UPDATE",
"physical.nvpcontroller.add": "PHYSICAL.NVPCONTROLLER.ADD",
"physical.nvpcontroller.delete": "PHYSICAL.NVPCONTROLLER.DELETE",
"physical.nvpcontroller.configure": "PHYSICAL.NVPCONTROLLER.CONFIGURE",
Expand Down
2 changes: 2 additions & 0 deletions ui/public/locales/ko_KR.json
Original file line number Diff line number Diff line change
Expand Up @@ -4466,6 +4466,8 @@
"backup.schedule.delete": "\ubc31\uc5c5 \uc77c\uc815 \uc0ad\uc81c",
"backup.usage.metric": "\ubc31\uc5c5 \uc0ac\uc6a9\ub7c9 \uba54\ud2b8\ub9ad",
"backup.offering.edit": "\ubc31\uc5c5 \uc624\ud37c\ub9c1 \ud3b8\uc9d1",
"backup.repository.add": "\ubc31\uc5c5 \uc800\uc7a5\uc18c \ucd94\uac00",
"backup.repository.update": "\ubc31\uc5c5 \uc800\uc7a5\uc18c \ud3b8\uc9d1",
"physical.nvpcontroller.add": "\ubb3c\ub9ac NVP\ucee8\ud2b8\ub864\ub7ec \ucd94\uac00",
"physical.nvpcontroller.delete": "\ubb3c\ub9ac NVP\ucee8\ud2b8\ub864\ub7ec \uc0ad\uc81c",
"physical.nvpcontroller.configure": "\ubb3c\ub9ac NVP\ucee8\ud2b8\ub864\ub7ec \uad6c\uc131",
Expand Down
2 changes: 1 addition & 1 deletion ui/src/views/compute/StartBackup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export default {
postAPI('createBackup', data).then(response => {
this.$pollJob({
jobId: response.createbackupresponse.jobid,
title: this.$t('label.create.bucket'),
title: this.$t('label.create.backup'),
description: values.name,
errorMessage: this.$t('message.create.backup.failed'),
loadingMessage: `${this.$t('label.create.backup')}: ${this.resource.name || this.resource.id}`,
Expand Down
50 changes: 4 additions & 46 deletions ui/src/views/compute/backup/CreateBackupSchedule.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

<template>
<div class="create-backup-schedule-layout">
<div v-if="!isVMResource" class="vm-selection">
<div class="vm-selection">
<a-form layout="vertical">
<a-form-item :label="$t('label.virtualmachine')" required>
<a-select
Expand All @@ -39,15 +39,15 @@
</a-form-item>
</a-form>
</div>
<div v-if="currentVMResource && currentVMResource.id">
<div v-if="selectedVM && selectedVM.id">
<BackupScheduleWizard
ref="backupScheduleWizard"
:resource="currentVMResource"
:resource="selectedVM"
@close-action="closeAction"
@refresh="handleRefresh"
/>
</div>
<div v-if="!currentVMResource || !currentVMResource.id" class="no-vm-selected">
<div v-else class="no-vm-selected">
<div class="empty-state">
<p>{{ $t('message.select.vm.to.continue') }}</p>
</div>
Expand All @@ -64,14 +64,6 @@ export default {
components: {
BackupScheduleWizard
},
props: {
resource: {
type: Object,
required: false,
default: () => null
}
},
inject: ['parentFetchData'],
data () {
return {
vms: [],
Expand All @@ -80,39 +72,6 @@ export default {
selectedVM: null
}
},
computed: {
resourceType () {
if (!this.resource) return 'none'

if (this.resource.vmstate !== undefined ||
this.resource.guestosid !== undefined ||
this.resource.hypervisor !== undefined ||
this.resource.backupofferingid !== undefined ||
this.resource.serviceofferingid !== undefined) {
return 'vm'
}
if (this.resource.intervaltype !== undefined &&
this.resource.schedule !== undefined) {
return 'backupschedule'
}

if (this.resource.virtualmachineid !== undefined) {
return 'backupschedule'
}

return 'unknown'
},
isVMResource () {
return this.resourceType === 'vm'
},
currentVMResource () {
if (this.isVMResource) {
return this.resource
} else {
return this.selectedVM
}
}
},
created () {
this.fetchVMs()
},
Expand Down Expand Up @@ -145,7 +104,6 @@ export default {
},
handleRefresh () {
this.$emit('refresh')
this.parentFetchData()
},
filterOption (input, option) {
return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
Expand Down
1 change: 1 addition & 0 deletions ui/src/views/compute/backup/FormSchedule.vue
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ export default {
description: this.$t('message.success.config.backup.schedule')
})
this.refreshSchedule()
this.closeSchedule()
this.resetForm()
}).catch(error => {
this.$notifyError(error)
Expand Down
Loading