From fc2251a03530ff5a6be659c081873ae0ad7dfc27 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 1 Feb 2023 13:56:00 +0100 Subject: [libvirt] Add method to add GVT-g override data --- .../java/org/openslx/libvirt/domain/Domain.java | 59 +++++++++++++++++++++- src/main/java/org/openslx/util/XmlHelper.java | 40 +++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/openslx/libvirt/domain/Domain.java b/src/main/java/org/openslx/libvirt/domain/Domain.java index ca10261..be49e1e 100644 --- a/src/main/java/org/openslx/libvirt/domain/Domain.java +++ b/src/main/java/org/openslx/libvirt/domain/Domain.java @@ -10,7 +10,6 @@ import java.util.stream.Collectors; import javax.xml.XMLConstants; -import org.openslx.libvirt.domain.device.Device; import org.openslx.libvirt.domain.device.Controller; import org.openslx.libvirt.domain.device.ControllerFloppy; import org.openslx.libvirt.domain.device.ControllerIde; @@ -18,6 +17,7 @@ import org.openslx.libvirt.domain.device.ControllerPci; import org.openslx.libvirt.domain.device.ControllerSata; import org.openslx.libvirt.domain.device.ControllerScsi; import org.openslx.libvirt.domain.device.ControllerUsb; +import org.openslx.libvirt.domain.device.Device; import org.openslx.libvirt.domain.device.Disk; import org.openslx.libvirt.domain.device.DiskCdrom; import org.openslx.libvirt.domain.device.DiskFloppy; @@ -44,10 +44,13 @@ import org.openslx.libvirt.xml.LibvirtXmlNode; import org.openslx.libvirt.xml.LibvirtXmlResources; import org.openslx.libvirt.xml.LibvirtXmlSerializationException; import org.openslx.libvirt.xml.LibvirtXmlValidationException; +import org.openslx.util.XmlHelper; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSSerializer; import org.xml.sax.InputSource; /** @@ -1544,6 +1547,60 @@ public class Domain extends LibvirtXmlDocument qemuCmdlnElement.appendChild( qemuCmdlnArgElement ); } + public void addGvtg( String optionalRomfile ) + { + final Element rootElement = Element.class.cast( this.getRootXmlNode().getXmlBaseNode() ); + final Document xmlDocument = this.getRootXmlNode().getXmlDocument(); + final Element qemuOverrideElement; + + final NodeList qemuCmdlnNodes = rootElement.getElementsByTagNameNS( XMLNS_QEMU_NS_URI, "override" ); + if ( qemuCmdlnNodes.getLength() < 1 ) { + // add missing namespace attribute + rootElement.setAttributeNS( XMLConstants.XMLNS_ATTRIBUTE_NS_URI, + XMLConstants.XMLNS_ATTRIBUTE + ":" + XMLNS_QEMU_NS_PREFIX, XMLNS_QEMU_NS_URI ); + // add missing element + qemuOverrideElement = xmlDocument.createElementNS( XMLNS_QEMU_NS_URI, "override" ); + qemuOverrideElement.setPrefix( XMLNS_QEMU_NS_PREFIX ); + rootElement.appendChild( qemuOverrideElement ); + } else { + // use available element + final Node qemuOverrideNode = qemuCmdlnNodes.item( 0 ); + assert ( qemuOverrideNode.getNodeType() == Node.ELEMENT_NODE ); + qemuOverrideElement = Element.class.cast( qemuOverrideNode ); + } + + // Get device subnode + Element qemuDeviceElement = XmlHelper.getOrCreateElement( xmlDocument, qemuOverrideElement, + XMLNS_QEMU_NS_URI, XMLNS_QEMU_NS_PREFIX, "device", "alias", "hostdev0" ); + // + DOMImplementationLS domImplLS = (DOMImplementationLS)xmlDocument.getImplementation(); + LSSerializer serializer = domImplLS.createLSSerializer(); + String str = serializer.writeToString( qemuOverrideElement ); + // + Element qemuFrontendElement = XmlHelper.getOrCreateElement( xmlDocument, qemuDeviceElement, + XMLNS_QEMU_NS_URI, XMLNS_QEMU_NS_PREFIX, "frontend", null, null ); + // Properties + Element prop; + prop = XmlHelper.getOrCreateElement( xmlDocument, qemuFrontendElement, + XMLNS_QEMU_NS_URI, XMLNS_QEMU_NS_PREFIX, "property", "name", "x-igd-opregion" ); + prop.setAttribute( "type", "bool" ); + prop.setAttribute( "value", "true" ); + prop = XmlHelper.getOrCreateElement( xmlDocument, qemuFrontendElement, + XMLNS_QEMU_NS_URI, XMLNS_QEMU_NS_PREFIX, "property", "name", "driver" ); + prop.setAttribute( "type", "string" ); + prop.setAttribute( "value", "vfio-pci-nohotplug" ); + prop = XmlHelper.getOrCreateElement( xmlDocument, qemuFrontendElement, + XMLNS_QEMU_NS_URI, XMLNS_QEMU_NS_PREFIX, "property", "name", "ramfb" ); + prop.setAttribute( "type", "bool" ); + prop.setAttribute( "value", "true" ); + if ( optionalRomfile != null ) { + prop = XmlHelper.getOrCreateElement( xmlDocument, qemuFrontendElement, + XMLNS_QEMU_NS_URI, XMLNS_QEMU_NS_PREFIX, "property", "name", "romfile" ); + prop.setAttribute( "type", "string" ); + prop.setAttribute( "value", optionalRomfile ); + } + } + /** * Removes boot oder entries in the Libvirt domain XML document. */ diff --git a/src/main/java/org/openslx/util/XmlHelper.java b/src/main/java/org/openslx/util/XmlHelper.java index e3607d9..f9366e0 100644 --- a/src/main/java/org/openslx/util/XmlHelper.java +++ b/src/main/java/org/openslx/util/XmlHelper.java @@ -22,7 +22,9 @@ import javax.xml.xpath.XPathFactory; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.w3c.dom.Attr; import org.w3c.dom.Document; +import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; @@ -157,4 +159,42 @@ public class XmlHelper return null; } } + + public static Element getOrCreateElement( Document doc, Element parent, String nsUri, String nsName, + String name, String attrName, String attrValue ) + { + final NodeList childList = parent.getElementsByTagNameNS( nsUri, name ); + Element element = null; + outer: for ( int i = 0; i < childList.getLength(); ++i ) { + Node n = childList.item( i ); + if ( n.getNodeType() != Node.ELEMENT_NODE ) + continue; + if ( attrName != null && attrValue != null ) { + for ( int ai = 0; ai < n.getAttributes().getLength(); ++ai ) { + Node attr = n.getAttributes().item( ai ); + if ( attr.getNodeType() != Attr.ELEMENT_NODE ) + continue; + Attr a = (Attr)attr; + if ( !attrName.equals( a.getLocalName() ) || !attrValue.equals( a.getValue() ) ) + continue; + element = (Element)n; + break outer; + } + } else { + element = (Element)n; + break; + } + } + if ( element == null ) { + // Need a new + element = doc.createElementNS( nsUri, name ); + element.setPrefix( nsName ); + if ( attrName != null && attrValue != null ) { + element.setAttribute( attrName, attrValue ); + } + parent.appendChild( element ); + } + return element; + } + } -- cgit v1.2.3-55-g7522