mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Fix: memory leak on volume allocation (#7136)
This commit is contained in:
parent
f39b02aec7
commit
c78a777d3a
@ -147,13 +147,7 @@ public class DeployDestination implements Serializable {
|
|||||||
destination.append("Storage(");
|
destination.append("Storage(");
|
||||||
if (displayStorage && _storage != null) {
|
if (displayStorage && _storage != null) {
|
||||||
StringBuffer storageBuf = new StringBuffer();
|
StringBuffer storageBuf = new StringBuffer();
|
||||||
//String storageStr = "";
|
|
||||||
for (Volume vol : _storage.keySet()) {
|
for (Volume vol : _storage.keySet()) {
|
||||||
if (!storageBuf.toString().equals("")) {
|
|
||||||
storageBuf.append(storageBuf.toString());
|
|
||||||
storageBuf.append(", ");
|
|
||||||
}
|
|
||||||
storageBuf.append(storageBuf);
|
|
||||||
storageBuf.append("Volume(");
|
storageBuf.append("Volume(");
|
||||||
storageBuf.append(vol.getId());
|
storageBuf.append(vol.getId());
|
||||||
storageBuf.append("|");
|
storageBuf.append("|");
|
||||||
@ -162,7 +156,7 @@ public class DeployDestination implements Serializable {
|
|||||||
storageBuf.append(_storage.get(vol).getId());
|
storageBuf.append(_storage.get(vol).getId());
|
||||||
storageBuf.append(")");
|
storageBuf.append(")");
|
||||||
}
|
}
|
||||||
destination.append(storageBuf.toString());
|
destination.append(storageBuf);
|
||||||
}
|
}
|
||||||
return destination.append(")]").toString();
|
return destination.append(")]").toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -149,4 +149,12 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
|
|||||||
* @return the number of hosts/agents this {@see ManagementServer} has responsibility over
|
* @return the number of hosts/agents this {@see ManagementServer} has responsibility over
|
||||||
*/
|
*/
|
||||||
int countByMs(long msid);
|
int countByMs(long msid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the hypervisor versions of the hosts in the datacenter which are in Up state in ascending order
|
||||||
|
* @param datacenterId data center id
|
||||||
|
* @param hypervisorType hypervisor type of the hosts
|
||||||
|
* @return ordered list of hypervisor versions
|
||||||
|
*/
|
||||||
|
List<String> listOrderedHostsHypervisorVersionsInDatacenter(long datacenterId, HypervisorType hypervisorType);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,7 +90,10 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
|
|||||||
"from vm_instance vm " +
|
"from vm_instance vm " +
|
||||||
"join host h on (vm.host_id=h.id) " +
|
"join host h on (vm.host_id=h.id) " +
|
||||||
"where vm.service_offering_id= ? and vm.state not in (\"Destroyed\", \"Expunging\", \"Error\") group by h.id";
|
"where vm.service_offering_id= ? and vm.state not in (\"Destroyed\", \"Expunging\", \"Error\") group by h.id";
|
||||||
|
private static final String GET_ORDERED_HW_VERSIONS_IN_DC = "select hypervisor_version from host " +
|
||||||
|
"where type = 'Routing' and status = 'Up' and hypervisor_type = ? and data_center_id = ? " +
|
||||||
|
"group by hypervisor_version " +
|
||||||
|
"order by hypervisor_version asc";
|
||||||
|
|
||||||
protected SearchBuilder<HostVO> TypePodDcStatusSearch;
|
protected SearchBuilder<HostVO> TypePodDcStatusSearch;
|
||||||
|
|
||||||
@ -1299,6 +1302,25 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
|
|||||||
return getCount(sc);
|
return getCount(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> listOrderedHostsHypervisorVersionsInDatacenter(long datacenterId, HypervisorType hypervisorType) {
|
||||||
|
PreparedStatement pstmt = null;
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
TransactionLegacy txn = TransactionLegacy.currentTxn();
|
||||||
|
pstmt = txn.prepareAutoCloseStatement(GET_ORDERED_HW_VERSIONS_IN_DC);
|
||||||
|
pstmt.setString(1, Objects.toString(hypervisorType));
|
||||||
|
pstmt.setLong(2, datacenterId);
|
||||||
|
ResultSet resultSet = pstmt.executeQuery();
|
||||||
|
while (resultSet.next()) {
|
||||||
|
result.add(resultSet.getString(1));
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
s_logger.error("Error trying to obtain hypervisor version on datacenter", e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<HostVO> listAllHostsByType(Host.Type type) {
|
public List<HostVO> listAllHostsByType(Host.Type type) {
|
||||||
SearchCriteria<HostVO> sc = TypeSearch.create();
|
SearchCriteria<HostVO> sc = TypeSearch.create();
|
||||||
|
|||||||
@ -4078,7 +4078,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||||||
} else {
|
} else {
|
||||||
HypervisorType hypervisorType = vm.getHypervisorType();
|
HypervisorType hypervisorType = vm.getHypervisorType();
|
||||||
if (hypervisorType != null && CollectionUtils.isNotEmpty(supportingDefaultHV) && supportingDefaultHV.contains(hypervisorType)) {
|
if (hypervisorType != null && CollectionUtils.isNotEmpty(supportingDefaultHV) && supportingDefaultHV.contains(hypervisorType)) {
|
||||||
maxDataVolumesSupported = _hypervisorCapabilitiesDao.getMaxDataVolumesLimit(hypervisorType, "default");
|
String hwVersion = getMinimumHypervisorVersionInDatacenter(vm.getDataCenterId(), hypervisorType);
|
||||||
|
maxDataVolumesSupported = _hypervisorCapabilitiesDao.getMaxDataVolumesLimit(hypervisorType, hwVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (maxDataVolumesSupported == null || maxDataVolumesSupported.intValue() <= 0) {
|
if (maxDataVolumesSupported == null || maxDataVolumesSupported.intValue() <= 0) {
|
||||||
@ -4090,6 +4091,16 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||||||
return maxDataVolumesSupported.intValue();
|
return maxDataVolumesSupported.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String getMinimumHypervisorVersionInDatacenter(long datacenterId, HypervisorType hypervisorType) {
|
||||||
|
String defaultHypervisorVersion = "default";
|
||||||
|
if (hypervisorType == HypervisorType.Simulator) {
|
||||||
|
return defaultHypervisorVersion;
|
||||||
|
}
|
||||||
|
List<String> hwVersions = _hostDao.listOrderedHostsHypervisorVersionsInDatacenter(datacenterId, hypervisorType);
|
||||||
|
String minHwVersion = CollectionUtils.isNotEmpty(hwVersions) ? hwVersions.get(0) : defaultHypervisorVersion;
|
||||||
|
return StringUtils.isBlank(minHwVersion) ? defaultHypervisorVersion : minHwVersion;
|
||||||
|
}
|
||||||
|
|
||||||
private Long getDeviceId(UserVmVO vm, Long deviceId) {
|
private Long getDeviceId(UserVmVO vm, Long deviceId) {
|
||||||
// allocate deviceId
|
// allocate deviceId
|
||||||
int maxDevices = getMaxDataVolumesSupported(vm) + 2; // add 2 to consider devices root volume and cdrom
|
int maxDevices = getMaxDataVolumesSupported(vm) + 2; // add 2 to consider devices root volume and cdrom
|
||||||
|
|||||||
@ -1197,4 +1197,36 @@ public class VolumeApiServiceImplTest {
|
|||||||
boolean result = volumeApiServiceImpl.isNewDiskOfferingTheSameAndCustomServiceOffering(existingDiskOffering, newDiskOffering);
|
boolean result = volumeApiServiceImpl.isNewDiskOfferingTheSameAndCustomServiceOffering(existingDiskOffering, newDiskOffering);
|
||||||
Assert.assertEquals(expectedResult, result);
|
Assert.assertEquals(expectedResult, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void testBaseListOrderedHostsHypervisorVersionInDc(List<String> hwVersions, HypervisorType hypervisorType,
|
||||||
|
String expected) {
|
||||||
|
when(_hostDao.listOrderedHostsHypervisorVersionsInDatacenter(anyLong(), any(HypervisorType.class)))
|
||||||
|
.thenReturn(hwVersions);
|
||||||
|
String min = volumeApiServiceImpl.getMinimumHypervisorVersionInDatacenter(1L, hypervisorType);
|
||||||
|
Assert.assertEquals(expected, min);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMinimumHypervisorVersionInDatacenterSimulator() {
|
||||||
|
List<String> hwVersions = List.of("4.17.3.0-SNAPSHOT");
|
||||||
|
HypervisorType hypervisorType = HypervisorType.Simulator;
|
||||||
|
String expected = "default";
|
||||||
|
testBaseListOrderedHostsHypervisorVersionInDc(hwVersions, hypervisorType, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMinimumHypervisorVersionInDatacenterEmptyVersion() {
|
||||||
|
List<String> hwVersions = List.of("", "xxxx", "yyyy");
|
||||||
|
HypervisorType hypervisorType = HypervisorType.KVM;
|
||||||
|
String expected = "default";
|
||||||
|
testBaseListOrderedHostsHypervisorVersionInDc(hwVersions, hypervisorType, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMinimumHypervisorVersionInDatacenterVersions() {
|
||||||
|
List<String> hwVersions = List.of("6.7", "6.7.1", "6.7.2");
|
||||||
|
HypervisorType hypervisorType = HypervisorType.VMware;
|
||||||
|
String expected = "6.7";
|
||||||
|
testBaseListOrderedHostsHypervisorVersionInDc(hwVersions, hypervisorType, expected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -873,6 +873,88 @@ class TestVMLifeCycle(cloudstackTestCase):
|
|||||||
|
|
||||||
self.assertEqual(Volume.list(self.apiclient, id=vol1.id), None, "List response contains records when it should not")
|
self.assertEqual(Volume.list(self.apiclient, id=vol1.id), None, "List response contains records when it should not")
|
||||||
|
|
||||||
|
@attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false")
|
||||||
|
def test_12_start_vm_multiple_volumes_allocated(self):
|
||||||
|
"""Test attaching multiple datadisks and start VM
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. Deploys a VM without starting it and attaches multiple datadisks to it
|
||||||
|
# 2. Start VM successfully
|
||||||
|
# 3. Destroys the VM with DataDisks option
|
||||||
|
|
||||||
|
custom_disk_offering = DiskOffering.list(self.apiclient, name='Custom')[0]
|
||||||
|
|
||||||
|
# Create VM without starting it
|
||||||
|
vm = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["small"],
|
||||||
|
accountid=self.account.name,
|
||||||
|
domainid=self.account.domainid,
|
||||||
|
serviceofferingid=self.small_offering.id,
|
||||||
|
startvm=False
|
||||||
|
)
|
||||||
|
self.cleanup.append(vm)
|
||||||
|
|
||||||
|
hosts = Host.list(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
type='Routing',
|
||||||
|
hypervisor=self.hypervisor,
|
||||||
|
state='Up')
|
||||||
|
|
||||||
|
if self.hypervisor.lower() in ["simulator"] or not hosts[0].hypervisorversion:
|
||||||
|
hypervisor_version = "default"
|
||||||
|
else:
|
||||||
|
hypervisor_version = hosts[0].hypervisorversion
|
||||||
|
|
||||||
|
res = self.dbclient.execute("select max_data_volumes_limit from hypervisor_capabilities where "
|
||||||
|
"hypervisor_type='%s' and hypervisor_version='%s';" %
|
||||||
|
(self.hypervisor.lower(), hypervisor_version))
|
||||||
|
if isinstance(res, list) and len(res) > 0:
|
||||||
|
max_volumes = res[0][0]
|
||||||
|
if max_volumes > 14:
|
||||||
|
max_volumes = 14
|
||||||
|
else:
|
||||||
|
max_volumes = 6
|
||||||
|
|
||||||
|
# Create and attach volumes
|
||||||
|
self.services["custom_volume"]["customdisksize"] = 1
|
||||||
|
self.services["custom_volume"]["zoneid"] = self.zone.id
|
||||||
|
for i in range(max_volumes):
|
||||||
|
volume = Volume.create_custom_disk(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["custom_volume"],
|
||||||
|
account=self.account.name,
|
||||||
|
domainid=self.account.domainid,
|
||||||
|
diskofferingid=custom_disk_offering.id
|
||||||
|
)
|
||||||
|
self.cleanup.append(volume)
|
||||||
|
VirtualMachine.attach_volume(vm, self.apiclient, volume)
|
||||||
|
|
||||||
|
# Start the VM
|
||||||
|
self.debug("Starting VM - ID: %s" % vm.id)
|
||||||
|
vm.start(self.apiclient)
|
||||||
|
list_vm_response = VirtualMachine.list(
|
||||||
|
self.apiclient,
|
||||||
|
id=vm.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_vm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_vm_response),
|
||||||
|
0,
|
||||||
|
"Check VM available in List Virtual Machines"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_vm_response[0].state,
|
||||||
|
"Running",
|
||||||
|
"Check virtual machine is in running state"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestSecuredVmMigration(cloudstackTestCase):
|
class TestSecuredVmMigration(cloudstackTestCase):
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user