mirror of https://github.com/apache/cloudstack.git
Add support for incremental volume snapshots for clvm_ng
This commit is contained in:
parent
348cf33908
commit
22c4934b19
|
|
@ -39,8 +39,8 @@ public class LibvirtClvmLockTransferCommandWrapper
|
|||
ClvmLockTransferCommand.Operation operation = cmd.getOperation();
|
||||
String volumeUuid = cmd.getVolumeUuid();
|
||||
|
||||
logger.info(String.format("Executing CLVM lock transfer: operation=%s, lv=%s, volume=%s",
|
||||
operation, lvPath, volumeUuid));
|
||||
logger.info("Executing CLVM lock transfer: operation={}, lv={}, volume={}",
|
||||
operation, lvPath, volumeUuid);
|
||||
|
||||
try {
|
||||
String lvchangeOpt;
|
||||
|
|
@ -69,20 +69,20 @@ public class LibvirtClvmLockTransferCommandWrapper
|
|||
String result = script.execute();
|
||||
|
||||
if (result != null) {
|
||||
logger.error("CLVM lock transfer failed for volume {}: {}}",
|
||||
logger.error("CLVM lock transfer failed for volume {}: {}",
|
||||
volumeUuid, result);
|
||||
return new Answer(cmd, false,
|
||||
String.format("lvchange %s %s failed: %s", lvchangeOpt, lvPath, result));
|
||||
}
|
||||
|
||||
logger.info("Successfully executed CLVM lock transfer: {} {}} for volume {}}",
|
||||
logger.info("Successfully executed CLVM lock transfer: {} {} for volume {}",
|
||||
lvchangeOpt, lvPath, volumeUuid);
|
||||
|
||||
return new Answer(cmd, true,
|
||||
String.format("Successfully %s CLVM volume %s", operationDesc, volumeUuid));
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Exception during CLVM lock transfer for volume {}: {}}",
|
||||
logger.error("Exception during CLVM lock transfer for volume {}: {}",
|
||||
volumeUuid, e.getMessage(), e);
|
||||
return new Answer(cmd, false, "Exception: " + e.getMessage());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -223,6 +223,26 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
" </devices>\n" +
|
||||
"</domain>";
|
||||
|
||||
private static final String DUMMY_VM_XML_BLOCK = "<domain type='qemu'>\n" +
|
||||
" <name>%s</name>\n" +
|
||||
" <memory unit='MiB'>256</memory>\n" +
|
||||
" <currentMemory unit='MiB'>256</currentMemory>\n" +
|
||||
" <vcpu>1</vcpu>\n" +
|
||||
" <os>\n" +
|
||||
" <type arch='%s' machine='%s'>hvm</type>\n" +
|
||||
" <boot dev='hd'/>\n" +
|
||||
" </os>\n" +
|
||||
" <devices>\n" +
|
||||
" <emulator>%s</emulator>\n" +
|
||||
" <disk type='block' device='disk'>\n" +
|
||||
" <driver name='qemu' type='qcow2' cache='none'/>\n"+
|
||||
" <source dev='%s'/>\n" +
|
||||
" <target dev='sda'/>\n" +
|
||||
" </disk>\n" +
|
||||
" <graphics type='vnc' port='-1'/>\n" +
|
||||
" </devices>\n" +
|
||||
"</domain>";
|
||||
|
||||
|
||||
public KVMStorageProcessor(final KVMStoragePoolManager storagePoolMgr, final LibvirtComputingResource resource) {
|
||||
this.storagePoolMgr = storagePoolMgr;
|
||||
|
|
@ -2038,9 +2058,21 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
newSnapshot.setPhysicalSize(snapshotSize);
|
||||
}
|
||||
} else if (primaryPool.getType() == StoragePoolType.CLVM || primaryPool.getType() == StoragePoolType.CLVM_NG) {
|
||||
CreateObjectAnswer result = takeClvmVolumeSnapshotOfStoppedVm(disk, snapshotName);
|
||||
if (result != null) return result;
|
||||
newSnapshot.setPath(snapshotPath);
|
||||
if (primaryPool.getType() == StoragePoolType.CLVM_NG && snapshotTO.isKvmIncrementalSnapshot()) {
|
||||
if (secondaryPool == null) {
|
||||
String errorMsg = String.format("Incremental snapshots for CLVM_NG require secondary storage. " +
|
||||
"Please configure secondary storage or disable incremental snapshots for volume [%s].", volume.getName());
|
||||
logger.error(errorMsg);
|
||||
return new CreateObjectAnswer(errorMsg);
|
||||
}
|
||||
logger.info("Taking incremental snapshot of CLVM_NG volume [{}] using QCOW2 backup to secondary storage.", volume.getName());
|
||||
newSnapshot = takeIncrementalVolumeSnapshotOfStoppedVm(snapshotTO, primaryPool, secondaryPool,
|
||||
imageStoreTo.getUrl(), snapshotName, volume, conn, cmd.getWait());
|
||||
} else {
|
||||
CreateObjectAnswer result = takeClvmVolumeSnapshotOfStoppedVm(disk, snapshotName);
|
||||
if (result != null) return result;
|
||||
newSnapshot.setPath(snapshotPath);
|
||||
}
|
||||
} else {
|
||||
if (snapshotTO.isKvmIncrementalSnapshot()) {
|
||||
newSnapshot = takeIncrementalVolumeSnapshotOfStoppedVm(snapshotTO, primaryPool, secondaryPool, imageStoreTo != null ? imageStoreTo.getUrl() : null, snapshotName, volume, conn, cmd.getWait());
|
||||
|
|
@ -2113,7 +2145,11 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||
String machine = resource.isGuestAarch64() ? LibvirtComputingResource.VIRT : LibvirtComputingResource.PC;
|
||||
String cpuArch = resource.getGuestCpuArch() != null ? resource.getGuestCpuArch() : "x86_64";
|
||||
|
||||
return String.format(DUMMY_VM_XML, vmName, cpuArch, machine, resource.getHypervisorPath(), primaryPool.getLocalPathFor(volumeObjectTo.getPath()));
|
||||
String volumePath = primaryPool.getLocalPathFor(volumeObjectTo.getPath());
|
||||
boolean isClvmNg = StoragePoolType.CLVM_NG == primaryPool.getType();
|
||||
|
||||
String xmlTemplate = isClvmNg ? DUMMY_VM_XML_BLOCK : DUMMY_VM_XML;
|
||||
return String.format(xmlTemplate, vmName, cpuArch, machine, resource.getHypervisorPath(), volumePath);
|
||||
}
|
||||
|
||||
private SnapshotObjectTO takeIncrementalVolumeSnapshotOfRunningVm(SnapshotObjectTO snapshotObjectTO, KVMStoragePool primaryPool, KVMStoragePool secondaryPool,
|
||||
|
|
|
|||
|
|
@ -2696,16 +2696,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
vmPool.getPoolType() == StoragePoolType.CLVM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a storage pool is CLVM type.
|
||||
*
|
||||
* @param pool Storage pool to check
|
||||
* @return true if pool is CLVM type
|
||||
*/
|
||||
private boolean isClvmPool(StoragePoolVO pool) {
|
||||
return pool != null && pool.getPoolType() == StoragePoolType.CLVM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the Volume Group (VG) name from a CLVM storage pool path.
|
||||
* For CLVM, the path is typically: /vgname
|
||||
|
|
@ -2797,7 +2787,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||
StoragePoolVO volumePool = pools.first();
|
||||
StoragePoolVO vmPool = pools.second();
|
||||
|
||||
if (!isClvmPool(volumePool)) {
|
||||
if (volumePool != null && !ClvmLockManager.isClvmPoolType(volumePool.getPoolType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1641,7 +1641,8 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
boolean isKvmAndFileBasedStorage = isHypervisorKvmAndFileBasedStorage(volume, storagePool);
|
||||
boolean backupSnapToSecondary = isBackupSnapshotToSecondaryForZone(volume.getDataCenterId());
|
||||
|
||||
if (isKvmAndFileBasedStorage && backupSnapToSecondary) {
|
||||
StoragePoolType poolType = volume.getStoragePoolType();
|
||||
if ((isKvmAndFileBasedStorage || StoragePoolType.CLVM_NG == poolType) && backupSnapToSecondary) {
|
||||
DataStore imageStore = snapshotSrv.findSnapshotImageStore(snapshot);
|
||||
if (imageStore == null) {
|
||||
throw new CloudRuntimeException(String.format("Could not find any secondary storage to allocate snapshot [%s].", snapshot));
|
||||
|
|
@ -1649,7 +1650,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
snapshot.setImageStore(imageStore);
|
||||
}
|
||||
|
||||
updateSnapshotPayload(volume.getPoolId(), payload, isKvmAndFileBasedStorage, clusterId);
|
||||
updateSnapshotPayload(volume.getPoolId(), payload, isKvmAndFileBasedStorage, poolType, clusterId);
|
||||
|
||||
snapshot.addPayload(payload);
|
||||
try {
|
||||
|
|
@ -1664,8 +1665,12 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
|
||||
SnapshotInfo snapshotOnPrimary = snapshotStrategy.takeSnapshot(snapshot);
|
||||
|
||||
// For CLVM_NG with incremental snapshots, the snapshot is already created directly on secondary storage
|
||||
boolean isClvmNgIncremental = storagePool.getPoolType() == StoragePoolType.CLVM_NG &&
|
||||
snapshot.isKvmIncrementalSnapshot();
|
||||
|
||||
if (backupSnapToSecondary) {
|
||||
if (!isKvmAndFileBasedStorage) {
|
||||
if (!isKvmAndFileBasedStorage && !isClvmNgIncremental) {
|
||||
backupSnapshotToSecondary(payload.getAsyncBackup(), snapshotStrategy, snapshotOnPrimary, payload.getZoneIds(), payload.getStoragePoolIds());
|
||||
if (storagePool.getPoolType() == StoragePoolType.CLVM || storagePool.getPoolType() == StoragePoolType.CLVM_NG) {
|
||||
_snapshotStoreDao.removeBySnapshotStore(snapshotId, snapshotOnPrimary.getDataStore().getId(), snapshotOnPrimary.getDataStore().getRole());
|
||||
|
|
@ -1852,7 +1857,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
}
|
||||
}
|
||||
|
||||
private void updateSnapshotPayload(long storagePoolId, CreateSnapshotPayload payload, boolean isKvmAndFileBasedStorage, Long clusterId) {
|
||||
private void updateSnapshotPayload(long storagePoolId, CreateSnapshotPayload payload, boolean isKvmAndFileBasedStorage, StoragePoolType poolType, Long clusterId) {
|
||||
StoragePoolVO storagePoolVO = _storagePoolDao.findById(storagePoolId);
|
||||
|
||||
if (storagePoolVO.isManaged()) {
|
||||
|
|
@ -1865,7 +1870,7 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
|
|||
payload.setLocationType(null);
|
||||
}
|
||||
|
||||
if (isKvmAndFileBasedStorage && kvmIncrementalSnapshot.valueIn(clusterId)) {
|
||||
if ((isKvmAndFileBasedStorage || StoragePoolType.CLVM_NG == poolType) && kvmIncrementalSnapshot.valueIn(clusterId)) {
|
||||
payload.setKvmIncrementalSnapshot(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5398,7 +5398,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
@Override
|
||||
public boolean setupVmForPvlan(boolean add, Long hostId, NicProfile nic) {
|
||||
if (!nic.getBroadCastUri().getScheme().equals("pvlan")) {
|
||||
if (nic == null) {
|
||||
logger.warn("Skipping PVLAN setup on host {} because NIC profile is null", hostId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nic.getBroadCastUri() == null) {
|
||||
logger.debug("Skipping PVLAN setup on host {} for NIC {} because broadcast URI is null", hostId, nic);
|
||||
return false;
|
||||
}
|
||||
|
||||
String scheme = nic.getBroadCastUri().getScheme();
|
||||
if (!"pvlan".equalsIgnoreCase(scheme)) {
|
||||
logger.debug("Skipping PVLAN setup on host {} for NIC {} because broadcast URI scheme is {}", hostId, nic, scheme);
|
||||
return false;
|
||||
}
|
||||
String op = "add";
|
||||
|
|
@ -5406,11 +5418,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
// "delete" would remove all the rules(if using ovs) related to this vm
|
||||
op = "delete";
|
||||
}
|
||||
Network network = _networkDao.findById(nic.getNetworkId());
|
||||
|
||||
Host host = _hostDao.findById(hostId);
|
||||
if (host == null) {
|
||||
logger.warn("Host with id {} does not exist", hostId);
|
||||
return false;
|
||||
}
|
||||
|
||||
Network network = _networkDao.findById(nic.getNetworkId());
|
||||
String networkTag = _networkModel.getNetworkTag(host.getHypervisorType(), network);
|
||||
PvlanSetupCommand cmd = PvlanSetupCommand.createVmSetup(op, nic.getBroadCastUri(), networkTag, nic.getMacAddress());
|
||||
Answer answer = null;
|
||||
Answer answer;
|
||||
try {
|
||||
answer = _agentMgr.send(hostId, cmd);
|
||||
} catch (OperationTimedoutException e) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue