in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java [3185:3417]
public void createVbd(final Connect conn, final VirtualMachineTO vmSpec, final String vmName, final LibvirtVMDef vm) throws InternalErrorException, LibvirtException, URISyntaxException {
final Map<String, String> details = vmSpec.getDetails();
final List<DiskTO> disks = Arrays.asList(vmSpec.getDisks());
boolean isSecureBoot = false;
boolean isWindowsTemplate = false;
Collections.sort(disks, new Comparator<DiskTO>() {
@Override
public int compare(final DiskTO arg0, final DiskTO arg1) {
return arg0.getDiskSeq() > arg1.getDiskSeq() ? 1 : -1;
}
});
boolean isUefiEnabled = MapUtils.isNotEmpty(details) && details.containsKey(GuestDef.BootType.UEFI.toString());
if (isUefiEnabled) {
isSecureBoot = isSecureMode(details.get(GuestDef.BootType.UEFI.toString()));
}
if (vmSpec.getOs().toLowerCase().contains("window")) {
isWindowsTemplate =true;
}
for (final DiskTO volume : disks) {
KVMPhysicalDisk physicalDisk = null;
KVMStoragePool pool = null;
final DataTO data = volume.getData();
if (volume.getType() == Volume.Type.ISO && data.getPath() != null) {
DataStoreTO dataStore = data.getDataStore();
String dataStoreUrl = null;
if (data.getPath().startsWith(ConfigDrive.CONFIGDRIVEDIR) && vmSpec.isConfigDriveOnHostCache() && data instanceof TemplateObjectTO) {
String configDrivePath = getConfigPath() + "/" + data.getPath();
physicalDisk = new KVMPhysicalDisk(configDrivePath, ((TemplateObjectTO) data).getUuid(), null);
physicalDisk.setFormat(PhysicalDiskFormat.FILE);
} else if (dataStore instanceof NfsTO) {
NfsTO nfsStore = (NfsTO)data.getDataStore();
dataStoreUrl = nfsStore.getUrl();
physicalDisk = getPhysicalDiskFromNfsStore(dataStoreUrl, data);
} else if (dataStore instanceof PrimaryDataStoreTO) {
//In order to support directly downloaded ISOs
PrimaryDataStoreTO primaryDataStoreTO = (PrimaryDataStoreTO) dataStore;
if (primaryDataStoreTO.getPoolType().equals(StoragePoolType.NetworkFilesystem)) {
String psHost = primaryDataStoreTO.getHost();
String psPath = primaryDataStoreTO.getPath();
dataStoreUrl = "nfs://" + psHost + File.separator + psPath;
physicalDisk = getPhysicalDiskFromNfsStore(dataStoreUrl, data);
} else if (primaryDataStoreTO.getPoolType().equals(StoragePoolType.SharedMountPoint) ||
primaryDataStoreTO.getPoolType().equals(StoragePoolType.Filesystem) ||
primaryDataStoreTO.getPoolType().equals(StoragePoolType.StorPool) ||
primaryDataStoreTO.getPoolType().equals(StoragePoolType.Linstor)) {
physicalDisk = getPhysicalDiskPrimaryStore(primaryDataStoreTO, data);
}
}
} else if (volume.getType() != Volume.Type.ISO) {
final PrimaryDataStoreTO store = (PrimaryDataStoreTO)data.getDataStore();
physicalDisk = getStoragePoolMgr().getPhysicalDisk(store.getPoolType(), store.getUuid(), data.getPath());
pool = physicalDisk.getPool();
}
String volPath = null;
if (physicalDisk != null) {
volPath = physicalDisk.getPath();
}
if (volume.getType() != Volume.Type.ISO
&& physicalDisk != null && physicalDisk.getFormat() == PhysicalDiskFormat.QCOW2
&& (pool.getType() == StoragePoolType.NetworkFilesystem
|| pool.getType() == StoragePoolType.SharedMountPoint
|| pool.getType() == StoragePoolType.Filesystem
|| pool.getType() == StoragePoolType.Gluster
|| pool.getType() == StoragePoolType.StorPool)) {
setBackingFileFormat(physicalDisk.getPath());
}
// check for disk activity, if detected we should exit because vm is running elsewhere
if (diskActivityCheckEnabled && physicalDisk != null && physicalDisk.getFormat() == PhysicalDiskFormat.QCOW2) {
LOGGER.debug("Checking physical disk file at path " + volPath + " for disk activity to ensure vm is not running elsewhere");
try {
HypervisorUtils.checkVolumeFileForActivity(volPath, diskActivityCheckTimeoutSeconds, diskActivityInactiveThresholdMilliseconds, diskActivityCheckFileSizeMin);
} catch (final IOException ex) {
throw new CloudRuntimeException("Unable to check physical disk file for activity", ex);
}
LOGGER.debug("Disk activity check cleared");
}
// if params contains a rootDiskController key, use its value (this is what other HVs are doing)
DiskDef.DiskBus diskBusType = getDiskModelFromVMDetail(vmSpec);
if (diskBusType == null) {
diskBusType = getGuestDiskModel(vmSpec.getPlatformEmulator(), isUefiEnabled);
}
DiskDef.DiskBus diskBusTypeData = getDataDiskModelFromVMDetail(vmSpec);
if (diskBusTypeData == null) {
diskBusTypeData = (diskBusType == DiskDef.DiskBus.SCSI) ? diskBusType : DiskDef.DiskBus.VIRTIO;
}
final DiskDef disk = new DiskDef();
int devId = volume.getDiskSeq().intValue();
if (volume.getType() == Volume.Type.ISO) {
final DiskDef.DiskType diskType = getDiskType(physicalDisk);
disk.defISODisk(volPath, devId, isUefiEnabled, diskType);
if (guestCpuArch != null && (guestCpuArch.equals("aarch64") || guestCpuArch.equals("s390x"))) {
disk.setBusType(DiskDef.DiskBus.SCSI);
}
} else {
if (pool == null) {
throw new CloudRuntimeException(String.format("Found null pool for volume %s", volume));
}
disk.setLogicalBlockIOSize(pool.getSupportedLogicalBlockSize());
disk.setPhysicalBlockIOSize(pool.getSupportedPhysicalBlockSize());
if (diskBusType == DiskDef.DiskBus.SCSI || diskBusType == DiskDef.DiskBus.VIRTIOBLK) {
disk.setQemuDriver(true);
disk.setDiscard(DiscardType.UNMAP);
}
boolean iothreadsEnabled = MapUtils.isNotEmpty(details) && details.containsKey(VmDetailConstants.IOTHREADS);
disk.isIothreadsEnabled(iothreadsEnabled);
String ioDriver = null;
if (MapUtils.isNotEmpty(volume.getDetails()) && volume.getDetails().containsKey(VmDetailConstants.IO_POLICY)) {
ioDriver = volume.getDetails().get(VmDetailConstants.IO_POLICY).toUpperCase();
} else if (iothreadsEnabled) {
ioDriver = IoDriverPolicy.THREADS.name();
}
setDiskIoDriver(disk, getIoDriverForTheStorage(ioDriver));
if (pool.getType() == StoragePoolType.RBD) {
/*
For RBD pools we use the secret mechanism in libvirt.
We store the secret under the UUID of the pool, that's why
we pass the pool's UUID as the authSecret
*/
disk.defNetworkBasedDisk(physicalDisk.getPath().replace("rbd:", ""), pool.getSourceHost(), pool.getSourcePort(), pool.getAuthUserName(),
pool.getUuid(), devId, diskBusType, DiskProtocol.RBD, DiskDef.DiskFmtType.RAW);
} else if (pool.getType() == StoragePoolType.PowerFlex) {
disk.defBlockBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData);
if (physicalDisk.getFormat().equals(PhysicalDiskFormat.QCOW2)) {
disk.setDiskFormatType(DiskDef.DiskFmtType.QCOW2);
}
} else if (pool.getType() == StoragePoolType.Gluster) {
final String mountpoint = pool.getLocalPath();
final String path = physicalDisk.getPath();
final String glusterVolume = pool.getSourceDir().replace("/", "");
disk.defNetworkBasedDisk(glusterVolume + path.replace(mountpoint, ""), pool.getSourceHost(), pool.getSourcePort(), null,
null, devId, diskBusType, DiskProtocol.GLUSTER, DiskDef.DiskFmtType.QCOW2);
} else if (pool.getType() == StoragePoolType.CLVM || physicalDisk.getFormat() == PhysicalDiskFormat.RAW) {
if (volume.getType() == Volume.Type.DATADISK && !(isWindowsTemplate && isUefiEnabled)) {
disk.defBlockBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData);
}
else {
disk.defBlockBasedDisk(physicalDisk.getPath(), devId, diskBusType);
}
if (pool.getType() == StoragePoolType.Linstor && isQemuDiscardBugFree(diskBusType)) {
disk.setDiscard(DiscardType.UNMAP);
}
} else {
if (volume.getType() == Volume.Type.DATADISK && !(isWindowsTemplate && isUefiEnabled)) {
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusTypeData, DiskDef.DiskFmtType.QCOW2);
} else {
if (isSecureBoot) {
disk.defFileBasedDisk(physicalDisk.getPath(), devId, DiskDef.DiskFmtType.QCOW2, isWindowsTemplate);
} else {
disk.defFileBasedDisk(physicalDisk.getPath(), devId, diskBusType, DiskDef.DiskFmtType.QCOW2);
}
}
}
pool.customizeLibvirtDiskDef(disk);
}
if (data instanceof VolumeObjectTO) {
final VolumeObjectTO volumeObjectTO = (VolumeObjectTO)data;
disk.setSerial(diskUuidToSerial(volumeObjectTO.getUuid()));
setBurstProperties(volumeObjectTO, disk);
if (volumeObjectTO.getCacheMode() != null) {
disk.setCacheMode(DiskDef.DiskCacheMode.valueOf(volumeObjectTO.getCacheMode().toString().toUpperCase()));
}
if (volumeObjectTO.requiresEncryption() &&
pool.getType().encryptionSupportMode() == Storage.EncryptionSupport.Hypervisor ) {
String secretUuid = createLibvirtVolumeSecret(conn, volumeObjectTO.getPath(), volumeObjectTO.getPassphrase());
DiskDef.LibvirtDiskEncryptDetails encryptDetails = new DiskDef.LibvirtDiskEncryptDetails(secretUuid, QemuObject.EncryptFormat.enumValue(volumeObjectTO.getEncryptFormat()));
disk.setLibvirtDiskEncryptDetails(encryptDetails);
}
}
if (vm.getDevices() == null) {
LOGGER.error("There is no devices for" + vm);
throw new RuntimeException("There is no devices for" + vm);
}
vm.getDevices().addDevice(disk);
}
if (vmSpec.getType() != VirtualMachine.Type.User) {
final DiskDef iso = new DiskDef();
iso.defISODisk(sysvmISOPath, DiskDef.DiskType.FILE);
if (guestCpuArch != null && (guestCpuArch.equals("aarch64") || guestCpuArch.equals("s390x"))) {
iso.setBusType(DiskDef.DiskBus.SCSI);
}
vm.getDevices().addDevice(iso);
}
// For LXC, find and add the root filesystem, rbd data disks
if (HypervisorType.LXC.toString().toLowerCase().equals(vm.getHvsType())) {
for (final DiskTO volume : disks) {
final DataTO data = volume.getData();
final PrimaryDataStoreTO store = (PrimaryDataStoreTO)data.getDataStore();
if (volume.getType() == Volume.Type.ROOT) {
final KVMPhysicalDisk physicalDisk = storagePoolManager.getPhysicalDisk(store.getPoolType(), store.getUuid(), data.getPath());
final FilesystemDef rootFs = new FilesystemDef(physicalDisk.getPath(), "/");
vm.getDevices().addDevice(rootFs);
} else if (volume.getType() == Volume.Type.DATADISK) {
final KVMPhysicalDisk physicalDisk = storagePoolManager.getPhysicalDisk(store.getPoolType(), store.getUuid(), data.getPath());
final KVMStoragePool pool = physicalDisk.getPool();
if(StoragePoolType.RBD.equals(pool.getType())) {
final int devId = volume.getDiskSeq().intValue();
final String device = mapRbdDevice(physicalDisk);
if (device != null) {
LOGGER.debug("RBD device on host is: " + device);
final DiskDef diskdef = new DiskDef();
diskdef.defBlockBasedDisk(device, devId, DiskDef.DiskBus.VIRTIO);
diskdef.setQemuDriver(false);
vm.getDevices().addDevice(diskdef);
} else {
throw new InternalErrorException("Error while mapping RBD device on host");
}
}
}
}
}
}