diff --git a/api/src/com/cloud/hypervisor/HypervisorCapabilities.java b/api/src/com/cloud/hypervisor/HypervisorCapabilities.java index d0fcf01cf16..f91da354c96 100644 --- a/api/src/com/cloud/hypervisor/HypervisorCapabilities.java +++ b/api/src/com/cloud/hypervisor/HypervisorCapabilities.java @@ -43,5 +43,8 @@ public interface HypervisorCapabilities { */ Long getMaxGuestsLimit(); - + /** + * @return the max. data volumes per VM supported by hypervisor + */ + Integer getMaxDataVolumesLimit(); } diff --git a/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java b/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java index 33cafbc92d9..75eebeb0dbc 100644 --- a/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java +++ b/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java @@ -55,6 +55,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(); } @@ -144,6 +147,15 @@ public class HypervisorCapabilitiesVO implements HypervisorCapabilities, Identit this.uuid = uuid; } + @Override + public Integer getMaxDataVolumesLimit() { + return maxDataVolumesLimit; + } + + public void setMaxDataVolumesLimit(Integer maxDataVolumesLimit) { + this.maxDataVolumesLimit = maxDataVolumesLimit; + } + @Override public boolean equals(Object obj) { if (obj instanceof HypervisorCapabilitiesVO) { diff --git a/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java b/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java index c7fb96935c7..8f4a47584b3 100644 --- a/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java +++ b/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java @@ -28,6 +28,7 @@ public interface HypervisorCapabilitiesDao extends GenericDao HypervisorTypeSearch; protected final SearchBuilder HypervisorTypeAndVersionSearch; protected final GenericSearchBuilder MaxGuestLimitByHypervisorSearch; - + protected final GenericSearchBuilder MaxDataVolumesLimitByHypervisorSearch; + private static final String DEFAULT_VERSION = "default"; protected HypervisorCapabilitiesDaoImpl() { @@ -54,7 +55,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 ab92c6b1585..fa988afc9f9 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -505,6 +505,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) { @@ -548,10 +566,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."); + 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."); } // 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 64c81a3dc68..b327106a42a 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -1565,6 +1565,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; @@ -1574,8 +1575,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-303to40.sql b/setup/db/db/schema-303to40.sql index c90d73be631..4ce8e65d1a2 100644 --- a/setup/db/db/schema-303to40.sql +++ b/setup/db/db/schema-303to40.sql @@ -80,5 +80,10 @@ DEALLOCATE PREPARE stmt1; AlTER TABLE physical_network_service_providers ADD CONSTRAINT `fk_pnetwork_service_providers__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE; UPDATE `cloud`.`configuration` SET description='In second, timeout for creating volume from snapshot' WHERE name='create.volume.from.snapshot.wait'; +ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN `max_data_volumes_limit` int unsigned DEFAULT 6 COMMENT 'Max. data volumes per VM supported by hypervisor'; +SET SQL_SAFE_UPDATES=0; +UPDATE `cloud`.`hypervisor_capabilities` SET `max_data_volumes_limit`=13 WHERE `hypervisor_type`='XenServer' AND (`hypervisor_version`='6.0' OR `hypervisor_version`='6.0.2'); +SET SQL_SAFE_UPDATES=1; +