FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

NAS backup: compression, encryption, bandwidth throttle, integrity check by jmsperu · Pull Request #12898 · apache/cloudstack · GitHub

Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .java  (9) .sh  (1) All 2 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ public void setVmState(VirtualMachine.State vmState) {

@LogLevel(LogLevel.Log4jLevel.Off)
private String mountOptions;
/** LUKS passphrase for backups taken with nas.backup.encryption.enabled; null for plain backups. Never logged. */
@LogLevel(LogLevel.Log4jLevel.Off)
private String encryptionPassphrase;
@Override

public boolean executeInSequence() {
Expand All @@ -153,6 +156,14 @@ public List<String> getBackupVolumesUUIDs() {
return backupVolumesUUIDs;
}

public String getEncryptionPassphrase() {
return encryptionPassphrase;
}

public void setEncryptionPassphrase(String encryptionPassphrase) {
this.encryptionPassphrase = encryptionPassphrase;
}

public void setBackupVolumesUUIDs(List<String> backupVolumesUUIDs) {
this.backupVolumesUUIDs = backupVolumesUUIDs;
}
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,20 @@
import com.cloud.agent.api.LogLevel;
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TakeBackupCommand extends Command {
// Detail-map keys shared between the management server (NASBackupProvider) and
// the KVM agent wrapper. Defining them once here avoids drift between producer
// and consumer when a key is renamed.
public static final String DETAIL_COMPRESSION = "compression";
public static final String DETAIL_ENCRYPTION = "encryption";
public static final String DETAIL_ENCRYPTION_PASSPHRASE = "encryption_passphrase";
public static final String DETAIL_BANDWIDTH_LIMIT = "bandwidth_limit";
public static final String DETAIL_INTEGRITY_CHECK = "integrity_check";

private String vmName;
private String backupPath;
private String backupRepoType;
Expand All @@ -35,6 +46,8 @@ public class TakeBackupCommand extends Command {
private Boolean quiesce;
@LogLevel(LogLevel.Log4jLevel.Off)
private String mountOptions;
Comment thread
jmsperu marked this conversation as resolved.
@LogLevel(LogLevel.Log4jLevel.Off)
private Map<String, String> details = new HashMap<>();

public TakeBackupCommand(String vmName, String backupPath) {
super();
Expand Down Expand Up @@ -106,6 +119,18 @@ public void setQuiesce(Boolean quiesce) {
this.quiesce = quiesce;
}

public Map<String, String> getDetails() {
return details;
}

public void setDetails(Map<String, String> details) {
this.details = details != null ? details : new HashMap<>();
}

public void addDetail(String key, String value) {
this.details.put(key, value);
}

@Override
public boolean executeInSequence() {
return true;
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,46 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
true,
BackupFrameworkEnabled.key());

ConfigKey<Boolean> NASBackupCompressionEnabled = new ConfigKey<>("Advanced", Boolean.class,
"nas.backup.compression.enabled",
"false",
"Enable qcow2 compression for NAS backup files.",
true,
ConfigKey.Scope.Zone,
BackupFrameworkEnabled.key());

ConfigKey<Boolean> NASBackupEncryptionEnabled = new ConfigKey<>("Advanced", Boolean.class,
"nas.backup.encryption.enabled",
"false",
"Enable LUKS encryption for NAS backup files.",
true,
ConfigKey.Scope.Zone,
BackupFrameworkEnabled.key());

ConfigKey<String> NASBackupEncryptionPassphrase = new ConfigKey<>("Secure", String.class,
"nas.backup.encryption.passphrase",
"",
"Passphrase for LUKS encryption of NAS backup files. Required when encryption is enabled.",
true,
ConfigKey.Scope.Zone,
BackupFrameworkEnabled.key());

ConfigKey<Integer> NASBackupBandwidthLimitMbps = new ConfigKey<>("Advanced", Integer.class,
"nas.backup.bandwidth.limit.mbps",
"0",
"Bandwidth limit in MiB/s for backup operations (0 = unlimited).",
true,
ConfigKey.Scope.Zone,
BackupFrameworkEnabled.key());

ConfigKey<Boolean> NASBackupIntegrityCheckEnabled = new ConfigKey<>("Advanced", Boolean.class,
"nas.backup.integrity.check",
"false",
"Run qemu-img check on backup files after creation to verify integrity.",
true,
ConfigKey.Scope.Zone,
BackupFrameworkEnabled.key());

@Inject
private BackupDao backupDao;

Expand Down Expand Up @@ -206,6 +246,9 @@ public Pair<Boolean, Backup> takeBackup(final VirtualMachine vm, Boolean quiesce
command.setMountOptions(backupRepository.getMountOptions());
command.setQuiesce(quiesceVM);

// Pass optional backup enhancement settings from zone-scoped configs
applyBackupEnhancementDetails(command, vm.getDataCenterId());

if (VirtualMachine.State.Stopped.equals(vm.getState())) {
List<VolumeVO> vmVolumes = volumeDao.findByInstance(vm.getId());
vmVolumes.sort(Comparator.comparing(Volume::getDeviceId));
Expand Down Expand Up @@ -254,6 +297,32 @@ public Pair<Boolean, Backup> takeBackup(final VirtualMachine vm, Boolean quiesce
}
}

/**
* Translates the zone-scoped backup-enhancement settings (compression, encryption,
* bandwidth limit, integrity check) into details on the {@link TakeBackupCommand}.
* Fails fast if encryption is enabled without a configured passphrase.
*/
protected void applyBackupEnhancementDetails(TakeBackupCommand command, Long zoneId) {
if (Boolean.TRUE.equals(NASBackupCompressionEnabled.valueIn(zoneId))) {
command.addDetail(TakeBackupCommand.DETAIL_COMPRESSION, "true");
}
if (Boolean.TRUE.equals(NASBackupEncryptionEnabled.valueIn(zoneId))) {
String passphrase = NASBackupEncryptionPassphrase.valueIn(zoneId);
if (passphrase == null || passphrase.isEmpty()) {
throw new CloudRuntimeException("NAS backup encryption is enabled but no passphrase is configured (nas.backup.encryption.passphrase)");
}
Comment thread
jmsperu marked this conversation as resolved.
command.addDetail(TakeBackupCommand.DETAIL_ENCRYPTION, "true");
command.addDetail(TakeBackupCommand.DETAIL_ENCRYPTION_PASSPHRASE, passphrase);
}
Integer bandwidthLimit = NASBackupBandwidthLimitMbps.valueIn(zoneId);
if (bandwidthLimit != null && bandwidthLimit > 0) {
command.addDetail(TakeBackupCommand.DETAIL_BANDWIDTH_LIMIT, String.valueOf(bandwidthLimit));
}
if (Boolean.TRUE.equals(NASBackupIntegrityCheckEnabled.valueIn(zoneId))) {
command.addDetail(TakeBackupCommand.DETAIL_INTEGRITY_CHECK, "true");
}
}

private BackupVO createBackupObject(VirtualMachine vm, String backupPath) {
BackupVO backup = new BackupVO();
backup.setVmId(vm.getId());
Expand All @@ -279,6 +348,19 @@ private BackupVO createBackupObject(VirtualMachine vm, String backupPath) {
return backupDao.persist(backup);
}

/**
* Restore-side counterpart of {@link #applyBackupEnhancementDetails}: hands the zone's LUKS passphrase
* to the host so encrypted backup files can be checked and converted back. It is sent whenever a
* passphrase is configured, not only while encryption is switched on, so backups taken before
* encryption was disabled stay restorable; the host ignores it for plain backups.
*/
protected void applyRestoreEncryptionDetails(RestoreBackupCommand command, Long zoneId) {
String passphrase = NASBackupEncryptionPassphrase.valueIn(zoneId);
if (passphrase != null && !passphrase.isEmpty()) {
command.setEncryptionPassphrase(passphrase);
}
}

@Override
public Pair<Boolean, String> restoreBackupToVM(VirtualMachine vm, Backup backup, String hostIp, String dataStoreUuid) {
return restoreVMBackup(vm, backup);
Expand Down Expand Up @@ -318,6 +400,7 @@ private Pair<Boolean, String> restoreVMBackup(VirtualMachine vm, Backup backup)
restoreCommand.setVmExists(vm.getRemoved() == null);
restoreCommand.setVmState(vm.getState());
restoreCommand.setMountTimeout(NASBackupRestoreMountTimeout.value());
applyRestoreEncryptionDetails(restoreCommand, vm.getDataCenterId());

BackupAnswer answer;
try {
Expand Down Expand Up @@ -435,6 +518,7 @@ public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, Backup.VolumeI
restoreCommand.setVmState(vmNameAndState.second());
restoreCommand.setMountTimeout(NASBackupRestoreMountTimeout.value());
restoreCommand.setBackupFiles(Collections.singletonList(matchingVolume.getPath()));
applyRestoreEncryptionDetails(restoreCommand, backup.getZoneId());

BackupAnswer answer;
try {
Expand Down Expand Up @@ -618,7 +702,12 @@ public Boolean crossZoneInstanceCreationEnabled(BackupOffering backupOffering) {
@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey[]{
NASBackupRestoreMountTimeout
NASBackupRestoreMountTimeout,
NASBackupCompressionEnabled,
NASBackupEncryptionEnabled,
NASBackupEncryptionPassphrase,
NASBackupBandwidthLimitMbps,
NASBackupIntegrityCheckEnabled
};
}

Expand Down
Loading
Loading

Back | FazBrowse Home | New Git URL