package org.ovirt.engine.core.vdsbroker.vdsbroker; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.common.FeatureSupported; import org.ovirt.engine.core.common.businessentities.VmDevice; import org.ovirt.engine.core.common.businessentities.storage.CinderDisk; import org.ovirt.engine.core.common.businessentities.storage.Disk; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; import org.ovirt.engine.core.common.businessentities.storage.DiskInterface; import org.ovirt.engine.core.common.businessentities.storage.DiskVmElement; import org.ovirt.engine.core.common.businessentities.storage.LunDisk; import org.ovirt.engine.core.common.businessentities.storage.PropagateErrors; import org.ovirt.engine.core.common.businessentities.storage.VolumeFormat; import org.ovirt.engine.core.common.utils.VmDeviceType; import org.ovirt.engine.core.common.vdscommands.HotPlugDiskVDSParameters; import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.vdsbroker.builder.vminfo.VmInfoBuildUtils; public class HotPlugDiskVDSCommand<P extends HotPlugDiskVDSParameters> extends VdsBrokerCommand<P> { @Inject private VmInfoBuildUtils vmInfoBuildUtils; protected Map<String, Object> sendInfo = new HashMap<>(); public HotPlugDiskVDSCommand(P parameters) { super(parameters); } @Override protected void executeVdsBrokerCommand() { buildSendDataToVdsm(); status = getBroker().hotplugDisk(sendInfo); proceedProxyReturnValue(); } protected void buildSendDataToVdsm() { sendInfo.put("vmId", getParameters().getVmId().toString()); sendInfo.put("drive", initDriveData()); } private Map<String, Object> initDriveData() { Map<String, Object> drive = new HashMap<>(); Disk disk = getParameters().getDisk(); VmDevice vmDevice = getParameters().getVmDevice(); drive.put(VdsProperties.Type, VmDeviceType.DISK.getName()); drive.put(VdsProperties.Address, getParameters().getAddressMap() != null ? getParameters().getAddressMap() : StringUtils.EMPTY); drive.put(VdsProperties.INTERFACE, getParameters().getDiskInterface().getName()); if (FeatureSupported.passDiscardSupported(getParameters().getVm().getCompatibilityVersion())) { drive.put(VdsProperties.DISCARD, getParameters().isPassDiscard()); } int numOfIoThreads = getParameters().getVm().getNumOfIoThreads(); if (numOfIoThreads != 0 && getParameters().getDiskInterface() == DiskInterface.VirtIO) { if (vmDevice.getSpecParams() == null) { vmDevice.setSpecParams(new HashMap<>()); } List<DiskVmElement> diskVmElements = DbFacade.getInstance().getDiskVmElementDao().getAllPluggedToVm(getParameters().getVmId()); int numOfAttachedVirtioInterfaces = 0; for (DiskVmElement dve : diskVmElements) { if (dve.getDiskInterface() == DiskInterface.VirtIO) { numOfAttachedVirtioInterfaces ++; } } int pinToIoThread = numOfAttachedVirtioInterfaces % numOfIoThreads + 1; vmDevice.getSpecParams().put(VdsProperties.pinToIoThread, pinToIoThread); } drive.put(VdsProperties.Shareable, (vmDevice.getSnapshotId() != null) ? VdsProperties.Transient : String.valueOf(disk.isShareable())); drive.put(VdsProperties.Optional, Boolean.FALSE.toString()); drive.put(VdsProperties.ReadOnly, String.valueOf(vmDevice.getReadOnly())); drive.put(VdsProperties.DeviceId, vmDevice.getId().getDeviceId().toString()); switch (disk.getDiskStorageType()) { case IMAGE: DiskImage diskImage = (DiskImage) disk; drive.put(VdsProperties.Device, VmDeviceType.DISK.getName()); drive.put(VdsProperties.Format, diskImage.getVolumeFormat().toString().toLowerCase()); drive.put(VdsProperties.DomainId, diskImage.getStorageIds().get(0).toString()); drive.put(VdsProperties.PoolId, diskImage.getStoragePoolId().toString()); drive.put(VdsProperties.VolumeId, diskImage.getImageId().toString()); drive.put(VdsProperties.ImageId, diskImage.getId().toString()); drive.put(VdsProperties.PropagateErrors, disk.getPropagateErrors().toString().toLowerCase()); vmInfoBuildUtils.handleIoTune(vmDevice, vmInfoBuildUtils.loadStorageQos(diskImage)); if (vmDevice.getSpecParams() != null) { drive.put(VdsProperties.SpecParams, vmDevice.getSpecParams()); } break; case LUN: LunDisk lunDisk = (LunDisk) disk; // If SCSI pass-through is enabled (VirtIO-SCSI/DirectLUN disk and SGIO is defined), // set device type as 'lun' (instead of 'disk') and set the specified SGIO boolean isVirtioScsi = getParameters().getDiskInterface() == DiskInterface.VirtIO_SCSI; boolean isScsiPassthrough = getParameters().getDisk().isScsiPassthrough(); if (isVirtioScsi) { if (isScsiPassthrough) { drive.put(VdsProperties.Device, VmDeviceType.LUN.getName()); drive.put(VdsProperties.Sgio, getParameters().getDisk().getSgio().toString().toLowerCase()); } else { drive.put(VdsProperties.Device, VmDeviceType.DISK.getName()); } } else { drive.put(VdsProperties.Device, VmDeviceType.DISK.getName()); } drive.put(VdsProperties.Guid, lunDisk.getLun().getLUNId()); drive.put(VdsProperties.Format, VolumeFormat.RAW.toString().toLowerCase()); drive.put(VdsProperties.PropagateErrors, PropagateErrors.Off.toString() .toLowerCase()); break; case CINDER: CinderDisk cinderDisk = (CinderDisk) disk; vmInfoBuildUtils.buildCinderDisk(cinderDisk, drive); drive.put(VdsProperties.Device, VmDeviceType.DISK.getName()); break; } return drive; } }