Skip to content

Commit 3f0fbf2

Browse files
committed
Merge pull request #1953 from Accelerite/CLOUDSTACK-9794
CLOUDSTACK-9794: Unable to attach more than 14 devices to a VMUpdated hardcoded value with max data volumes limit from hypervisor capabilities. * pr/1953: CLOUDSTACK-9794: Unable to attach more than 14 devices to a VM Signed-off-by: Rajani Karuturi <rajani.karuturi@accelerite.com>
2 parents 9b85cbc + 93f5b6e commit 3f0fbf2

2 files changed

Lines changed: 38 additions & 21 deletions

File tree

plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -584,18 +584,36 @@ public void defFileBasedDisk(String filePath, String diskLabel, DiskBus bus, Dis
584584

585585
/* skip iso label */
586586
private String getDevLabel(int devId, DiskBus bus) {
587+
if (devId < 0) {
588+
return "";
589+
}
590+
587591
if (devId == 2) {
588592
devId++;
589593
}
590594

591-
char suffix = (char)('a' + devId);
592595
if (bus == DiskBus.SCSI) {
593-
return "sd" + suffix;
596+
return "sd" + getDevLabelSuffix(devId);
594597
} else if (bus == DiskBus.VIRTIO) {
595-
return "vd" + suffix;
598+
return "vd" + getDevLabelSuffix(devId);
599+
}
600+
return "hd" + getDevLabelSuffix(devId);
601+
}
602+
603+
private String getDevLabelSuffix(int deviceIndex) {
604+
if (deviceIndex < 0) {
605+
return "";
596606
}
597-
return "hd" + suffix;
598607

608+
int base = 'z' - 'a' + 1;
609+
String labelSuffix = "";
610+
do {
611+
char suffix = (char)('a' + (deviceIndex % base));
612+
labelSuffix = suffix + labelSuffix;
613+
deviceIndex = (deviceIndex / base) - 1;
614+
} while (deviceIndex >= 0);
615+
616+
return labelSuffix;
599617
}
600618

601619
public void defFileBasedDisk(String filePath, int devId, DiskBus bus, DiskFmtType diskFmtType) {
@@ -716,11 +734,6 @@ public DiskFmtType getDiskFormatType() {
716734
return _diskFmtType;
717735
}
718736

719-
public int getDiskSeq() {
720-
char suffix = _diskLabel.charAt(_diskLabel.length() - 1);
721-
return suffix - 'a';
722-
}
723-
724737
public void setBytesReadRate(Long bytesReadRate) {
725738
_bytesReadRate = bytesReadRate;
726739
}

server/src/com/cloud/storage/VolumeApiServiceImpl.java

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,9 +1433,9 @@ public Volume attachVolumeToVM(Long vmId, Long volumeId, Long deviceId) {
14331433
// that supported by hypervisor
14341434
if (deviceId == null || deviceId.longValue() != 0) {
14351435
List<VolumeVO> existingDataVolumes = _volsDao.findByInstanceAndType(vmId, Volume.Type.DATADISK);
1436-
int maxDataVolumesSupported = getMaxDataVolumesSupported(vm);
1437-
if (existingDataVolumes.size() >= maxDataVolumesSupported) {
1438-
throw new InvalidParameterValueException("The specified VM already has the maximum number of data disks (" + maxDataVolumesSupported + "). Please specify another VM.");
1436+
int maxAttachableDataVolumesSupported = getMaxDataVolumesSupported(vm) - 2; //IDs: 0 (ROOT) and 3 (CD-ROM) are reserved
1437+
if (existingDataVolumes.size() >= maxAttachableDataVolumesSupported) {
1438+
throw new InvalidParameterValueException("The specified VM already has the maximum number of data disks (" + maxAttachableDataVolumesSupported + ") attached. Please specify another VM.");
14391439
}
14401440
}
14411441

@@ -2527,7 +2527,7 @@ private VolumeVO sendAttachVolumeCommand(UserVmVO vm, VolumeVO volumeToAttach, L
25272527

25282528
DataTO volTO = volFactory.getVolume(volumeToAttach.getId()).getTO();
25292529

2530-
deviceId = getDeviceId(vm.getId(), deviceId);
2530+
deviceId = getDeviceId(vm, deviceId);
25312531

25322532
DiskTO disk = storageMgr.getDiskWithThrottling(volTO, volumeToAttach.getVolumeType(), deviceId, volumeToAttach.getPath(),
25332533
vm.getServiceOfferingId(), volumeToAttach.getDiskOfferingId());
@@ -2585,7 +2585,7 @@ private VolumeVO sendAttachVolumeCommand(UserVmVO vm, VolumeVO volumeToAttach, L
25852585
_volsDao.update(volumeToAttach.getId(), volumeToAttach);
25862586
}
25872587
} else {
2588-
deviceId = getDeviceId(vm.getId(), deviceId);
2588+
deviceId = getDeviceId(vm, deviceId);
25892589

25902590
_volsDao.attachVolume(volumeToAttach.getId(), vm.getId(), deviceId);
25912591
}
@@ -2623,7 +2623,7 @@ private int getMaxDataVolumesSupported(UserVmVO vm) {
26232623
_hostDao.loadDetails(host);
26242624
maxDataVolumesSupported = _hypervisorCapabilitiesDao.getMaxDataVolumesLimit(host.getHypervisorType(), host.getDetail("product_version"));
26252625
}
2626-
if (maxDataVolumesSupported == null) {
2626+
if (maxDataVolumesSupported == null || maxDataVolumesSupported.intValue() <= 0) {
26272627
maxDataVolumesSupported = 6; // 6 data disks by default if nothing
26282628
// is specified in
26292629
// 'hypervisor_capabilities' table
@@ -2632,28 +2632,32 @@ private int getMaxDataVolumesSupported(UserVmVO vm) {
26322632
return maxDataVolumesSupported.intValue();
26332633
}
26342634

2635-
private Long getDeviceId(long vmId, Long deviceId) {
2635+
private Long getDeviceId(UserVmVO vm, Long deviceId) {
26362636
// allocate deviceId
2637-
List<VolumeVO> vols = _volsDao.findByInstance(vmId);
2637+
int maxDeviceId = getMaxDataVolumesSupported(vm) - 1;
2638+
List<VolumeVO> vols = _volsDao.findByInstance(vm.getId());
26382639
if (deviceId != null) {
2639-
if (deviceId.longValue() > 15 || deviceId.longValue() == 3) {
2640-
throw new RuntimeException("deviceId should be 1,2,4-15");
2640+
if (deviceId.longValue() <= 0 || deviceId.longValue() > maxDeviceId || deviceId.longValue() == 3) {
2641+
throw new RuntimeException("deviceId should be 1,2,4-" + maxDeviceId);
26412642
}
26422643
for (VolumeVO vol : vols) {
26432644
if (vol.getDeviceId().equals(deviceId)) {
2644-
throw new RuntimeException("deviceId " + deviceId + " is used by vm" + vmId);
2645+
throw new RuntimeException("deviceId " + deviceId + " is used by vm " + vm.getId());
26452646
}
26462647
}
26472648
} else {
26482649
// allocate deviceId here
26492650
List<String> devIds = new ArrayList<String>();
2650-
for (int i = 1; i < 15; i++) {
2651+
for (int i = 1; i <= maxDeviceId; i++) {
26512652
devIds.add(String.valueOf(i));
26522653
}
26532654
devIds.remove("3");
26542655
for (VolumeVO vol : vols) {
26552656
devIds.remove(vol.getDeviceId().toString().trim());
26562657
}
2658+
if (devIds.isEmpty()) {
2659+
throw new RuntimeException("All device Ids are used by vm " + vm.getId());
2660+
}
26572661
deviceId = Long.parseLong(devIds.iterator().next());
26582662
}
26592663

0 commit comments

Comments
 (0)