From 6bc1d1247aa6dcce8b8050c84054d175433e1e83 Mon Sep 17 00:00:00 2001 From: Koushik Das Date: Tue, 31 Jul 2012 19:13:05 +0530 Subject: [PATCH] Fix for CS-15631 Support for up to 16 VDIs per VM on XS 6.0 and above (16 VDIs => root + cd + 14 data volumes). Currently in CS number of data disk that can be attached to VM is hard-coded to 6. Made this setting configurable by moving it to hypervisor capabilities. Although XS 6.0 and above supports upto 16 VDIs but while testing on XS 6.0.2 found that only 13 data volumes can be attached to a VM. So for XS 6.0 and 6.0.2 max_data_volumes_limit is set to 13 currently. Reviewed-by: Nitin --- .../hypervisor/HypervisorCapabilities.java | 5 ++- .../hypervisor/HypervisorCapabilitiesVO.java | 12 ++++++ .../dao/HypervisorCapabilitiesDao.java | 5 ++- .../dao/HypervisorCapabilitiesDaoImpl.java | 41 ++++++++++++++++++- .../src/com/cloud/vm/UserVmManagerImpl.java | 25 +++++++++-- setup/db/create-schema.sql | 5 ++- setup/db/db/schema-304to305.sql | 3 ++ 7 files changed, 86 insertions(+), 10 deletions(-) diff --git a/api/src/com/cloud/hypervisor/HypervisorCapabilities.java b/api/src/com/cloud/hypervisor/HypervisorCapabilities.java index 7efd355f471..524da8e5d2c 100644 --- a/api/src/com/cloud/hypervisor/HypervisorCapabilities.java +++ b/api/src/com/cloud/hypervisor/HypervisorCapabilities.java @@ -39,5 +39,8 @@ public interface HypervisorCapabilities { */ Long getMaxGuestsLimit(); - + /** + * @return the max. data volumes supported by hypervisor + */ + Integer getMaxDataVolumesLimit(); } diff --git a/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java b/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java index 7084d8adb67..13017036aea 100644 --- a/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java +++ b/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java @@ -51,6 +51,9 @@ public class HypervisorCapabilitiesVO implements HypervisorCapabilities, Identit @Column(name="uuid") private String uuid; + @Column(name="max_data_volumes_limit") + private Integer maxDataVolumesLimit; + protected HypervisorCapabilitiesVO() { this.uuid = UUID.randomUUID().toString(); } @@ -139,6 +142,15 @@ public class HypervisorCapabilitiesVO implements HypervisorCapabilities, Identit public void setUuid(String uuid) { this.uuid = uuid; } + + @Override + public Integer getMaxDataVolumesLimit() { + return maxDataVolumesLimit; + } + + public void setMaxDataVolumesLimit(Integer maxDataVolumesLimit) { + this.maxDataVolumesLimit = maxDataVolumesLimit; + } @Override public boolean equals(Object obj) { diff --git a/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java b/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java index 0e9e64a968b..d2073be0637 100644 --- a/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java +++ b/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java @@ -24,6 +24,7 @@ public interface HypervisorCapabilitiesDao extends GenericDao HypervisorTypeSearch; protected final SearchBuilder HypervisorTypeAndVersionSearch; - protected final GenericSearchBuilder MaxGuestLimitByHypervisorSearch; + protected final GenericSearchBuilder MaxGuestLimitByHypervisorSearch; + protected final GenericSearchBuilder MaxDataVolumesLimitByHypervisorSearch; private static final String DEFAULT_VERSION = "default"; @@ -50,7 +51,13 @@ public class HypervisorCapabilitiesDaoImpl extends GenericDaoBase sc = MaxDataVolumesLimitByHypervisorSearch.create(); + sc.setParameters("hypervisorType", hypervisorType); + sc.setParameters("hypervisorVersion", hypervisorVersion); + List limitList = customSearch(sc, null); + if (!limitList.isEmpty()) { + result = limitList.get(0); + } else { + useDefault = true; + } + } else { + useDefault = true; + } + // If data is not available for a specific hypervisor version then use 'default' as the version + if (useDefault) { + SearchCriteria sc = MaxDataVolumesLimitByHypervisorSearch.create(); + sc.setParameters("hypervisorType", hypervisorType); + sc.setParameters("hypervisorVersion", DEFAULT_VERSION); + List limitList = customSearch(sc, null); + if (!limitList.isEmpty()) { + result = limitList.get(0); + } + } + return result; } } \ No newline at end of file diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 573c06ceae0..54310ded9b8 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -508,6 +508,24 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } } + private int getMaxDataVolumesSupported(UserVmVO vm) { + Long hostId = vm.getHostId(); + if (hostId == null) { + hostId = vm.getLastHostId(); + } + HostVO host = _hostDao.findById(hostId); + Integer maxDataVolumesSupported = null; + if (host != null) { + _hostDao.loadDetails(host); + maxDataVolumesSupported = _hypervisorCapabilitiesDao.getMaxDataVolumesLimit(host.getHypervisorType(), host.getDetail("product_version")); + } + if (maxDataVolumesSupported == null) { + maxDataVolumesSupported = 6; // 6 data disks by default if nothing is specified in 'hypervisor_capabilities' table + } + + return maxDataVolumesSupported.intValue(); + } + @Override @ActionEvent(eventType = EventTypes.EVENT_VOLUME_ATTACH, eventDescription = "attaching volume", async = true) public Volume attachVolumeToVM(AttachVolumeCmd command) { @@ -551,10 +569,11 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } } - // Check that the VM has less than 6 data volumes attached + // Check that the number of data volumes attached to VM is less than that supported by hypervisor List existingDataVolumes = _volsDao.findByInstanceAndType(vmId, Volume.Type.DATADISK); - if (existingDataVolumes.size() >= 6) { - throw new InvalidParameterValueException("The specified VM already has the maximum number of data disks (6). Please specify another VM.", null); + int maxDataVolumesSupported = getMaxDataVolumesSupported(vm); + if (existingDataVolumes.size() >= maxDataVolumesSupported) { + throw new InvalidParameterValueException("The specified VM already has the maximum number of data disks (" + maxDataVolumesSupported + "). Please specify another VM.", null); } // Check that the VM and the volume are in the same zone diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index a081749af9c..8a8e7bd90f9 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -1581,6 +1581,7 @@ CREATE TABLE `cloud`.`hypervisor_capabilities` ( `hypervisor_version` varchar(32), `max_guests_limit` bigint unsigned DEFAULT 50, `security_group_enabled` int(1) unsigned DEFAULT 1 COMMENT 'Is security group supported', + `max_data_volumes_limit` int unsigned DEFAULT 6 COMMENT 'Max. data volumes per VM supported by hypervisor', PRIMARY KEY (`id`), CONSTRAINT `uc_hypervisor_capabilities__uuid` UNIQUE (`uuid`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; @@ -1590,8 +1591,8 @@ INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES ('XenServer', '5.6', 50, 1); INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES ('XenServer', '5.6 FP1', 50, 1); INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES ('XenServer', '5.6 SP2', 50, 1); -INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES ('XenServer', '6.0', 50, 1); -INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES ('XenServer', '6.0.2', 50, 1); +INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_data_volumes_limit) VALUES ('XenServer', '6.0', 50, 1, 13); +INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_data_volumes_limit) VALUES ('XenServer', '6.0.2', 50, 1, 13); INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES ('VMware', 'default', 128, 0); INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES ('VMware', '4.0', 128, 0); INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES ('VMware', '4.1', 128, 0); diff --git a/setup/db/db/schema-304to305.sql b/setup/db/db/schema-304to305.sql index 29d79675fec..7c54ddbadda 100755 --- a/setup/db/db/schema-304to305.sql +++ b/setup/db/db/schema-304to305.sql @@ -342,3 +342,6 @@ CREATE TABLE `cloud`.`s2s_vpn_connection` ( ALTER TABLE `cloud`.`data_center` ADD COLUMN `is_local_storage_enabled` tinyint NOT NULL DEFAULT 0 COMMENT 'Is local storage offering enabled for this data center; 1: enabled, 0: not'; UPDATE `cloud`.`data_center` SET `is_local_storage_enabled` = IF ((SELECT `value` FROM `cloud`.`configuration` WHERE `name`='use.local.storage')='true', 1, 0) WHERE `removed` IS NULL; + +ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN `max_data_volumes_limit` int unsigned DEFAULT 6 COMMENT 'Max. data volumes per VM supported by hypervisor'; +UPDATE TABLE `cloud`.`hypervisor_capabilities` SET `max_data_volumes_limit`=13 WHERE `hypervisor_type`='XenServer' AND (`hypervisor_version`='6.0' OR `hypervisor_version`='6.0.2');