summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Bentele2021-08-11 16:00:36 +0200
committerManuel Bentele2021-08-11 16:00:36 +0200
commita5b5fa1dd56279c63d572bcf6037cb59527f5e4b (patch)
tree715bf10ed874ee7fbd7f47aad46f39ff2a8ae2b9
parentImplement blocking network.target and network-online.target (diff)
downloadmltk-a5b5fa1dd56279c63d572bcf6037cb59527f5e4b.tar.gz
mltk-a5b5fa1dd56279c63d572bcf6037cb59527f5e4b.tar.xz
mltk-a5b5fa1dd56279c63d572bcf6037cb59527f5e4b.zip
[qemu] Add transformation of Libvirt graphics type to local SPICE graphics
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java2
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGraphics.java110
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGraphicsTest.java96
-rw-r--r--core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestUtils.java10
4 files changed, 215 insertions, 3 deletions
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
index c9d47f5e..5d6bb136 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/App.java
@@ -26,6 +26,7 @@ import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuS
import org.openslx.runvirt.plugin.qemu.configuration.TransformationGenericUuid;
import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuArchitecture;
import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuGpuPassthroughNvidia;
+import org.openslx.runvirt.plugin.qemu.configuration.TransformationSpecificQemuGraphics;
import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu;
import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu.QemuSessionType;
import org.openslx.runvirt.viewer.Viewer;
@@ -141,6 +142,7 @@ public class App
final LibvirtHypervisorQemu hypervisorQemu = LibvirtHypervisorQemu.class.cast( hypervisor );
transformationManager.register( new TransformationSpecificQemuArchitecture( hypervisorQemu ), true );
+ transformationManager.register( new TransformationSpecificQemuGraphics( hypervisorQemu ), true );
transformationManager.register( new TransformationSpecificQemuSerialDevices( hypervisorQemu ), true );
transformationManager.register( new TransformationSpecificQemuGpuPassthroughNvidia( hypervisorQemu ), false );
}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGraphics.java b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGraphics.java
new file mode 100644
index 00000000..29727bfa
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/main/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGraphics.java
@@ -0,0 +1,110 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Graphics.ListenType;
+import org.openslx.libvirt.domain.device.GraphicsSpice;
+import org.openslx.libvirt.domain.device.GraphicsSpice.ImageCompression;
+import org.openslx.libvirt.domain.device.GraphicsSpice.StreamingMode;
+import org.openslx.libvirt.domain.device.GraphicsVnc;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.runvirt.plugin.qemu.virtualization.LibvirtHypervisorQemu;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+import org.openslx.virtualization.configuration.transformation.TransformationSpecific;
+
+/**
+ * Specific graphics transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class TransformationSpecificQemuGraphics
+ extends TransformationSpecific<Domain, CommandLineArgs, LibvirtHypervisorQemu>
+{
+ /**
+ * Name of the configuration transformation.
+ */
+ private static final String NAME = "QEMU Graphics [GPU emulation, framebuffer, ...]";
+
+ /**
+ * Creates a new graphics transformation for Libvirt/QEMU virtualization configurations.
+ *
+ * @param hypervisor Libvirt/QEMU hypervisor.
+ */
+ public TransformationSpecificQemuGraphics( LibvirtHypervisorQemu virtualizer )
+ {
+ super( TransformationSpecificQemuGraphics.NAME, virtualizer );
+ }
+
+ /**
+ * Validates a virtualization configuration and input arguments for this transformation.
+ *
+ * @param config virtualization configuration for the validation.
+ * @param args input arguments for the validation.
+ * @throws TransformationException validation has failed.
+ */
+ private void validateInputs( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ if ( config == null ) {
+ throw new TransformationException( "Virtualization configuration is missing!" );
+ }
+ }
+
+ /**
+ * Add a SPICE graphics device configured for local access through a Unix domain socket.
+ *
+ * @param config virtualization configuration into that the SPICE graphics device is added.
+ * @param openGlEnabled state whether OpenGL is enabled or not.
+ *
+ * @return created SPICE graphics device instance.
+ */
+ public GraphicsSpice addLocalSpiceGraphics( Domain config, boolean openGlEnabled )
+ {
+ final GraphicsSpice newGraphicsSpiceDevice = config.addGraphicsSpiceDevice();
+
+ // select local Unix domain socket access
+ newGraphicsSpiceDevice.setListenType( ListenType.NONE );
+
+ // disable optimizations (compressions) for local usage
+ newGraphicsSpiceDevice.setImageCompression( ImageCompression.OFF );
+ newGraphicsSpiceDevice.setPlaybackCompression( false );
+ newGraphicsSpiceDevice.setStreamingMode( StreamingMode.OFF );
+
+ // enable OpenGL acceleration if necessary
+ newGraphicsSpiceDevice.setOpenGl( openGlEnabled );
+
+ return newGraphicsSpiceDevice;
+ }
+
+ @Override
+ public void transform( Domain config, CommandLineArgs args ) throws TransformationException
+ {
+ // validate configuration and input arguments
+ this.validateInputs( config, args );
+
+ // convert all VNC graphics devices to local SPICE graphics devices
+ for ( final GraphicsVnc graphicsVncDevice : config.getGraphicVncDevices() ) {
+
+ // remove VNC graphics device
+ graphicsVncDevice.remove();
+
+ // add SPICE graphics device with local Unix domain socket access
+ this.addLocalSpiceGraphics( config, false );
+ }
+
+ // convert all SPICE graphics devices to local SPICE graphics devices
+ for ( final GraphicsSpice graphicsSpiceDevice : config.getGraphicSpiceDevices() ) {
+
+ if ( graphicsSpiceDevice.getListenType() != ListenType.NONE ) {
+
+ // save state of configured OpenGL option
+ final boolean openGlEnabled = graphicsSpiceDevice.isOpenGlEnabled();
+
+ // remove VNC graphics device
+ graphicsSpiceDevice.remove();
+
+ // add SPICE graphics device with local Unix domain socket access
+ this.addLocalSpiceGraphics( config, openGlEnabled );
+ }
+ }
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGraphicsTest.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGraphicsTest.java
new file mode 100644
index 00000000..c132f5a5
--- /dev/null
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationSpecificQemuGraphicsTest.java
@@ -0,0 +1,96 @@
+package org.openslx.runvirt.plugin.qemu.configuration;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.Graphics;
+import org.openslx.libvirt.domain.device.GraphicsSpice;
+import org.openslx.libvirt.domain.device.GraphicsSpice.ImageCompression;
+import org.openslx.libvirt.domain.device.GraphicsSpice.StreamingMode;
+import org.openslx.libvirt.domain.device.GraphicsVnc;
+import org.openslx.runvirt.plugin.qemu.cmdln.CommandLineArgs;
+import org.openslx.virtualization.configuration.transformation.TransformationException;
+
+class TransformationSpecificQemuGraphicsStub extends TransformationSpecificQemuGraphics
+{
+ public TransformationSpecificQemuGraphicsStub()
+ {
+ super( null );
+ }
+}
+
+public class TransformationSpecificQemuGraphicsTest
+{
+ @Test
+ @DisplayName( "Test transformation of VM SPICE graphic device configuration" )
+ public void testTransformationSpecificQemuGraphicsSpice() throws TransformationException
+ {
+ final TransformationSpecificQemuGraphicsStub transformation = new TransformationSpecificQemuGraphicsStub();
+ final Domain config = TransformationTestUtils.getDefaultDomain();
+ final CommandLineArgs args = TransformationTestUtils.getDefaultCmdLnArgs();
+
+ final ArrayList<Graphics> devicesBeforeTransformation = config.getGraphicDevices();
+ assertEquals( 1, devicesBeforeTransformation.size() );
+ final ArrayList<GraphicsSpice> spiceDevicesBeforeTransformation = config.getGraphicSpiceDevices();
+ assertEquals( 1, spiceDevicesBeforeTransformation.size() );
+ final ArrayList<GraphicsVnc> vncDevicesBeforeTransformation = config.getGraphicVncDevices();
+ assertEquals( 0, vncDevicesBeforeTransformation.size() );
+
+ transformation.transform( config, args );
+
+ final ArrayList<Graphics> devicesAfterTransformation = config.getGraphicDevices();
+ assertEquals( 1, devicesAfterTransformation.size() );
+ final ArrayList<GraphicsSpice> spiceDevicesAfterTransformation = config.getGraphicSpiceDevices();
+ assertEquals( 1, spiceDevicesAfterTransformation.size() );
+ final ArrayList<GraphicsVnc> vncDevicesAfterTransformation = config.getGraphicVncDevices();
+ assertEquals( 0, vncDevicesAfterTransformation.size() );
+
+ final GraphicsSpice spiceDeviceAfterTransformation = spiceDevicesAfterTransformation.get( 0 );
+ assertEquals( ImageCompression.OFF, spiceDeviceAfterTransformation.getImageCompression() );
+ assertFalse( spiceDeviceAfterTransformation.isPlaybackCompressionOn() );
+ assertEquals( StreamingMode.OFF, spiceDeviceAfterTransformation.getStreamingMode() );
+ assertFalse( spiceDeviceAfterTransformation.isOpenGlEnabled() );
+
+ assertDoesNotThrow( () -> config.validateXml() );
+ }
+
+ @Test
+ @DisplayName( "Test transformation of VM VNC graphic device" )
+ public void testTransformationSpecificQemuGraphicsVnc() throws TransformationException
+ {
+ final TransformationSpecificQemuGraphicsStub transformation = new TransformationSpecificQemuGraphicsStub();
+ final Domain config = TransformationTestUtils
+ .getDomain( "qemu-kvm_default-ubuntu-20-04-vm_transform-non-persistent_vnc.xml" );
+ final CommandLineArgs args = TransformationTestUtils.getEmptyCmdLnArgs();
+
+ final ArrayList<Graphics> devicesBeforeTransformation = config.getGraphicDevices();
+ assertEquals( 1, devicesBeforeTransformation.size() );
+ final ArrayList<GraphicsSpice> spiceDevicesBeforeTransformation = config.getGraphicSpiceDevices();
+ assertEquals( 0, spiceDevicesBeforeTransformation.size() );
+ final ArrayList<GraphicsVnc> vncDevicesBeforeTransformation = config.getGraphicVncDevices();
+ assertEquals( 1, vncDevicesBeforeTransformation.size() );
+
+ transformation.transform( config, args );
+
+ final ArrayList<Graphics> devicesAfterTransformation = config.getGraphicDevices();
+ assertEquals( 1, devicesAfterTransformation.size() );
+ final ArrayList<GraphicsSpice> spiceDevicesAfterTransformation = config.getGraphicSpiceDevices();
+ assertEquals( 1, spiceDevicesAfterTransformation.size() );
+ final ArrayList<GraphicsVnc> vncDevicesAfterTransformation = config.getGraphicVncDevices();
+ assertEquals( 0, vncDevicesAfterTransformation.size() );
+
+ final GraphicsSpice spiceDeviceAfterTransformation = spiceDevicesAfterTransformation.get( 0 );
+ assertEquals( ImageCompression.OFF, spiceDeviceAfterTransformation.getImageCompression() );
+ assertFalse( spiceDeviceAfterTransformation.isPlaybackCompressionOn() );
+ assertEquals( StreamingMode.OFF, spiceDeviceAfterTransformation.getStreamingMode() );
+ assertFalse( spiceDeviceAfterTransformation.isOpenGlEnabled() );
+
+ assertDoesNotThrow( () -> config.validateXml() );
+ }
+}
diff --git a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestUtils.java b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestUtils.java
index 597fd8d6..7bd76be5 100644
--- a/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestUtils.java
+++ b/core/modules/qemu/runvirt-plugin-qemu/src/test/java/org/openslx/runvirt/plugin/qemu/configuration/TransformationTestUtils.java
@@ -102,13 +102,12 @@ public class TransformationTestUtils
return TransformationTestUtils.getCmdLnArgs( new String[] {} );
}
- public static Domain getDefaultDomain()
+ public static Domain getDomain( String fileName )
{
Domain domain = null;
try {
- domain = new Domain( LibvirtXmlTestResources
- .getLibvirtXmlStream( "qemu-kvm_default-ubuntu-20-04-vm_transform-non-persistent.xml" ) );
+ domain = new Domain( LibvirtXmlTestResources.getLibvirtXmlStream( fileName ) );
} catch ( LibvirtXmlDocumentException | LibvirtXmlSerializationException | LibvirtXmlValidationException e ) {
fail( "Cannot prepare requested Libvirt domain XML file from the resources folder: "
+ e.getLocalizedMessage() );
@@ -116,4 +115,9 @@ public class TransformationTestUtils
return domain;
}
+
+ public static Domain getDefaultDomain()
+ {
+ return TransformationTestUtils.getDomain( "qemu-kvm_default-ubuntu-20-04-vm_transform-non-persistent.xml" );
+ }
}