Skip to content
Open
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 @@ -55,7 +55,7 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
ConfigKey<String> BackupProviderPlugin = new ConfigKey<>("Advanced", String.class,
"backup.framework.provider.plugin",
"dummy",
"The backup and recovery provider plugin.", true, ConfigKey.Scope.Zone, BackupFrameworkEnabled.key());
"The backup and recovery provider plugin. Valid plugin values: dummy, veeam, networker and nas", true, ConfigKey.Scope.Zone, BackupFrameworkEnabled.key());

ConfigKey<Long> BackupSyncPollingInterval = new ConfigKey<>("Advanced", Long.class,
"backup.framework.sync.interval",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.cloud.agent.api.Command;
import com.cloud.agent.api.LogLevel;
import com.cloud.vm.VirtualMachine;
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;

import java.util.List;

Expand All @@ -31,6 +32,7 @@ public class RestoreBackupCommand extends Command {
private String backupRepoType;
private String backupRepoAddress;
private List<String> backupVolumesUUIDs;
private List<PrimaryDataStoreTO> restoreVolumePools;
private List<String> restoreVolumePaths;
private String diskType;
private Boolean vmExists;
Expand Down Expand Up @@ -73,6 +75,14 @@ public void setBackupRepoAddress(String backupRepoAddress) {
this.backupRepoAddress = backupRepoAddress;
}

public List<PrimaryDataStoreTO> getRestoreVolumePools() {
return restoreVolumePools;
}

public void setRestoreVolumePools(List<PrimaryDataStoreTO> restoreVolumePools) {
this.restoreVolumePools = restoreVolumePools;
}

public List<String> getRestoreVolumePaths() {
return restoreVolumePaths;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
import com.cloud.hypervisor.Hypervisor;
import com.cloud.offering.DiskOffering;
import com.cloud.resource.ResourceManager;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeApiServiceImpl;
import com.cloud.storage.VolumeVO;
Expand All @@ -49,10 +49,13 @@

import org.apache.cloudstack.backup.dao.BackupDao;
import org.apache.cloudstack.backup.dao.BackupRepositoryDao;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

Expand Down Expand Up @@ -97,6 +100,9 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
@Inject
private PrimaryDataStoreDao primaryDataStoreDao;

@Inject
DataStoreManager dataStoreMgr;

@Inject
private AgentManager agentManager;

Expand Down Expand Up @@ -179,7 +185,8 @@ public Pair<Boolean, Backup> takeBackup(final VirtualMachine vm, Boolean quiesce
if (VirtualMachine.State.Stopped.equals(vm.getState())) {
List<VolumeVO> vmVolumes = volumeDao.findByInstance(vm.getId());
vmVolumes.sort(Comparator.comparing(Volume::getDeviceId));
List<String> volumePaths = getVolumePaths(vmVolumes);
Pair<List<PrimaryDataStoreTO>, List<String>> volumePoolsAndPaths = getVolumePoolsAndPaths(vmVolumes);
List<String> volumePaths = volumePoolsAndPaths.second();
command.setVolumePaths(volumePaths);
}

Expand Down Expand Up @@ -279,7 +286,9 @@ private boolean restoreVMBackup(VirtualMachine vm, Backup backup) {
restoreCommand.setMountOptions(backupRepository.getMountOptions());
restoreCommand.setVmName(vm.getName());
restoreCommand.setBackupVolumesUUIDs(backedVolumesUUIDs);
restoreCommand.setRestoreVolumePaths(getVolumePaths(restoreVolumes));
Pair<List<PrimaryDataStoreTO>, List<String>> volumePoolsAndPaths = getVolumePoolsAndPaths(restoreVolumes);
restoreCommand.setRestoreVolumePools(volumePoolsAndPaths.first());
restoreCommand.setRestoreVolumePaths(volumePoolsAndPaths.second());
restoreCommand.setVmExists(vm.getRemoved() == null);
restoreCommand.setVmState(vm.getState());

Expand All @@ -294,31 +303,42 @@ private boolean restoreVMBackup(VirtualMachine vm, Backup backup) {
return answer.getResult();
}

private List<String> getVolumePaths(List<VolumeVO> volumes) {
private Pair<List<PrimaryDataStoreTO>, List<String>> getVolumePoolsAndPaths(List<VolumeVO> volumes) {
List<PrimaryDataStoreTO> volumePools = new ArrayList<>();
List<String> volumePaths = new ArrayList<>();
for (VolumeVO volume : volumes) {
StoragePoolVO storagePool = primaryDataStoreDao.findById(volume.getPoolId());
if (Objects.isNull(storagePool)) {
throw new CloudRuntimeException("Unable to find storage pool associated to the volume");
}
String volumePathPrefix;
if (ScopeType.HOST.equals(storagePool.getScope())) {
volumePathPrefix = storagePool.getPath();
} else if (Storage.StoragePoolType.SharedMountPoint.equals(storagePool.getPoolType())) {
volumePathPrefix = storagePool.getPath();
} else {
volumePathPrefix = String.format("/mnt/%s", storagePool.getUuid());
}

DataStore dataStore = dataStoreMgr.getDataStore(storagePool.getId(), DataStoreRole.Primary);
volumePools.add(dataStore != null ? (PrimaryDataStoreTO)dataStore.getTO() : null);

String volumePathPrefix = getVolumePathPrefix(storagePool);
volumePaths.add(String.format("%s/%s", volumePathPrefix, volume.getPath()));
}
return volumePaths;
return new Pair<>(volumePools, volumePaths);
}

private String getVolumePathPrefix(StoragePoolVO storagePool) {
String volumePathPrefix;
if (ScopeType.HOST.equals(storagePool.getScope()) ||
Storage.StoragePoolType.SharedMountPoint.equals(storagePool.getPoolType()) ||
Storage.StoragePoolType.RBD.equals(storagePool.getPoolType())) {
volumePathPrefix = storagePool.getPath();
} else {
// Should be Storage.StoragePoolType.NetworkFilesystem
volumePathPrefix = String.format("/mnt/%s", storagePool.getUuid());
}
return volumePathPrefix;
}

@Override
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());
final StoragePoolHostVO dataStore = storagePoolHostDao.findByUuid(dataStoreUuid);
final StoragePoolVO pool = primaryDataStoreDao.findByUuid(dataStoreUuid);
final HostVO hostVO = hostDao.findByIp(hostIp);

LOG.debug("Restoring vm volume {} from backup {} on the NAS Backup Provider", backupVolumeInfo, backup);
Expand All @@ -335,19 +355,26 @@ public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, Backup.VolumeI
restoredVolume.setUuid(volumeUUID);
restoredVolume.setRemoved(null);
restoredVolume.setDisplayVolume(true);
restoredVolume.setPoolId(dataStore.getPoolId());
restoredVolume.setPoolId(pool.getId());
restoredVolume.setPoolType(pool.getPoolType());
restoredVolume.setPath(restoredVolume.getUuid());
restoredVolume.setState(Volume.State.Copying);
restoredVolume.setFormat(Storage.ImageFormat.QCOW2);
restoredVolume.setSize(backupVolumeInfo.getSize());
restoredVolume.setDiskOfferingId(diskOffering.getId());
if (pool.getPoolType() != Storage.StoragePoolType.RBD) {
restoredVolume.setFormat(Storage.ImageFormat.QCOW2);
} else {
restoredVolume.setFormat(Storage.ImageFormat.RAW);
}

RestoreBackupCommand restoreCommand = new RestoreBackupCommand();
restoreCommand.setBackupPath(backup.getExternalId());
restoreCommand.setBackupRepoType(backupRepository.getType());
restoreCommand.setBackupRepoAddress(backupRepository.getAddress());
restoreCommand.setVmName(vmNameAndState.first());
restoreCommand.setRestoreVolumePaths(Collections.singletonList(String.format("%s/%s", dataStore.getLocalPath(), volumeUUID)));
restoreCommand.setRestoreVolumePaths(Collections.singletonList(String.format("%s/%s", getVolumePathPrefix(pool), volumeUUID)));
DataStore dataStore = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
restoreCommand.setRestoreVolumePools(Collections.singletonList(dataStore != null ? (PrimaryDataStoreTO)dataStore.getTO() : null));
restoreCommand.setDiskType(backupVolumeInfo.getType().name().toLowerCase(Locale.ROOT));
restoreCommand.setMountOptions(backupRepository.getMountOptions());
restoreCommand.setVmExists(null);
Expand Down
Loading
Loading