From c3272867bd20690b7619962ca88e02ad67d288f6 Mon Sep 17 00:00:00 2001 From: nvazquez Date: Mon, 15 Jul 2019 15:32:31 -0300 Subject: [PATCH 1/5] Prevent NullPointerException when vm has not run before --- .../src/main/java/com/cloud/storage/VolumeApiServiceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 2022d5b5be13..5098e18a43a3 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -2861,7 +2861,9 @@ private VolumeVO sendAttachVolumeCommand(UserVmVO vm, VolumeVO volumeToAttach, L } } - verifyManagedStorage(volumeToAttachStoragePool.getId(), hostId); + if (volumeToAttachStoragePool != null) { + verifyManagedStorage(volumeToAttachStoragePool.getId(), hostId); + } // volumeToAttachStoragePool should be null if the VM we are attaching the disk to has never been started before DataStore dataStore = volumeToAttachStoragePool != null ? dataStoreMgr.getDataStore(volumeToAttachStoragePool.getId(), DataStoreRole.Primary) : null; From 5e2c301dc553c6f0514deb37d48c0c240ca7c9fd Mon Sep 17 00:00:00 2001 From: nvazquez Date: Mon, 15 Jul 2019 15:33:17 -0300 Subject: [PATCH 2/5] Add hypervisor default max volumes if vm has not run before --- .../main/java/com/cloud/storage/VolumeApiServiceImpl.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 5098e18a43a3..5332fd38516c 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -3009,6 +3009,13 @@ private int getMaxDataVolumesSupported(UserVmVO vm) { if (host != null) { _hostDao.loadDetails(host); maxDataVolumesSupported = _hypervisorCapabilitiesDao.getMaxDataVolumesLimit(host.getHypervisorType(), host.getDetail("product_version")); + } else { + List supportingDefaultHV = Arrays.asList(HypervisorType.XenServer, HypervisorType.VMware, + HypervisorType.KVM, HypervisorType.Ovm, HypervisorType.LXC); + HypervisorType hypervisorType = vm.getHypervisorType(); + if (hypervisorType != null && supportingDefaultHV.contains(hypervisorType)) { + maxDataVolumesSupported = _hypervisorCapabilitiesDao.getMaxDataVolumesLimit(hypervisorType, "default"); + } } if (maxDataVolumesSupported == null || maxDataVolumesSupported.intValue() <= 0) { maxDataVolumesSupported = 6; // 6 data disks by default if nothing From 5fa201ce8faedafdcd753dd47e553caa1961c922 Mon Sep 17 00:00:00 2001 From: nvazquez Date: Tue, 16 Jul 2019 10:47:06 -0300 Subject: [PATCH 3/5] Check database for default hypervisor entries instead of hardcoded --- .../hypervisor/dao/HypervisorCapabilitiesDao.java | 2 ++ .../dao/HypervisorCapabilitiesDaoImpl.java | 13 +++++++++++++ .../com/cloud/storage/VolumeApiServiceImpl.java | 5 ++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java b/engine/schema/src/main/java/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java index 029a8fa273cf..83c32b1c2efd 100644 --- a/engine/schema/src/main/java/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java +++ b/engine/schema/src/main/java/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java @@ -35,4 +35,6 @@ public interface HypervisorCapabilitiesDao extends GenericDao getHypervisorsWithDefaultEntries(); } diff --git a/engine/schema/src/main/java/com/cloud/hypervisor/dao/HypervisorCapabilitiesDaoImpl.java b/engine/schema/src/main/java/com/cloud/hypervisor/dao/HypervisorCapabilitiesDaoImpl.java index a4341380ddc4..5cecff2af95f 100644 --- a/engine/schema/src/main/java/com/cloud/hypervisor/dao/HypervisorCapabilitiesDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/hypervisor/dao/HypervisorCapabilitiesDaoImpl.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.hypervisor.dao; +import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.StringUtils; @@ -106,4 +107,16 @@ public Boolean isVmSnapshotEnabled(HypervisorType hypervisorType, String hypervi HypervisorCapabilitiesVO result = getCapabilities(hypervisorType, hypervisorVersion); return result.getVmSnapshotEnabled(); } + + @Override + public List getHypervisorsWithDefaultEntries() { + SearchCriteria sc = HypervisorTypeAndVersionSearch.create(); + sc.setParameters("hypervisorVersion", DEFAULT_VERSION); + List hypervisorCapabilitiesVOS = listBy(sc); + List hvs = new ArrayList<>(); + for (HypervisorCapabilitiesVO capabilitiesVO : hypervisorCapabilitiesVOS) { + hvs.add(capabilitiesVO.getHypervisorType()); + } + return hvs; + } } diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 5332fd38516c..1c1a5697f5bc 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -3010,10 +3010,9 @@ private int getMaxDataVolumesSupported(UserVmVO vm) { _hostDao.loadDetails(host); maxDataVolumesSupported = _hypervisorCapabilitiesDao.getMaxDataVolumesLimit(host.getHypervisorType(), host.getDetail("product_version")); } else { - List supportingDefaultHV = Arrays.asList(HypervisorType.XenServer, HypervisorType.VMware, - HypervisorType.KVM, HypervisorType.Ovm, HypervisorType.LXC); + List supportingDefaultHV = _hypervisorCapabilitiesDao.getHypervisorsWithDefaultEntries(); HypervisorType hypervisorType = vm.getHypervisorType(); - if (hypervisorType != null && supportingDefaultHV.contains(hypervisorType)) { + if (hypervisorType != null && CollectionUtils.isNotEmpty(supportingDefaultHV) && supportingDefaultHV.contains(hypervisorType)) { maxDataVolumesSupported = _hypervisorCapabilitiesDao.getMaxDataVolumesLimit(hypervisorType, "default"); } } From 6a3382671bb329c6223aafa09b35314895db90ef Mon Sep 17 00:00:00 2001 From: nvazquez Date: Tue, 16 Jul 2019 11:19:34 -0300 Subject: [PATCH 4/5] Fix failing test --- .../test/java/com/cloud/storage/VolumeApiServiceImplTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java index 9d1426ce9f15..da346536d5a3 100644 --- a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java +++ b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java @@ -33,6 +33,7 @@ import java.util.UUID; import java.util.concurrent.ExecutionException; +import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; @@ -149,6 +150,8 @@ public class VolumeApiServiceImplTest { private HostDao _hostDao; @Mock private StoragePoolTagsDao storagePoolTagsDao; + @Mock + private HypervisorCapabilitiesDao hypervisorCapabilitiesDao; private DetachVolumeCmd detachCmd = new DetachVolumeCmd(); private Class _detachCmdClass = detachCmd.getClass(); From dd1b02832946c83e1cbf4192d75e589bcfa346a2 Mon Sep 17 00:00:00 2001 From: nvazquez Date: Tue, 16 Jul 2019 15:09:09 -0300 Subject: [PATCH 5/5] Reduce number of invokations --- .../src/main/java/com/cloud/storage/VolumeApiServiceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 1c1a5697f5bc..aa3c8522dc71 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -266,6 +266,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic private List _storagePoolAllocators; + private List supportingDefaultHV; + VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this); static final ConfigKey VmJobCheckInterval = new ConfigKey("Advanced", Long.class, "vm.job.check.interval", "3000", "Interval in milliseconds to check if the job is complete", false); @@ -3010,7 +3012,6 @@ private int getMaxDataVolumesSupported(UserVmVO vm) { _hostDao.loadDetails(host); maxDataVolumesSupported = _hypervisorCapabilitiesDao.getMaxDataVolumesLimit(host.getHypervisorType(), host.getDetail("product_version")); } else { - List supportingDefaultHV = _hypervisorCapabilitiesDao.getHypervisorsWithDefaultEntries(); HypervisorType hypervisorType = vm.getHypervisorType(); if (hypervisorType != null && CollectionUtils.isNotEmpty(supportingDefaultHV) && supportingDefaultHV.contains(hypervisorType)) { maxDataVolumesSupported = _hypervisorCapabilitiesDao.getMaxDataVolumesLimit(hypervisorType, "default"); @@ -3062,6 +3063,7 @@ private Long getDeviceId(UserVmVO vm, Long deviceId) { public boolean configure(String name, Map params) { String maxVolumeSizeInGbString = _configDao.getValue(Config.MaxVolumeSize.toString()); _maxVolumeSizeInGb = NumbersUtil.parseLong(maxVolumeSizeInGbString, 2000); + supportingDefaultHV = _hypervisorCapabilitiesDao.getHypervisorsWithDefaultEntries(); return true; }