Update hypervisor snapshot reserve for the root volume earlier than when it is currently being set

This commit is contained in:
Mike Tutkowski 2015-01-27 22:14:35 -07:00
parent 65e8e50dec
commit 1b51bbbf74
6 changed files with 66 additions and 35 deletions

View File

@ -124,6 +124,4 @@ public interface VolumeOrchestrationService {
StoragePool findStoragePool(DiskProfile dskCh, DataCenter dc, Pod pod, Long clusterId, Long hostId, VirtualMachine vm, Set<StoragePool> avoid); StoragePool findStoragePool(DiskProfile dskCh, DataCenter dc, Pod pod, Long clusterId, Long hostId, VirtualMachine vm, Set<StoragePool> avoid);
void updateVolumeDiskChain(long volumeId, String path, String chainInfo); void updateVolumeDiskChain(long volumeId, String path, String chainInfo);
VolumeInfo updateHypervisorSnapshotReserveForVolume(DiskOffering diskOffering, VolumeInfo volumeInfo, HypervisorType hyperType);
} }

View File

@ -27,6 +27,8 @@ import org.apache.cloudstack.storage.command.CommandResult;
import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.ConcurrentOperationException;
import com.cloud.host.Host; import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.offering.DiskOffering;
public interface VolumeService { public interface VolumeService {
class VolumeApiResult extends CommandResult { class VolumeApiResult extends CommandResult {
@ -102,4 +104,5 @@ public interface VolumeService {
SnapshotInfo takeSnapshot(VolumeInfo volume); SnapshotInfo takeSnapshot(VolumeInfo volume);
VolumeInfo updateHypervisorSnapshotReserveForVolume(DiskOffering diskOffering, long volumeId, HypervisorType hyperType);
} }

View File

@ -483,7 +483,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
public VolumeInfo createVolume(VolumeInfo volume, VirtualMachine vm, VirtualMachineTemplate template, DataCenter dc, Pod pod, Long clusterId, ServiceOffering offering, public VolumeInfo createVolume(VolumeInfo volume, VirtualMachine vm, VirtualMachineTemplate template, DataCenter dc, Pod pod, Long clusterId, ServiceOffering offering,
DiskOffering diskOffering, List<StoragePool> avoids, long size, HypervisorType hyperType) { DiskOffering diskOffering, List<StoragePool> avoids, long size, HypervisorType hyperType) {
// update the volume's hypervisor_ss_reserve from its disk offering (used for managed storage) // update the volume's hypervisor_ss_reserve from its disk offering (used for managed storage)
volume = updateHypervisorSnapshotReserveForVolume(diskOffering, volume, hyperType); volume = volService.updateHypervisorSnapshotReserveForVolume(diskOffering, volume.getId(), hyperType);
StoragePool pool = null; StoragePool pool = null;
@ -546,29 +546,6 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
throw new CloudRuntimeException("create volume failed even after template re-deploy"); throw new CloudRuntimeException("create volume failed even after template re-deploy");
} }
// For managed storage on Xen and VMware, we need to potentially make space for hypervisor snapshots.
// The disk offering can collect this information and pass it on to the volume that's about to be created.
// Ex. if you want a 10 GB CloudStack volume to reside on managed storage on Xen, this leads to an SR
// that is a total size of (10 GB * (hypervisorSnapshotReserveSpace / 100) + 10 GB).
@Override
public VolumeInfo updateHypervisorSnapshotReserveForVolume(DiskOffering diskOffering, VolumeInfo volumeInfo, HypervisorType hyperType) {
Integer hypervisorSnapshotReserve = diskOffering.getHypervisorSnapshotReserve();
if (hyperType == HypervisorType.KVM) {
hypervisorSnapshotReserve = null;
} else if (hypervisorSnapshotReserve == null || hypervisorSnapshotReserve < 0) {
hypervisorSnapshotReserve = 0;
}
VolumeVO volume = _volsDao.findById(volumeInfo.getId());
volume.setHypervisorSnapshotReserve(hypervisorSnapshotReserve);
_volsDao.update(volume.getId(), volume);
return volFactory.getVolume(volume.getId());
}
public String getRandomVolumeName() { public String getRandomVolumeName() {
return UUID.randomUUID().toString(); return UUID.randomUUID().toString();
} }
@ -1259,7 +1236,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType(); HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType();
// update the volume's hypervisor_ss_reserve from its disk offering (used for managed storage) // update the volume's hypervisor_ss_reserve from its disk offering (used for managed storage)
updateHypervisorSnapshotReserveForVolume(diskOffering, volume, hyperType); volService.updateHypervisorSnapshotReserveForVolume(diskOffering, volume.getId(), hyperType);
volume = volFactory.getVolume(newVol.getId(), destPool); volume = volFactory.getVolume(newVol.getId(), destPool);
@ -1279,7 +1256,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType(); HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType();
// update the volume's hypervisor_ss_reserve from its disk offering (used for managed storage) // update the volume's hypervisor_ss_reserve from its disk offering (used for managed storage)
updateHypervisorSnapshotReserveForVolume(diskOffering, volume, hyperType); volService.updateHypervisorSnapshotReserveForVolume(diskOffering, volume.getId(), hyperType);
long hostId = vm.getVirtualMachine().getHostId(); long hostId = vm.getVirtualMachine().getHostId();

View File

@ -27,7 +27,6 @@ import javax.inject.Inject;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy; import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
@ -90,7 +89,6 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
@Inject private SnapshotDetailsDao _snapshotDetailsDao; @Inject private SnapshotDetailsDao _snapshotDetailsDao;
@Inject private VolumeDao _volumeDao; @Inject private VolumeDao _volumeDao;
@Inject private VolumeDataFactory _volumeDataFactory; @Inject private VolumeDataFactory _volumeDataFactory;
@Inject private VolumeOrchestrationService _volumeMgr;
@Inject private VolumeService _volumeService; @Inject private VolumeService _volumeService;
@Override @Override
@ -253,7 +251,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
SnapshotVO snapshot = _snapshotDao.findById(snapshotInfo.getId()); SnapshotVO snapshot = _snapshotDao.findById(snapshotInfo.getId());
// update the volume's hypervisor_ss_reserve from its disk offering (used for managed storage) // update the volume's hypervisor_ss_reserve from its disk offering (used for managed storage)
_volumeMgr.updateHypervisorSnapshotReserveForVolume(diskOffering, volumeInfo, snapshot.getHypervisorType()); _volumeService.updateHypervisorSnapshotReserveForVolume(diskOffering, volumeInfo.getId(), snapshot.getHypervisorType());
AsyncCallFuture<VolumeApiResult> future = _volumeService.createVolumeAsync(volumeInfo, volumeInfo.getDataStore()); AsyncCallFuture<VolumeApiResult> future = _volumeService.createVolumeAsync(volumeInfo, volumeInfo.getDataStore());

View File

@ -26,6 +26,7 @@ import java.util.Map;
import javax.inject.Inject; import javax.inject.Inject;
import com.cloud.offering.DiskOffering;
import com.cloud.storage.RegisterVolumePayload; import com.cloud.storage.RegisterVolumePayload;
import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity; import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
@ -79,6 +80,7 @@ import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.Host; import com.cloud.host.Host;
import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.DataStoreRole; import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ScopeType; import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Storage.StoragePoolType;
@ -1567,4 +1569,28 @@ public class VolumeServiceImpl implements VolumeService {
return snapshot; return snapshot;
} }
// For managed storage on Xen and VMware, we need to potentially make space for hypervisor snapshots.
// The disk offering can collect this information and pass it on to the volume that's about to be created.
// Ex. if you want a 10 GB CloudStack volume to reside on managed storage on Xen, this leads to an SR
// that is a total size of (10 GB * (hypervisorSnapshotReserveSpace / 100) + 10 GB).
@Override
public VolumeInfo updateHypervisorSnapshotReserveForVolume(DiskOffering diskOffering, long volumeId, HypervisorType hyperType) {
if (diskOffering != null && hyperType != null) {
Integer hypervisorSnapshotReserve = diskOffering.getHypervisorSnapshotReserve();
if (hyperType == HypervisorType.KVM) {
hypervisorSnapshotReserve = null;
} else if (hypervisorSnapshotReserve == null || hypervisorSnapshotReserve < 0) {
hypervisorSnapshotReserve = 0;
}
VolumeVO volume = volDao.findById(volumeId);
volume.setHypervisorSnapshotReserve(hypervisorSnapshotReserve);
volDao.update(volume.getId(), volume);
}
return volFactory.getVolume(volumeId);
}
} }

