diff --git a/0009-add-hotplug-or-unplug-hostdev-and-migrate.patch b/0009-add-hotplug-or-unplug-hostdev-and-migrate.patch new file mode 100644 index 0000000000000000000000000000000000000000..70011ad89c35702e8fd82b78ac475f52473ac966 --- /dev/null +++ b/0009-add-hotplug-or-unplug-hostdev-and-migrate.patch @@ -0,0 +1,692 @@ +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdev/AbstractVmHostDevicesCommand.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdev/AbstractVmHostDevicesCommand.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdev/AbstractVmHostDevicesCommand.java 2020-11-19 01:15:47.000000000 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdev/AbstractVmHostDevicesCommand.java 2022-12-31 10:22:12.568769660 +0800 +@@ -55,7 +55,7 @@ + } + + // hot(un)plug not supported (yet) +- if (getVm().getStatus() != VMStatus.Down) { ++ if (getVm().getStatus() == VMStatus.PoweringUp) { + return failVmStatusIllegal(); + } + +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdev/AddVmHostDevicesCommand.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdev/AddVmHostDevicesCommand.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdev/AddVmHostDevicesCommand.java 2020-11-19 01:15:47.000000000 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdev/AddVmHostDevicesCommand.java 2022-12-31 10:22:12.564769660 +0800 +@@ -14,12 +14,18 @@ + import org.ovirt.engine.core.common.businessentities.HostDevice; + import org.ovirt.engine.core.common.businessentities.VmDevice; + import org.ovirt.engine.core.common.businessentities.VmHostDevice; ++import org.ovirt.engine.core.common.businessentities.network.VmNic; + import org.ovirt.engine.core.common.errors.EngineMessage; ++import org.ovirt.engine.core.common.vdscommands.VDSCommandType; ++import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; ++import org.ovirt.engine.core.common.vdscommands.VmNicDeviceVDSParameters; + import org.ovirt.engine.core.dao.HostDeviceDao; + import org.ovirt.engine.core.dao.VmDeviceDao; ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; + + public class AddVmHostDevicesCommand extends AbstractVmHostDevicesCommand { +- ++ private static final Logger log = LoggerFactory.getLogger(AddVmHostDevicesCommand.class); + @Inject + private VmDeviceDao vmDeviceDao; + @Inject +@@ -50,8 +56,9 @@ + List devicesToUpdate = new ArrayList<>(); + + for (HostDevice hostDevice : affectedHostDevices) { ++ VmHostDevice device; + if (!existingDevices.containsKey(hostDevice.getDeviceName())) { +- VmHostDevice device = new VmHostDevice(getVmId(), hostDevice); ++ device = new VmHostDevice(getVmId(), hostDevice); + + // if the device was not explicitly intended by the user (only added due to the IOMMU group + // we mark it as as placeholder +@@ -60,7 +67,7 @@ + + devicesToAdd.add(device); + } else { +- VmHostDevice device = new VmHostDevice(existingDevices.get(hostDevice.getDeviceName())); ++ device = new VmHostDevice(existingDevices.get(hostDevice.getDeviceName())); + // if the device was previously only added as placeholder we update the flag + // as it is now explicitly requested by the user + if (getPrimaryDeviceNames().contains(device.getDevice()) && device.isIommuPlaceholder()) { +@@ -69,6 +76,17 @@ + devicesToUpdate.add(device); + } + } ++ if(getVm().getStatus().isUpOrPaused() ++ && hostDeviceDao.getHostDeviceByHostIdAndDeviceName(getVdsIdRef(), device.getDevice()) != null) { ++ VmNic nic = new VmNic(); ++ nic.setPciAddress(device.getDevice()); ++ VDSReturnValue vdsReturnValue = runVdsCommand(VDSCommandType.HotPlugNic, ++ new VmNicDeviceVDSParameters(getVdsIdRef(), ++ getVm(), ++ nic, ++ device)); ++ } ++ hostDeviceDao.setVmIdOnHostDevice(hostDevice.getId(), getVmId()); + } + + vmDeviceDao.saveAllInBatch(devicesToAdd); +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdev/RemoveVmHostDevicesCommand.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdev/RemoveVmHostDevicesCommand.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdev/RemoveVmHostDevicesCommand.java 2020-11-19 01:15:47.000000000 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/hostdev/RemoveVmHostDevicesCommand.java 2022-12-31 10:22:12.564769660 +0800 +@@ -15,7 +15,12 @@ + import org.ovirt.engine.core.common.businessentities.HostDevice; + import org.ovirt.engine.core.common.businessentities.VmDevice; + import org.ovirt.engine.core.common.businessentities.VmHostDevice; ++import org.ovirt.engine.core.common.businessentities.network.VmNic; + import org.ovirt.engine.core.common.errors.EngineMessage; ++import org.ovirt.engine.core.common.vdscommands.VDSCommandType; ++import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; ++import org.ovirt.engine.core.common.vdscommands.VmNicDeviceVDSParameters; ++import org.ovirt.engine.core.dao.HostDeviceDao; + import org.ovirt.engine.core.dao.VmDeviceDao; + + public class RemoveVmHostDevicesCommand extends AbstractVmHostDevicesCommand { +@@ -23,6 +28,9 @@ + @Inject + private VmDeviceDao vmDeviceDao; + ++ @Inject ++ private HostDeviceDao hostDeviceDao; ++ + public RemoveVmHostDevicesCommand(VmHostDevicesParameters parameters, CommandContext cmdContext) { + super(parameters, cmdContext); + } +@@ -49,6 +57,19 @@ + // first just set the flag that this device is not required + device.setIommuPlaceholder(true); + } ++ if(getVm().getStatus().isUpOrPaused()) { ++ VmNic nic = new VmNic(); ++ nic.setPciAddress(device.getDevice()); ++ VDSReturnValue vdsReturnValue = runVdsCommand(VDSCommandType.HotUnplugNic, ++ new VmNicDeviceVDSParameters(getVdsIdRef(), ++ getVm(), ++ nic, ++ device)); ++ if (!vdsReturnValue.getSucceeded()) { ++ log.error("Failed to hot unplug host device!!!"); ++ } ++ } ++ hostDeviceDao.setVmIdOnHostDevice(hostDevice.getId(), null); + } + } + +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MigrateVmCommand.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MigrateVmCommand.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MigrateVmCommand.java 2020-11-19 01:15:47.000000000 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MigrateVmCommand.java 2022-12-31 10:22:12.020769660 +0800 +@@ -42,6 +42,7 @@ + import org.ovirt.engine.core.common.action.LockProperties.Scope; + import org.ovirt.engine.core.common.action.MigrateVmParameters; + import org.ovirt.engine.core.common.action.PlugAction; ++import org.ovirt.engine.core.common.action.VmHostDevicesParameters; + import org.ovirt.engine.core.common.businessentities.MigrationMethod; + import org.ovirt.engine.core.common.businessentities.OriginType; + import org.ovirt.engine.core.common.businessentities.VDS; +@@ -74,6 +75,7 @@ + import org.ovirt.engine.core.compat.Version; + import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector; + import org.ovirt.engine.core.dao.DiskDao; ++import org.ovirt.engine.core.dao.HostDeviceDao; + import org.ovirt.engine.core.dao.VdsDao; + import org.ovirt.engine.core.dao.VmDynamicDao; + import org.ovirt.engine.core.dao.network.HostNetworkQosDao; +@@ -100,6 +102,8 @@ + @Inject + private VmDynamicDao vmDynamicDao; + @Inject ++ private HostDeviceDao hostDeviceDao; ++ @Inject + private NetworkDao networkDao; + @Inject + private VdsDao vdsDao; +@@ -540,6 +544,17 @@ + try { + queryDowntime(); + vmDynamicDao.clearMigratingToVds(getVmId()); ++ hostDeviceDao.getHostDevicesByHostId(getVdsId()) ++ .stream() ++ .forEach(dev -> { ++ if (dev.getVmId() != null && dev.getVmId().toString().equals(getVmId().toString())){ ++ ActionReturnValue retVal = runInternalAction(ActionType.RemoveVmHostDevices, ++ new VmHostDevicesParameters(dev.getVmId(), dev.getDeviceName())); ++ if (retVal == null || !retVal.getSucceeded()) { ++ throw new EngineException(EngineError.destroyErr); ++ } ++ } ++ }); + updateVmAfterMigrationToDifferentCluster(); + plugPassthroughNics(); + initParametersForExternalNetworks(destinationVds, true); +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/SchedulingManager.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/SchedulingManager.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/SchedulingManager.java 2020-11-19 01:15:47.000000000 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/SchedulingManager.java 2022-12-31 10:22:13.096769660 +0800 +@@ -954,7 +954,9 @@ + break; + } + List currentHostList = new ArrayList<>(hostList); +- hostList = filterPolicyUnit.filter(context, hostList, vmGroup, result.getDetails()); ++ if (!filterPolicyUnit.getPolicyUnit().getName().equals("HostDevice")){ ++ hostList = filterPolicyUnit.filter(context, hostList, vmGroup, result.getDetails()); ++ } + logFilterActions(currentHostList, + toIdSet(hostList), + EngineMessage.VAR__FILTERTYPE__INTERNAL, +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/network/VmNic.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/network/VmNic.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/network/VmNic.java 2020-11-19 01:15:48.000000000 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/network/VmNic.java 2022-12-31 10:22:14.904769660 +0800 +@@ -29,6 +29,7 @@ + + private Guid vmId; + private Guid vnicProfileId; ++ private String pciAddress; + + /** + * Link State of the Nic.
+@@ -50,6 +51,14 @@ + return vmId; + } + ++ public void setPciAddress(String pciAddress) { ++ this.pciAddress = pciAddress; ++ } ++ ++ public String getPciAddress() { ++ return pciAddress; ++ } ++ + @Override + public Object getQueryableId() { + return getVmId(); +@@ -114,6 +123,7 @@ + .append("macAddress", getMacAddress()) + .append("linked", isLinked()) + .append("vmId", getVmId()) ++ .append("pciAddress", getPciAddress()) + .build(); + } + +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/LibvirtVmXmlBuilder.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/LibvirtVmXmlBuilder.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/LibvirtVmXmlBuilder.java 2022-12-31 09:29:03.244769660 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/LibvirtVmXmlBuilder.java 2022-12-31 10:22:10.140769660 +0800 +@@ -197,6 +197,16 @@ + init(vm, vmInfoBuildUtils, hostId); + } + ++ public LibvirtVmXmlBuilder( ++ VM vm, ++ Guid hostId, ++ VmDevice device, ++ VmInfoBuildUtils vmInfoBuildUtils ++ ) { ++ this.device = device; ++ init(vm, vmInfoBuildUtils, hostId); ++ } ++ + /** + * This constructor is meant for building a partial XML for hot-plugging disk. + */ +@@ -318,6 +328,27 @@ + return writer.getStringXML(); + } + ++ public String buildHotplugHostdev() { ++ List> hostDevDisks = new ArrayList<>(); ++ HostDevice hostDevice = hostDevicesSupplier.get().get(device.getDevice()); ++ writer.writeStartDocument(false); ++ writer.writeStartElement("hotplug"); ++ ++ writer.writeStartElement("devices"); ++ writeHostDevice(device, hostDevice, hostDevDisks); ++ writer.writeEndElement(); ++ ++ writer.writeStartElement("metadata"); ++ writer.setPrefix(OVIRT_VM_PREFIX, OVIRT_VM_URI); ++ writer.writeNamespace(OVIRT_VM_PREFIX, OVIRT_VM_URI); ++ writer.writeStartElement(OVIRT_VM_URI, "vm"); ++ // writeHostdevMetadata(); ++ writer.writeEndElement(); ++ writer.writeEndElement(); ++ ++ return writer.getStringXML(); ++ } ++ + public String buildHotplugDisk() { + writer.writeStartDocument(false); + writer.writeStartElement("hotplug"); +@@ -1771,7 +1817,7 @@ + } + + writer.writeStartElement("hostdev"); +- writer.writeAttributeString("managed", "no"); ++ writer.writeAttributeString("managed", "yes"); + writer.writeAttributeString("mode", "subsystem"); + writer.writeAttributeString("type", "pci"); + +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/VmInfoBuildUtils.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/VmInfoBuildUtils.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/VmInfoBuildUtils.java 2022-12-31 09:28:51.516769660 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/builder/vminfo/VmInfoBuildUtils.java 2022-12-31 10:22:10.136769660 +0800 +@@ -19,6 +19,7 @@ + import java.util.Optional; + import java.util.Set; + import java.util.TimeZone; ++import java.util.TreeSet; + import java.util.regex.Matcher; + import java.util.regex.Pattern; + import java.util.stream.Collectors; +@@ -1390,6 +1391,21 @@ + return vdsStatisticsDao.get(hostId); + } + ++ public Map getHostDevices(Guid hostId, Boolean isAll) { ++ if(isAll){ ++ return hostDeviceDao.getAll() ++ .stream() ++ .collect(Collectors.collectingAndThen( ++ Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(HostDevice::getDeviceName))), ArrayList::new)) ++ .stream() ++ .collect(Collectors.toMap(HostDevice::getDeviceName, device -> device)); ++ }else { ++ return hostDeviceDao.getHostDevicesByHostId(hostId) ++ .stream() ++ .collect(Collectors.toMap(HostDevice::getDeviceName, device -> device)); ++ } ++ } ++ + public Map getHostDevices(Guid hostId) { + return hostDeviceDao.getHostDevicesByHostId(hostId) + .stream() +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/libvirt/Hotunplug.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/libvirt/Hotunplug.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/libvirt/Hotunplug.java 2020-11-19 01:15:49.000000000 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/libvirt/Hotunplug.java 2022-12-31 10:22:09.828769660 +0800 +@@ -35,6 +35,7 @@ + public static class Devices { + private Device nic; + private Device disk; ++ private Device hostdev; + + public Device getInterface() { + return nic; +@@ -46,6 +47,16 @@ + return this; + } + ++ public Device getHostdev() { ++ return hostdev; ++ } ++ ++ @XmlElement ++ public Devices setHostdev(Device hostdev) { ++ this.hostdev = hostdev; ++ return this; ++ } ++ + public Device getDisk() { + return disk; + } +@@ -58,7 +69,32 @@ + } + + public static class Device { ++ private String type; + private Alias alias; ++ private Source source; ++ ++ public Device(VmDevice device, boolean is_hostdev) { ++ /** ++ * For VMs that were started in lower compatibility versions and that don't support user-aliases, we should ++ * get the reported alias from the database, otherwise we have no way to tell what is the device alias since ++ * it is generated by libvirt. ++ * For newly created VMs, it may happen that the alias is not set in the database yet and in that case a ++ * user alias needs to be set here and passed to libvirt with the hot unplug request. It will later be updated ++ * in the database by the vm device monitoring. ++ */ ++ ++ if(is_hostdev){ ++ this.type = "pci"; //Only pci host devices are supported to hot plug or unplug!! ++ int len = device.getDevice().split("_").length; ++ Address address = new Address("0x" + device.getDevice().split("_")[len-4], "0x" + device.getDevice().split("_")[len-3] ++ , "0x" + device.getDevice().split("_")[len-2], "0x" + device.getDevice().split("_")[len-1]); ++ this.source = new Source(address); ++ } ++ ++ String alias = StringUtils.isNotEmpty(device.getAlias()) ? device.getAlias() : ++ LibvirtVmXmlBuilder.generateUserAliasForDevice(device); ++ this.alias = new Alias(alias); ++ } + + public Device(VmDevice device) { + /** +@@ -69,11 +105,21 @@ + * user alias needs to be set here and passed to libvirt with the hot unplug request. It will later be updated + * in the database by the vm device monitoring. + */ ++ + String alias = StringUtils.isNotEmpty(device.getAlias()) ? device.getAlias() : + LibvirtVmXmlBuilder.generateUserAliasForDevice(device); + this.alias = new Alias(alias); + } + ++ public String getType() { ++ return type; ++ } ++ ++ @XmlAttribute ++ public void setType(String type) { ++ this.type = type; ++ } ++ + public Alias getAlias() { + return alias; + } +@@ -82,6 +128,15 @@ + public void setAlias(Alias alias) { + this.alias = alias; + } ++ ++ public Source getSource() { ++ return source; ++ } ++ ++ @XmlElement ++ public void setSource(Source source) { ++ this.source = source; ++ } + } + + private static class Alias { +@@ -100,4 +155,71 @@ + this.name = name; + } + } ++ ++ private static class Source { ++ private Address address; ++ ++ public Source(Address address) { ++ this.address = address; ++ } ++ ++ public Address getAddress() { ++ return address; ++ } ++ ++ @XmlElement ++ public void setAddress(Address address) { ++ this.address = address; ++ } ++ } ++ ++ private static class Address { ++ private String domain; ++ private String bus; ++ private String slot; ++ private String function; ++ ++ public Address(String domain, String bus, String slot, String function) { ++ this.domain = domain; ++ this.bus = bus; ++ this.slot = slot; ++ this.function = function; ++ } ++ ++ public String getDomain() { ++ return domain; ++ } ++ ++ @XmlAttribute ++ public void setDomain(String domain) { ++ this.domain = domain; ++ } ++ ++ public String getBus() { ++ return bus; ++ } ++ ++ @XmlAttribute ++ public void setBus(String bus) { ++ this.bus = bus; ++ } ++ ++ public String getSlot() { ++ return slot; ++ } ++ ++ @XmlAttribute ++ public void setSlot(String slot) { ++ this.slot = slot; ++ } ++ ++ public String getFunction() { ++ return function; ++ } ++ ++ @XmlAttribute ++ public void setFunction(String function) { ++ this.function = function; ++ } ++ } + } +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HotPlugNicVDSCommand.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HotPlugNicVDSCommand.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HotPlugNicVDSCommand.java 2020-11-19 01:15:49.000000000 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HotPlugNicVDSCommand.java 2022-12-31 10:22:09.604769660 +0800 +@@ -24,39 +24,50 @@ + + @Override + protected void executeVdsBrokerCommand() { + result = getBroker().hotPlugNic(createParametersStruct()); + proceedProxyReturnValue(); + setReturnValue(result); +- } ++ } + +- @Override +- protected Status getReturnStatus() { +- return result.getStatus(); +- } ++ @Override ++ protected Status getReturnStatus() { ++ return result.getStatus(); ++ } + +- @Override +- protected Object getReturnValueFromBroker() { +- return result; +- } ++ @Override ++ protected Object getReturnValueFromBroker() { ++ return result; ++ } + +- @Override +- protected String generateDomainXml() { +- VmNic nic = getParameters().getNic(); +- VmDevice vmDevice = getParameters().getVmDevice(); +- LibvirtVmXmlBuilder builder = new LibvirtVmXmlBuilder( +- getParameters().getVm(), +- getVds().getId(), +- nic, +- vmDevice, +- vmInfoBuildUtils, +- nic.isPassthrough() ? +- Collections.singletonMap(nic.getId(), vmDevice.getHostDevice()) +- : Collections.emptyMap()); +- String libvirtXml = builder.buildHotplugNic(); +- String prettyLibvirtXml = XmlUtils.prettify(libvirtXml); +- if (prettyLibvirtXml != null) { +- log.info("NIC hot-plug: {}", prettyLibvirtXml); +- } +- return libvirtXml; +- } ++ @Override ++ protected String generateDomainXml() { ++ String libvirtXml = null; ++ VmNic nic = getParameters().getNic(); ++ VmDevice vmDevice = getParameters().getVmDevice(); ++ if(nic.getPciAddress() == null){ ++ LibvirtVmXmlBuilder builder = new LibvirtVmXmlBuilder( ++ getParameters().getVm(), ++ getVds().getId(), ++ nic, ++ vmDevice, ++ vmInfoBuildUtils, ++ nic.isPassthrough() ? ++ Collections.singletonMap(nic.getId(), vmDevice.getHostDevice()) ++ : Collections.emptyMap()); ++ libvirtXml = builder.buildHotplugNic(); ++ }else{ ++ LibvirtVmXmlBuilder builder = new LibvirtVmXmlBuilder( ++ getParameters().getVm(), ++ getVds().getId(), ++ vmDevice, ++ vmInfoBuildUtils ++ ); ++ libvirtXml = builder.buildHotplugHostdev(); ++ } ++ String prettyLibvirtXml = XmlUtils.prettify(libvirtXml); ++ if (prettyLibvirtXml != null) { ++ log.info("NIC hot-plug: {}", prettyLibvirtXml); ++ } ++ return libvirtXml; ++ } + } +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HotUnplugNicVDSCommand.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HotUnplugNicVDSCommand.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HotUnplugNicVDSCommand.java 2020-11-19 01:15:49.000000000 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/HotUnplugNicVDSCommand.java 2022-12-31 10:22:09.360769660 +0800 +@@ -7,6 +7,7 @@ + import javax.xml.bind.Marshaller; + + import org.ovirt.engine.core.common.businessentities.VmDevice; ++import org.ovirt.engine.core.common.businessentities.network.VmNic; + import org.ovirt.engine.core.common.vdscommands.VmNicDeviceVDSParameters; + import org.ovirt.engine.core.utils.XmlUtils; + import org.ovirt.engine.core.vdsbroker.libvirt.Hotunplug; +@@ -29,7 +30,18 @@ + protected String generateDomainXml() throws JAXBException { + Marshaller jaxbMarshaller = JAXBContext.newInstance(Hotunplug.class).createMarshaller(); + VmDevice device = getParameters().getVmDevice(); +- Hotunplug hotunplug = new Hotunplug().setDevices(new Devices().setInterface(new Device(device))); ++ VmNic nic = getParameters().getNic(); ++ Hotunplug hotunplug = null; ++ if(nic.getPciAddress() != null){ ++ if(device.getDevice().matches("[a-zA-Z0-9-_]*(pci_)+\\w*")){ ++ hotunplug = new Hotunplug().setDevices(new Devices().setHostdev(new Device(device, true))); ++ }else{ ++ log.error("Only pci host devices are supported to hot plug or unplug!!"); ++ return null; ++ } ++ }else{ ++ hotunplug = new Hotunplug().setDevices(new Devices().setInterface(new Device(device))); ++ } + StringWriter sw = new StringWriter(); + jaxbMarshaller.marshal(hotunplug, sw); + String libvirtXml = sw.toString(); +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/MigrateBrokerVDSCommand.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/MigrateBrokerVDSCommand.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/MigrateBrokerVDSCommand.java 2020-11-19 01:15:49.000000000 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/MigrateBrokerVDSCommand.java 2022-12-31 10:22:09.476769660 +0800 +@@ -1,10 +1,15 @@ + package org.ovirt.engine.core.vdsbroker.vdsbroker; + ++import java.util.ArrayList; + 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.vdscommands.MigrateVDSCommandParameters; ++import org.ovirt.engine.core.dao.HostDeviceDao; + + public class MigrateBrokerVDSCommand

extends VdsBrokerCommand

{ + +@@ -12,6 +17,9 @@ + super(parameters); + } + ++ @Inject ++ private HostDeviceDao hostDeviceDao; ++ + @Override + protected void executeVdsBrokerCommand() { + status = getBroker().migrate(createMigrationInfo()); +@@ -20,6 +28,7 @@ + + private Map createMigrationInfo() { + Map migrationInfo = new HashMap<>(); ++ List hostDevices = new ArrayList<>(); + + P parameters = getParameters(); + migrationInfo.put(VdsProperties.vm_guid, parameters.getVmId().toString()); +@@ -28,6 +37,22 @@ + migrationInfo.put(VdsProperties.method, parameters.getMigrationMethod().name().toLowerCase()); + migrationInfo.put(VdsProperties.TUNNELED, Boolean.toString(parameters.isTunnelMigration())); + migrationInfo.put("abortOnError", Boolean.TRUE.toString()); ++ hostDeviceDao.getHostDevicesByHostId(parameters.getDstVdsId()) ++ .stream() ++ .forEach(dev -> { ++ if (dev.getVmId() != null && dev.getVmId().toString().equals(parameters.getVmId().toString())){ ++ if (dev.isPci()) { ++ hostDevices.add(dev.getAddress().get("domain")); ++ hostDevices.add(dev.getAddress().get("bus")); ++ hostDevices.add(dev.getAddress().get("slot")); ++ hostDevices.add(dev.getAddress().get("function")); ++ } ++ } ++ }); ++ if (!hostDevices.isEmpty()){ ++ hostDevices.add(" "); ++ migrationInfo.put(VdsProperties.Hostdev_Address, hostDevices.toString()); ++ } + + if (StringUtils.isNotBlank(parameters.getDstQemu())) { + migrationInfo.put(VdsProperties.DST_QEMU, parameters.getDstQemu()); +diff -Nur ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java +--- ovirt-engine-4.4.4.1/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java 2020-11-19 01:15:49.000000000 +0800 ++++ ovirt-engine-4.4.4.1-bk/backend/manager/modules/vdsbroker/src/main/java/org/ovirt/engine/core/vdsbroker/vdsbroker/VdsProperties.java 2022-12-31 10:22:09.496769660 +0800 +@@ -419,6 +419,7 @@ + public static final String domains = "storageDomains"; + public static final String hooks = "hooks"; + public static final String TUNNELED = "tunneled"; ++ public static final String Hostdev_Address = "hostdevaddress"; + public static final String DST_QEMU = "dstqemu"; + public static final String MIGRATION_DOWNTIME = "downtime"; + public static final String AUTO_CONVERGE = "autoConverge"; +diff -Nur ovirt-engine-4.4.4.1/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/hostdev/AddVmHostDevicesModel.java ovirt-engine-4.4.4.1-bk/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/hostdev/AddVmHostDevicesModel.java +--- ovirt-engine-4.4.4.1/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/hostdev/AddVmHostDevicesModel.java 2020-11-19 01:15:50.000000000 +0800 ++++ ovirt-engine-4.4.4.1-bk/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/hostdev/AddVmHostDevicesModel.java 2022-12-31 10:23:02.456769660 +0800 +@@ -6,10 +6,14 @@ + import java.util.Set; + import java.util.stream.Collectors; + ++import org.ovirt.engine.core.common.action.ActionType; ++import org.ovirt.engine.core.common.action.VdsActionParameters; + import org.ovirt.engine.core.common.businessentities.HostDeviceView; ++import org.ovirt.engine.core.common.businessentities.VDS; + import org.ovirt.engine.core.common.businessentities.VM; + import org.ovirt.engine.core.common.businessentities.VmHostDevice; + import org.ovirt.engine.core.common.config.ConfigValues; ++import org.ovirt.engine.ui.frontend.Frontend; + import org.ovirt.engine.ui.uicommonweb.Linq; + import org.ovirt.engine.ui.uicommonweb.UICommand; + import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider; +@@ -54,7 +58,13 @@ + @Override + public void init(VM vm) { + super.init(vm); +- ++ for(VDS host : getPinnedHost().getItemsAsList()){ ++ Frontend.getInstance().runAction(ActionType.RefreshHost, new VdsActionParameters(host.getId()), ++ result -> { ++ getWindow().stopProgress(); ++ setWindow(null); ++ }); ++ } + initCapabilities(); + fetchExistingDevices(); + }