Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class CommvaultTakeBackupCommand extends Command {
private String backupPath;
private List<PrimaryDataStoreTO> volumePools;
private List<String> volumePaths;
private List<String> volumeUuids;
private Boolean quiesce;

public CommvaultTakeBackupCommand(String vmName, String backupPath) {
Expand Down Expand Up @@ -69,6 +70,14 @@ public void setVolumePaths(List<String> volumePaths) {
this.volumePaths = volumePaths;
}

public List<String> getVolumeUuids() {
return volumeUuids;
}

public void setVolumeUuids(List<String> volumeUuids) {
this.volumeUuids = volumeUuids;
}

public Boolean getQuiesce() {
return quiesce;
}
Expand All @@ -81,4 +90,4 @@ public void setQuiesce(Boolean quiesce) {
public boolean executeInSequence() {
return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class TakeBackupCommand extends Command {
private String backupRepoAddress;
private List<PrimaryDataStoreTO> volumePools;
private List<String> volumePaths;
private List<String> volumeUuids;
private Boolean quiesce;
@LogLevel(LogLevel.Log4jLevel.Off)
private String mountOptions;
Expand Down Expand Up @@ -98,6 +99,14 @@ public void setVolumePaths(List<String> volumePaths) {
this.volumePaths = volumePaths;
}

public List<String> getVolumeUuids() {
return volumeUuids;
}

public void setVolumeUuids(List<String> volumeUuids) {
this.volumeUuids = volumeUuids;
}

public Boolean getQuiesce() {
return quiesce;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,10 +300,11 @@ public Pair<Boolean, Backup> takeBackup(VirtualMachine vm, Boolean quiesceVM) {
BackupVO backupVO = createBackupObject(vm, backupPath);
CommvaultTakeBackupCommand command = new CommvaultTakeBackupCommand(vm.getInstanceName(), backupPath);
command.setQuiesce(quiesceVM);
List<VolumeVO> vmVolumes = volumeDao.findByInstance(vm.getId());
vmVolumes.sort(Comparator.comparing(Volume::getDeviceId));
command.setVolumeUuids(vmVolumes.stream().map(VolumeVO::getUuid).collect(Collectors.toList()));

if (VirtualMachine.State.Stopped.equals(vm.getState())) {
List<VolumeVO> vmVolumes = volumeDao.findByInstance(vm.getId());
vmVolumes.sort(Comparator.comparing(Volume::getDeviceId));
Pair<List<PrimaryDataStoreTO>, List<String>> volumePoolsAndPaths = getVolumePoolsAndPaths(vmVolumes);
command.setVolumePools(volumePoolsAndPaths.first());
command.setVolumePaths(volumePoolsAndPaths.second());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,11 @@ public Pair<Boolean, Backup> takeBackup(final VirtualMachine vm, Boolean quiesce
command.setBackupRepoAddress(backupRepository.getAddress());
command.setMountOptions(backupRepository.getMountOptions());
command.setQuiesce(quiesceVM);
List<VolumeVO> vmVolumes = volumeDao.findByInstance(vm.getId());
vmVolumes.sort(Comparator.comparing(Volume::getDeviceId));
command.setVolumeUuids(vmVolumes.stream().map(VolumeVO::getUuid).collect(Collectors.toList()));

if (VirtualMachine.State.Stopped.equals(vm.getState())) {
List<VolumeVO> vmVolumes = volumeDao.findByInstance(vm.getId());
vmVolumes.sort(Comparator.comparing(Volume::getDeviceId));
Pair<List<PrimaryDataStoreTO>, List<String>> volumePoolsAndPaths = getVolumePoolsAndPaths(vmVolumes);
command.setVolumePools(volumePoolsAndPaths.first());
command.setVolumePaths(volumePoolsAndPaths.second());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public Answer execute(CommvaultTakeBackupCommand command, LibvirtComputingResour
final String backupPath = command.getBackupPath();
List<PrimaryDataStoreTO> volumePools = command.getVolumePools();
final List<String> volumePaths = command.getVolumePaths();
final List<String> volumeUuids = command.getVolumeUuids();
KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();

List<String> diskPaths = new ArrayList<>();
Expand All @@ -70,7 +71,8 @@ public Answer execute(CommvaultTakeBackupCommand command, LibvirtComputingResour
"-v", vmName,
"-p", backupPath,
"-q", command.getQuiesce() != null && command.getQuiesce() ? "true" : "false",
"-d", diskPaths.isEmpty() ? "" : String.join(",", diskPaths)
"-d", diskPaths.isEmpty() ? "" : String.join(",", diskPaths),
"-u", volumeUuids == null || volumeUuids.isEmpty() ? "" : String.join(",", volumeUuids)
});

Pair<Integer, String> result = Script.executePipedCommands(commands, libvirtComputingResource.getCmdsTimeout());
Expand All @@ -88,4 +90,4 @@ public Answer execute(CommvaultTakeBackupCommand command, LibvirtComputingResour
BackupAnswer answer = new BackupAnswer(command, true, "success");
return answer;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public Answer execute(TakeBackupCommand command, LibvirtComputingResource libvir
final String mountOptions = command.getMountOptions();
List<PrimaryDataStoreTO> volumePools = command.getVolumePools();
final List<String> volumePaths = command.getVolumePaths();
final List<String> volumeUuids = command.getVolumeUuids();
KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();

List<String> diskPaths = new ArrayList<>();
Expand Down Expand Up @@ -78,7 +79,8 @@ public Answer execute(TakeBackupCommand command, LibvirtComputingResource libvir
"-m", Objects.nonNull(mountOptions) ? mountOptions : "",
"-p", backupPath,
"-q", command.getQuiesce() != null && command.getQuiesce() ? "true" : "false",
"-d", diskPaths.isEmpty() ? "" : String.join(",", diskPaths)
"-d", diskPaths.isEmpty() ? "" : String.join(",", diskPaths),
"-u", volumeUuids == null || volumeUuids.isEmpty() ? "" : String.join(",", volumeUuids)
});

Pair<Integer, String> result = Script.executePipedCommands(commands, libvirtComputingResource.getCmdsTimeout());
Expand Down Expand Up @@ -110,4 +112,4 @@ public Answer execute(TakeBackupCommand command, LibvirtComputingResource libvir
answer.setSize(backupSize);
return answer;
}
}
}
31 changes: 28 additions & 3 deletions scripts/vm/hypervisor/kvm/cvtbackup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ OP=""
VM=""
BACKUP_DIR=""
DISK_PATHS=""
VOLUME_UUIDS=""
QUIESCE=""
logFile="/var/log/cloudstack/agent/agent.log"

Expand Down Expand Up @@ -90,12 +91,23 @@ sanity_checks() {
backup_running_vm() {
mkdir -p "$dest" || { echo "Failed to create backup directory $dest"; exit 1; }

local -a volume_uuid_arr=()
if [[ -n "$VOLUME_UUIDS" ]]; then
read -r -a volume_uuid_arr <<< "${VOLUME_UUIDS//,/ }"
fi

name="root"
local disk_index=0
echo "<domainbackup mode='push'><disks>" > $dest/backup.xml
for disk in $(virsh -c qemu:///system domblklist $VM --details 2>/dev/null | awk '/disk/{print$3}'); do
volpath=$(virsh -c qemu:///system domblklist $VM --details | awk "/$disk/{print $4}" | sed 's/.*\///')
echo "<disk name='$disk' backup='yes' type='file' backupmode='full'><driver type='qcow2'/><target file='$dest/$name.$volpath.qcow2' /></disk>" >> $dest/backup.xml
volid="$volpath"
if [[ ${#volume_uuid_arr[@]} -gt $disk_index && -n "${volume_uuid_arr[$disk_index]}" ]]; then
volid="${volume_uuid_arr[$disk_index]}"
fi
echo "<disk name='$disk' backup='yes' type='file' backupmode='full'><driver type='qcow2'/><target file='$dest/$name.$volid.qcow2' /></disk>" >> $dest/backup.xml
name="datadisk"
((disk_index+=1))
done
echo "</disks></domainbackup>" >> $dest/backup.xml

Expand Down Expand Up @@ -151,10 +163,17 @@ backup_stopped_vm() {
mkdir -p "$dest" || { echo "Failed to create backup directory $dest"; exit 1; }

IFS=","
local -a volume_uuid_arr=()
if [[ -n "$VOLUME_UUIDS" ]]; then
IFS=',' read -r -a volume_uuid_arr <<< "$VOLUME_UUIDS"
fi

name="root"
local disk_index=0
for disk in $DISK_PATHS; do
if [[ "$disk" == rbd:* ]]; then
if [[ ${#volume_uuid_arr[@]} -gt $disk_index && -n "${volume_uuid_arr[$disk_index]}" ]]; then
volUuid="${volume_uuid_arr[$disk_index]}"
elif [[ "$disk" == rbd:* ]]; then
# disk for rbd => rbd:<pool>/<uuid>:mon_host=<monitor_host>...
# sample: rbd:cloudstack/53d5c355-d726-4d3e-9422-046a503a0b12:mon_host=10.0.1.2...
beforeUuid="${disk#*/}" # Remove up to first slash after rbd:
Expand All @@ -168,6 +187,7 @@ backup_stopped_vm() {
cleanup
fi
name="datadisk"
((disk_index+=1))
done
sync

Expand Down Expand Up @@ -218,6 +238,11 @@ while [[ $# -gt 0 ]]; do
shift
shift
;;
-u|--volumeuuids)
VOLUME_UUIDS="$2"
shift
shift
;;
-h|--help)
usage
shift
Expand Down Expand Up @@ -252,4 +277,4 @@ else
backup_stopped_vm
fi

exit 0
exit 0
31 changes: 28 additions & 3 deletions scripts/vm/hypervisor/kvm/nasbackup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ NAS_ADDRESS=""
MOUNT_OPTS=""
BACKUP_DIR=""
DISK_PATHS=""
VOLUME_UUIDS=""
QUIESCE=""
logFile="/var/log/cloudstack/agent/agent.log"

Expand Down Expand Up @@ -93,12 +94,23 @@ backup_running_vm() {
mount_operation
mkdir -p "$dest" || { echo "Failed to create backup directory $dest"; exit 1; }

local -a volume_uuid_arr=()
if [[ -n "$VOLUME_UUIDS" ]]; then
read -r -a volume_uuid_arr <<< "${VOLUME_UUIDS//,/ }"
fi

name="root"
local disk_index=0
echo "<domainbackup mode='push'><disks>" > $dest/backup.xml
for disk in $(virsh -c qemu:///system domblklist $VM --details 2>/dev/null | awk '/disk/{print$3}'); do
volpath=$(virsh -c qemu:///system domblklist $VM --details | awk "/$disk/{print $4}" | sed 's/.*\///')
echo "<disk name='$disk' backup='yes' type='file' backupmode='full'><driver type='qcow2'/><target file='$dest/$name.$volpath.qcow2' /></disk>" >> $dest/backup.xml
volid="$volpath"
if [[ ${#volume_uuid_arr[@]} -gt $disk_index && -n "${volume_uuid_arr[$disk_index]}" ]]; then
volid="${volume_uuid_arr[$disk_index]}"
fi
echo "<disk name='$disk' backup='yes' type='file' backupmode='full'><driver type='qcow2'/><target file='$dest/$name.$volid.qcow2' /></disk>" >> $dest/backup.xml
name="datadisk"
((disk_index+=1))
done
echo "</disks></domainbackup>" >> $dest/backup.xml

Expand Down Expand Up @@ -162,10 +174,17 @@ backup_stopped_vm() {
mkdir -p "$dest" || { echo "Failed to create backup directory $dest"; exit 1; }

IFS=","
local -a volume_uuid_arr=()
if [[ -n "$VOLUME_UUIDS" ]]; then
IFS=',' read -r -a volume_uuid_arr <<< "$VOLUME_UUIDS"
fi

name="root"
local disk_index=0
for disk in $DISK_PATHS; do
if [[ "$disk" == rbd:* ]]; then
if [[ ${#volume_uuid_arr[@]} -gt $disk_index && -n "${volume_uuid_arr[$disk_index]}" ]]; then
volUuid="${volume_uuid_arr[$disk_index]}"
elif [[ "$disk" == rbd:* ]]; then
# disk for rbd => rbd:<pool>/<uuid>:mon_host=<monitor_host>...
# sample: rbd:cloudstack/53d5c355-d726-4d3e-9422-046a503a0b12:mon_host=10.0.1.2...
beforeUuid="${disk#*/}" # Remove up to first slash after rbd:
Expand All @@ -179,6 +198,7 @@ backup_stopped_vm() {
cleanup
fi
name="datadisk"
((disk_index+=1))
done
sync

Expand Down Expand Up @@ -280,6 +300,11 @@ while [[ $# -gt 0 ]]; do
shift
shift
;;
-u|--volumeuuids)
VOLUME_UUIDS="$2"
shift
shift
;;
-h|--help)
usage
shift
Expand All @@ -305,4 +330,4 @@ elif [ "$OP" = "delete" ]; then
delete_backup
elif [ "$OP" = "stats" ]; then
get_backup_stats
fi
fi
Original file line number Diff line number Diff line change
Expand Up @@ -1702,6 +1702,20 @@ private void syncOutOfBandBackups(final BackupProvider backupProvider, DataCente
backupProvider.syncBackupMetrics(dataCenter.getId());
for (final VMInstanceVO vm : vms) {
try {
Long backupOfferingId = vm.getBackupOfferingId();
if (backupOfferingId == null) {
logger.debug("Skipping VM [{}] because backup offering is not assigned.", vm);
continue;
}
BackupOfferingVO offering = backupOfferingDao.findById(vm.getBackupOfferingId());
if (offering == null) {
logger.debug("Skipping VM [{}] because backup offering [{}] was not found.", vm, backupOfferingId);
continue;
}
if (!backupProvider.getName().equalsIgnoreCase(offering.getProvider())) {
logger.debug("Skipping VM [{}] because backup offering provider [{}] does not match current provider [{}].", vm, offering.getProvider(), backupProvider.getName());
continue;
}
logger.debug(String.format("Trying to sync backups of VM [%s] using backup provider [%s].", vm, backupProvider.getName()));
// Sync out-of-band backups
syncBackups(backupProvider, vm);
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 {
api('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
Loading