From 1b51bbbf74552734824cc680f23c3a1e8b0eb9aa Mon Sep 17 00:00:00 2001 From: Mike Tutkowski Date: Tue, 27 Jan 2015 22:14:35 -0700 Subject: [PATCH] Update hypervisor snapshot reserve for the root volume earlier than when it is currently being set --- .../service/VolumeOrchestrationService.java | 2 - .../subsystem/api/storage/VolumeService.java | 3 ++ .../orchestration/VolumeOrchestrator.java | 29 ++------------- .../StorageSystemDataMotionStrategy.java | 4 +- .../storage/volume/VolumeServiceImpl.java | 26 +++++++++++++ .../com/cloud/storage/StorageManagerImpl.java | 37 +++++++++++++++++-- 6 files changed, 66 insertions(+), 35 deletions(-) diff --git a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java index 497db3d601a..3522c1b97d9 100644 --- a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java +++ b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java @@ -124,6 +124,4 @@ public interface VolumeOrchestrationService { StoragePool findStoragePool(DiskProfile dskCh, DataCenter dc, Pod pod, Long clusterId, Long hostId, VirtualMachine vm, Set avoid); void updateVolumeDiskChain(long volumeId, String path, String chainInfo); - - VolumeInfo updateHypervisorSnapshotReserveForVolume(DiskOffering diskOffering, VolumeInfo volumeInfo, HypervisorType hyperType); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java index 171e9df0dc0..280aea495da 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java @@ -27,6 +27,8 @@ import org.apache.cloudstack.storage.command.CommandResult; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.exception.ConcurrentOperationException; import com.cloud.host.Host; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.offering.DiskOffering; public interface VolumeService { class VolumeApiResult extends CommandResult { @@ -102,4 +104,5 @@ public interface VolumeService { SnapshotInfo takeSnapshot(VolumeInfo volume); + VolumeInfo updateHypervisorSnapshotReserveForVolume(DiskOffering diskOffering, long volumeId, HypervisorType hyperType); } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index ab90fa7e809..7c6d3e24f93 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -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, DiskOffering diskOffering, List avoids, long size, HypervisorType hyperType) { // 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; @@ -546,29 +546,6 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati 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() { return UUID.randomUUID().toString(); } @@ -1259,7 +1236,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType(); // 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); @@ -1279,7 +1256,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati HypervisorType hyperType = vm.getVirtualMachine().getHypervisorType(); // 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(); diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java index 26a631bc468..e9244be4f99 100644 --- a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java +++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java @@ -27,7 +27,6 @@ import javax.inject.Inject; import org.apache.log4j.Logger; 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.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy; @@ -90,7 +89,6 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy { @Inject private SnapshotDetailsDao _snapshotDetailsDao; @Inject private VolumeDao _volumeDao; @Inject private VolumeDataFactory _volumeDataFactory; - @Inject private VolumeOrchestrationService _volumeMgr; @Inject private VolumeService _volumeService; @Override @@ -253,7 +251,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy { SnapshotVO snapshot = _snapshotDao.findById(snapshotInfo.getId()); // 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 future = _volumeService.createVolumeAsync(volumeInfo, volumeInfo.getDataStore()); diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index 5527c3de3f9..4ff28d72a8b 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -26,6 +26,7 @@ import java.util.Map; import javax.inject.Inject; +import com.cloud.offering.DiskOffering; import com.cloud.storage.RegisterVolumePayload; import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity; 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.host.Host; import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.DataStoreRole; import com.cloud.storage.ScopeType; import com.cloud.storage.Storage.StoragePoolType; @@ -1567,4 +1569,28 @@ public class VolumeServiceImpl implements VolumeService { 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); + } } diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index c7b3c3502eb..ba8925aac3f 100644 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -138,6 +138,7 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Volume.Type; +import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.StoragePoolWorkDao; @@ -266,6 +267,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C private TemplateService _imageSrv; @Inject EndPointSelector _epSelector; + @Inject + private DiskOfferingDao _diskOfferingDao; protected List _discoverers; @@ -1579,14 +1582,22 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C long allocatedSizeWithtemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, null); long totalAskingSize = 0; for (Volume volume : volumes) { - if (volume.getTemplateId() != null) { - VMTemplateVO tmpl = _templateDao.findByIdIncludingRemoved(volume.getTemplateId()); + VolumeVO volumeVO = _volumeDao.findById(volume.getId()); + + 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) { allocatedSizeWithtemplate = _capacityMgr.getAllocatedPoolCapacity(poolVO, tmpl); } } - if (volume.getState() != Volume.State.Ready) { - totalAskingSize = totalAskingSize + getVolumeSizeIncludingHypervisorSnapshotReserve(volume, pool); + if (volumeVO.getState() != Volume.State.Ready) { + totalAskingSize = totalAskingSize + getVolumeSizeIncludingHypervisorSnapshotReserve(volumeVO, pool); } } @@ -1631,6 +1642,24 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C 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) { DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName()); DataStoreDriver storeDriver = storeProvider.getDataStoreDriver();