View File

@ -138,6 +138,7 @@ import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Volume.Type; import com.cloud.storage.Volume.Type;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.StoragePoolWorkDao; import com.cloud.storage.dao.StoragePoolWorkDao;
@ -266,6 +267,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
private TemplateService _imageSrv; private TemplateService _imageSrv;
@Inject @Inject
EndPointSelector _epSelector; EndPointSelector _epSelector;
@Inject
private DiskOfferingDao _diskOfferingDao;
protected List<StoragePoolDiscoverer> _discoverers; protected List<StoragePoolDiscoverer> _discoverers;
@ -1579,14 +1582,22 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
long allocatedSizeWithtemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, null); long allocatedSizeWithtemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, null);
long totalAskingSize = 0; long totalAskingSize = 0;
for (Volume volume : volumes) { for (Volume volume : volumes) {
if (volume.getTemplateId() != null) { VolumeVO volumeVO = _volumeDao.findById(volume.getId());
VMTemplateVO tmpl = _templateDao.findByIdIncludingRemoved(volume.getTemplateId());
if (volumeVO.getHypervisorSnapshotReserve() == null) {
volService.updateHypervisorSnapshotReserveForVolume(getDiskOfferingVO(volumeVO), volumeVO.getId(), getHypervisorType(volumeVO));
volumeVO = _volumeDao.findById(volume.getId());
}
if (volumeVO.getTemplateId() != null) {
VMTemplateVO tmpl = _templateDao.findByIdIncludingRemoved(volumeVO.getTemplateId());
if (tmpl != null && tmpl.getFormat() != ImageFormat.ISO) { if (tmpl != null && tmpl.getFormat() != ImageFormat.ISO) {
allocatedSizeWithtemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, tmpl); allocatedSizeWithtemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, tmpl);
} }
} }
if (volume.getState() != Volume.State.Ready) { if (volumeVO.getState() != Volume.State.Ready) {
totalAskingSize = totalAskingSize + getVolumeSizeIncludingHypervisorSnapshotReserve(volume, pool); totalAskingSize = totalAskingSize + getVolumeSizeIncludingHypervisorSnapshotReserve(volumeVO, pool);
} }
} }
@ -1631,6 +1642,24 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
return true; return true;
} }
private DiskOfferingVO getDiskOfferingVO(Volume volume) {
Long diskOfferingId = volume.getDiskOfferingId();
return _diskOfferingDao.findById(diskOfferingId);
}
private HypervisorType getHypervisorType(Volume volume) {
Long instanceId = volume.getInstanceId();
VMInstanceVO vmInstance = _vmInstanceDao.findById(instanceId);
if (vmInstance != null) {
return vmInstance.getHypervisorType();
}
return null;
}
private long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) { private long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) {
DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName()); DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName());
DataStoreDriver storeDriver = storeProvider.getDataStoreDriver(); DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();