summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx
diff options
context:
space:
mode:
authorStephan Schwär2021-02-19 00:09:54 +0100
committerStephan Schwär2021-02-19 00:09:54 +0100
commit62dce8c2b4e519f689e89038ff2afe4496f60628 (patch)
tree7c6802a436e2beb943065b5a377b61eb77d93170 /src/main/java/org/openslx
parent[docker] Check recieved content. (diff)
parentAdd automatic RelaxNG schema validation for Libvirt domain XML documents (diff)
downloadmaster-sync-shared-62dce8c2b4e519f689e89038ff2afe4496f60628.tar.gz
master-sync-shared-62dce8c2b4e519f689e89038ff2afe4496f60628.tar.xz
master-sync-shared-62dce8c2b4e519f689e89038ff2afe4496f60628.zip
Merge remote-tracking branch 'origin/feature/qemu-integration'
Diffstat (limited to 'src/main/java/org/openslx')
-rw-r--r--src/main/java/org/openslx/libvirt/domain/Domain.java1018
-rw-r--r--src/main/java/org/openslx/libvirt/domain/DomainUtils.java118
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/Controller.java181
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/ControllerFloppy.java54
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/ControllerIde.java128
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/ControllerPci.java145
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/ControllerSata.java54
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/ControllerScsi.java138
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/ControllerUsb.java139
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/Device.java205
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/Disk.java427
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/DiskCdrom.java55
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/DiskFloppy.java52
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/DiskStorage.java54
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/Graphics.java138
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/GraphicsSdl.java54
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/GraphicsSpice.java74
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/GraphicsVnc.java54
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/Hostdev.java139
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/HostdevPci.java79
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/HostdevUsb.java52
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/Interface.java316
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/InterfaceBridge.java54
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/InterfaceNetwork.java54
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/Sound.java128
-rw-r--r--src/main/java/org/openslx/libvirt/domain/device/Video.java188
-rw-r--r--src/main/java/org/openslx/libvirt/xml/LibvirtXmlCreatable.java26
-rw-r--r--src/main/java/org/openslx/libvirt/xml/LibvirtXmlDocument.java373
-rw-r--r--src/main/java/org/openslx/libvirt/xml/LibvirtXmlDocumentException.java25
-rw-r--r--src/main/java/org/openslx/libvirt/xml/LibvirtXmlEditable.java241
-rw-r--r--src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java356
-rw-r--r--src/main/java/org/openslx/libvirt/xml/LibvirtXmlResources.java52
-rw-r--r--src/main/java/org/openslx/libvirt/xml/LibvirtXmlSchemaValidator.java282
-rw-r--r--src/main/java/org/openslx/libvirt/xml/LibvirtXmlSerializable.java57
-rw-r--r--src/main/java/org/openslx/libvirt/xml/LibvirtXmlSerializationException.java25
-rw-r--r--src/main/java/org/openslx/libvirt/xml/LibvirtXmlValidatable.java18
-rw-r--r--src/main/java/org/openslx/libvirt/xml/LibvirtXmlValidationException.java25
-rw-r--r--src/main/java/org/openslx/util/vm/DiskImage.java191
-rw-r--r--src/main/java/org/openslx/util/vm/DockerMetaDataDummy.java17
-rw-r--r--src/main/java/org/openslx/util/vm/QemuMetaData.java797
-rw-r--r--src/main/java/org/openslx/util/vm/QemuMetaDataUtils.java188
-rw-r--r--src/main/java/org/openslx/util/vm/VboxMetaData.java14
-rw-r--r--src/main/java/org/openslx/util/vm/VmMetaData.java9
-rw-r--r--src/main/java/org/openslx/util/vm/VmwareMetaData.java16
44 files changed, 6709 insertions, 101 deletions
diff --git a/src/main/java/org/openslx/libvirt/domain/Domain.java b/src/main/java/org/openslx/libvirt/domain/Domain.java
new file mode 100644
index 0000000..4e15ec1
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/Domain.java
@@ -0,0 +1,1018 @@
+package org.openslx.libvirt.domain;
+
+import java.io.File;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+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;
+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.Disk;
+import org.openslx.libvirt.domain.device.DiskCdrom;
+import org.openslx.libvirt.domain.device.DiskFloppy;
+import org.openslx.libvirt.domain.device.DiskStorage;
+import org.openslx.libvirt.domain.device.Graphics;
+import org.openslx.libvirt.domain.device.GraphicsSdl;
+import org.openslx.libvirt.domain.device.GraphicsSpice;
+import org.openslx.libvirt.domain.device.GraphicsVnc;
+import org.openslx.libvirt.domain.device.Hostdev;
+import org.openslx.libvirt.domain.device.Interface;
+import org.openslx.libvirt.domain.device.InterfaceBridge;
+import org.openslx.libvirt.domain.device.InterfaceNetwork;
+import org.openslx.libvirt.domain.device.Sound;
+import org.openslx.libvirt.domain.device.Video;
+import org.openslx.libvirt.xml.LibvirtXmlDocument;
+import org.openslx.libvirt.xml.LibvirtXmlDocumentException;
+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.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * Implementation of the Libvirt domain XML document.
+ *
+ * The Libvirt domain XML document is used to describe virtual machines and their configurations.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class Domain extends LibvirtXmlDocument
+{
+ /**
+ * Creates Libvirt domain XML document from {@link String} providing Libvirt domain XML content.
+ *
+ * @param xml {@link String} with Libvirt domain XML content.
+ *
+ * @throws LibvirtXmlDocumentException creation of XML context failed.
+ * @throws LibvirtXmlSerializationException serialization of the domain XML content failed.
+ * @throws LibvirtXmlValidationException XML content is not a valid domain XML document.
+ */
+ public Domain( String xml )
+ throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException
+ {
+ super( xml, LibvirtXmlResources.getLibvirtRng( "domain.rng" ) );
+ }
+
+ /**
+ * Creates Libvirt domain XML document from {@link File} containing Libvirt domain XML content.
+ *
+ * @param xml existing {@link File} containing Libvirt domain XML content.
+ *
+ * @throws LibvirtXmlDocumentException creation of XML context failed.
+ * @throws LibvirtXmlSerializationException serialization of the domain XML content failed.
+ * @throws LibvirtXmlValidationException XML content is not a valid domain XML document.
+ */
+ public Domain( File xml )
+ throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException
+ {
+ super( xml, LibvirtXmlResources.getLibvirtRng( "domain.rng" ) );
+ }
+
+ /**
+ * Creates Libvirt domain XML document from {@link InputStream} providing Libvirt domain XML
+ * content.
+ *
+ * @param xml {@link InputStream} providing Libvirt domain XML content.
+ *
+ * @throws LibvirtXmlDocumentException creation of XML context failed.
+ * @throws LibvirtXmlSerializationException serialization of the domain XML content failed.
+ * @throws LibvirtXmlValidationException XML content is not a valid domain XML document.
+ */
+ public Domain( InputStream xml )
+ throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException
+ {
+ super( xml, LibvirtXmlResources.getLibvirtRng( "domain.rng" ) );
+ }
+
+ /**
+ * Creates Libvirt domain XML document from {@link InputSource} providing Libvirt domain XML
+ * content.
+ *
+ * @param xml {@link InputSource} providing Libvirt domain XML content.
+ *
+ * @throws LibvirtXmlDocumentException creation of XML context failed.
+ * @throws LibvirtXmlSerializationException serialization of the domain XML content failed.
+ * @throws LibvirtXmlValidationException XML content is not a valid domain XML document.
+ */
+ public Domain( InputSource xml )
+ throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException
+ {
+ super( xml, LibvirtXmlResources.getLibvirtRng( "domain.rng" ) );
+ }
+
+ /**
+ * Types of hypervisors specifiable for a virtual machine in the Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ public enum Type
+ {
+ // @formatter:off
+ QEMU ( "qemu" ),
+ KQEMU ( "kqemu" ),
+ KVM ( "kvm" ),
+ XEN ( "xen" ),
+ LXC ( "lxc" ),
+ UML ( "uml" ),
+ OPENVZ( "openvz" ),
+ TEST ( "test" ),
+ VMWARE( "vmware" ),
+ HYPERV( "hyperv" ),
+ VBOX ( "vbox" ),
+ PHYP ( "phyp" ),
+ VZ ( "vz" ),
+ BHYVE ( "bhyve" );
+ // @formatter:on
+
+ /**
+ * Name of the hypervisor in a Libvirt domain XML document.
+ */
+ private String type;
+
+ /**
+ * Creates a hypervisor type.
+ *
+ * @param type valid name of the hypervisor in a Libvirt domain XML document.
+ */
+ Type( String type )
+ {
+ this.type = type;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.type;
+ }
+
+ /**
+ * Creates a hypervisor type from its name with error check.
+ *
+ * @param type name of the hypervisor in the Libvirt domain XML document.
+ * @return valid hypervisor type.
+ */
+ public static Type fromString( String type )
+ {
+ for ( Type t : Type.values() ) {
+ if ( t.type.equalsIgnoreCase( type ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Returns hypervisor type defined in the Libvirt domain XML document.
+ *
+ * @return hypervisor type.
+ */
+ public Type getType()
+ {
+ String typeValue = this.getRootXmlNode().getXmlElementAttributeValue( null, "type" );
+ return Type.fromString( typeValue );
+ }
+
+ /**
+ * Sets hypervisor type in Libvirt domain XML document.
+ *
+ * @param type hypervisor type for Libvirt domain XML document.
+ */
+ public void setType( Type type )
+ {
+ this.getRootXmlNode().setXmlElementAttributeValue( null, "type", type.toString() );
+ }
+
+ /**
+ * Returns virtual machine name defined in the Libvirt domain XML document.
+ *
+ * @return name of the virtual machine.
+ */
+ public String getName()
+ {
+ return this.getRootXmlNode().getXmlElementValue( "name" );
+ }
+
+ /**
+ * Sets virtual machine name in the Libvirt domain XML document.
+ *
+ * @param name virtual machine name for Libvirt domain XML document.
+ */
+ public void setName( String name )
+ {
+ this.getRootXmlNode().setXmlElementValue( "name", name );
+ }
+
+ /**
+ * Returns virtual machine title defined in the Libvirt domain XML document.
+ *
+ * @return title of the virtual machine.
+ */
+ public String getTitle()
+ {
+ return this.getRootXmlNode().getXmlElementValue( "title" );
+ }
+
+ /**
+ * Sets virtual machine title in the Libvirt domain XML document.
+ *
+ * @param title virtual machine title for Libvirt domain XML document.
+ */
+ public void setTitle( String title )
+ {
+ this.getRootXmlNode().setXmlElementValue( "title", title );
+ }
+
+ /**
+ * Returns virtual machine description defined in the Libvirt domain XML document.
+ *
+ * @return description of virtual machine.
+ */
+ public String getDescription()
+ {
+ return this.getRootXmlNode().getXmlElementValue( "description" );
+ }
+
+ /**
+ * Sets virtual machine description in the Libvirt domain XML document.
+ *
+ * @param description virtual machine description for Libvirt domain XML document.
+ */
+ public void setDescription( String description )
+ {
+ this.getRootXmlNode().setXmlElementValue( "description", description );
+ }
+
+ /**
+ * Returns virtual machine UUID defined in the Libvirt domain XML document.
+ *
+ * @return UUID of virtual machine.
+ */
+ public String getUuid()
+ {
+ return this.getRootXmlNode().getXmlElementValue( "uuid" );
+ }
+
+ /**
+ * Sets virtual machine UUID in the Libvirt domain XML document.
+ *
+ * @param uuid virtual machine UUID for Libvirt domain XML document.
+ */
+ public void setUuid( String uuid )
+ {
+ this.getRootXmlNode().setXmlElementValue( "uuid", uuid );
+ }
+
+ /**
+ * Removes virtual machine UUID in the Libvirt domain XML document.
+ */
+ public void removeUuid()
+ {
+ this.getRootXmlNode().removeXmlElement( "uuid" );
+ }
+
+ /**
+ * Returns virtual machine memory defined in the Libvirt domain XML document.
+ *
+ * @return memory of virtual machine.
+ */
+ public BigInteger getMemory()
+ {
+ String memValue = this.getRootXmlNode().getXmlElementValue( "memory" );
+ String memUnit = this.getRootXmlNode().getXmlElementAttributeValue( "memory", "unit" );
+ return DomainUtils.decodeMemory( memValue, memUnit );
+ }
+
+ /**
+ * Sets virtual machine memory in the Libvirt domain XML document.
+ *
+ * @param memory virtual machine memory in the Libvirt domain XML document.
+ */
+ public void setMemory( BigInteger memory )
+ {
+ this.getRootXmlNode().setXmlElementAttributeValue( "memory", "unit", "KiB" );
+ this.getRootXmlNode().setXmlElementValue( "memory", DomainUtils.encodeMemory( memory, "KiB" ) );
+ }
+
+ /**
+ * Returns current virtual machine memory defined in the Libvirt domain XML document.
+ *
+ * @return current memory of virtual machine.
+ */
+ public BigInteger getCurrentMemory()
+ {
+ String memValue = this.getRootXmlNode().getXmlElementValue( "currentMemory" );
+ String memUnit = this.getRootXmlNode().getXmlElementAttributeValue( "currentMemory", "unit" );
+ return DomainUtils.decodeMemory( memValue, memUnit );
+ }
+
+ /**
+ * Set current virtual machine memory in the Libvirt domain XML document.
+ *
+ * @param currentMemory current virtual machine memory in the Libvirt domain XML document.
+ */
+ public void setCurrentMemory( BigInteger currentMemory )
+ {
+ this.getRootXmlNode().setXmlElementAttributeValue( "currentMemory", "unit", "KiB" );
+ this.getRootXmlNode().setXmlElementValue( "currentMemory", DomainUtils.encodeMemory( currentMemory, "KiB" ) );
+ }
+
+ /**
+ * Returns number of virtual machine CPUs defined in the Libvirt domain XML document.
+ *
+ * @return number of CPUs of the virtual machine.
+ */
+ public int getVCpu()
+ {
+ String number = this.getRootXmlNode().getXmlElementValue( "vcpu" );
+ return Integer.parseUnsignedInt( number );
+ }
+
+ /**
+ * Set number of virtual machine CPUs in the Libvirt domain XML document.
+ *
+ * @param number virtual machine CPUs.
+ */
+ public void setVCpu( int number )
+ {
+ this.getRootXmlNode().setXmlElementValue( "vcpu", Integer.toString( number ) );
+ }
+
+ /**
+ * Returns virtual machine CPU model defined in the Libvirt domain XML document.
+ *
+ * @return CPU model of virtual machine.
+ */
+ public String getCpuModel()
+ {
+ return this.getRootXmlNode().getXmlElementValue( "cpu/model" );
+ }
+
+ /**
+ * Sets virtual machine CPU model in the Libvirt domain XML document.
+ *
+ * @param model virtual machine CPU model.
+ */
+ public void setCpuModel( String model )
+ {
+ this.getRootXmlNode().setXmlElementValue( "cpu/model", model );
+ }
+
+ /**
+ * CPU modes specifiable for a virtual machine in the Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ public enum CpuMode
+ {
+ // @formatter:off
+ CUSTOM ( "custom" ),
+ HOST_MODEL ( "host-model" ),
+ HOST_PASSTHROUGH( "host-passthrough" );
+ // @formatter:on
+
+ /**
+ * Name of the CPU mode in a Libvirt domain XML document.
+ */
+ private String cpuMode;
+
+ /**
+ * Creates a CPU mode.
+ *
+ * @param mode valid name of the CPU mode in the Libvirt domain XML document.
+ */
+ CpuMode( String mode )
+ {
+ this.cpuMode = mode;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.cpuMode;
+ }
+
+ /**
+ * Creates a CPU mode from its name with error check.
+ *
+ * @param mode name of the CPU mode in the Libvirt domain XML document.
+ * @return valid CPU mode.
+ */
+ public static CpuMode fromString( String mode )
+ {
+ for ( CpuMode t : CpuMode.values() ) {
+ if ( t.cpuMode.equalsIgnoreCase( mode ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Returns virtual machine CPU mode defined in the Libvirt domain XML document.
+ *
+ * @return CPU mode of the virtual machine.
+ */
+ public CpuMode getCpuMode()
+ {
+ String cpuMode = this.getRootXmlNode().getXmlElementAttributeValue( "cpu", "mode" );
+ return CpuMode.fromString( cpuMode );
+ }
+
+ /**
+ * Sets virtual machine CPU mode in the Libvirt domain XML document.
+ *
+ * @param mode virtual machine CPU mode.
+ */
+ public void setCpuMode( CpuMode mode )
+ {
+ this.getRootXmlNode().setXmlElementAttributeValue( "cpu", "mode", mode.toString() );
+ }
+
+ /**
+ * CPU checks specifiable for a virtual machine in the Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ public enum CpuCheck
+ {
+ // @formatter:off
+ NONE ( "none" ),
+ PARTIAL( "partial" ),
+ FULL ( "full" );
+ // @formatter:on
+
+ /**
+ * Name of the CPU check in the Libvirt domain XML document.
+ */
+ private String cpuCheck;
+
+ /**
+ * Creates a CPU check.
+ *
+ * @param check valid name of the CPU check in the Libvirt domain XML document.
+ */
+ CpuCheck( String check )
+ {
+ this.cpuCheck = check;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.cpuCheck;
+ }
+
+ /**
+ * Creates a CPU check from its name with error check.
+ *
+ * @param mode name of the CPU check in the Libvirt domain XML document.
+ * @return valid CPU check.
+ */
+ public static CpuCheck fromString( String check )
+ {
+ for ( CpuCheck t : CpuCheck.values() ) {
+ if ( t.cpuCheck.equalsIgnoreCase( check ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Returns virtual machine CPU check defined in the Libvirt domain XML document.
+ *
+ * @return CPU check of the virtual machine.
+ */
+ public CpuCheck getCpuCheck()
+ {
+ String cpuCheck = this.getRootXmlNode().getXmlElementAttributeValue( "cpu", "check" );
+ return CpuCheck.fromString( cpuCheck );
+ }
+
+ /**
+ * Sets virtual machine CPU check in the Libvirt domain XML document.
+ *
+ * @param check virtual machine CPU check.
+ */
+ public void setCpuCheck( CpuCheck check )
+ {
+ this.getRootXmlNode().setXmlElementAttributeValue( "cpu", "check", check.toString() );
+ }
+
+ /**
+ * Returns virtual machine devices defined in the Libvirt domain XML document.
+ *
+ * @return devices of the virtual machine.
+ */
+ public ArrayList<Device> getDevices()
+ {
+ ArrayList<Device> devices = new ArrayList<Device>();
+ Node devicesNode = this.getRootXmlNode().getXmlElement( "devices" );
+
+ if ( devicesNode != null ) {
+
+ NodeList devicesElements = devicesNode.getChildNodes();
+
+ for ( int i = 0; i < devicesElements.getLength(); i++ ) {
+ LibvirtXmlNode deviceNode = null;
+ deviceNode = new LibvirtXmlNode( this.getRootXmlNode().getXmlDocument(), devicesElements.item( i ) );
+ Device device = Device.newInstance( deviceNode );
+
+ if ( device != null ) {
+ devices.add( device );
+ }
+ }
+ }
+
+ return devices;
+ }
+
+ /**
+ * Filter list of virtual machine devices of type {@link Device} and cast filtered instances to
+ * more specific device type <code>R</code>.
+ *
+ * @param <R> specific device type for filtering and casting.
+ * @param cls specific device type's class.
+ * @param devices list of virtual machines devices.
+ * @return filtered list of virtual machines devices of type <code>R</code>.
+ */
+ private static <R> ArrayList<R> filterDevices( Class<R> cls, ArrayList<Device> devices )
+ {
+ Predicate<Device> byFilter = device -> cls.isInstance( device );
+ Function<Device, R> castFunction = device -> cls.cast( device );
+
+ return devices.stream().filter( byFilter ).map( castFunction )
+ .collect( Collectors.toCollection( ArrayList::new ) );
+ }
+
+ /**
+ * Returns list of virtual machine controller devices specified in the Libvirt domain XML
+ * document.
+ *
+ * @return list of virtual machine controller devices.
+ */
+ public ArrayList<Controller> getControllerDevices()
+ {
+ return Domain.filterDevices( Controller.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine floppy controller devices specified in the Libvirt domain XML
+ * document.
+ *
+ * @return list of virtual machine floppy controller devices.
+ */
+ public ArrayList<ControllerFloppy> getFloppyControllerDevices()
+ {
+ return Domain.filterDevices( ControllerFloppy.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine IDE controller devices specified in the Libvirt domain XML
+ * document.
+ *
+ * @return list of virtual machine IDE controller devices.
+ */
+ public ArrayList<ControllerIde> getIdeControllerDevices()
+ {
+ return Domain.filterDevices( ControllerIde.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine floppy controller devices specified in the Libvirt domain XML
+ * document.
+ *
+ * @return list of virtual machine floppy controller devices.
+ */
+ public ArrayList<ControllerPci> getPciControllerDevices()
+ {
+ return Domain.filterDevices( ControllerPci.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine SATA controller devices specified in the Libvirt domain XML
+ * document.
+ *
+ * @return list of virtual machine SATA controller devices.
+ */
+ public ArrayList<ControllerSata> getSataControllerDevices()
+ {
+ return Domain.filterDevices( ControllerSata.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine SCSI controller devices specified in the Libvirt domain XML
+ * document.
+ *
+ * @return list of virtual machine SCSI controller devices.
+ */
+ public ArrayList<ControllerScsi> getScsiControllerDevices()
+ {
+ return Domain.filterDevices( ControllerScsi.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine USB controller devices specified in the Libvirt domain XML
+ * document.
+ *
+ * @return list of virtual machine USB controller devices.
+ */
+ public ArrayList<ControllerUsb> getUsbControllerDevices()
+ {
+ return Domain.filterDevices( ControllerUsb.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine disk devices specified in the Libvirt domain XML document.
+ *
+ * @return list of virtual machine disk devices.
+ */
+ public ArrayList<Disk> getDiskDevices()
+ {
+ return Domain.filterDevices( Disk.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine disk CDROM devices specified in the Libvirt domain XML
+ * document.
+ *
+ * @return list of virtual machine disk CDROM devices.
+ */
+ public ArrayList<DiskCdrom> getDiskCdromDevices()
+ {
+ return Domain.filterDevices( DiskCdrom.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine disk floppy devices specified in the Libvirt domain XML
+ * document.
+ *
+ * @return list of virtual machine disk floppy devices.
+ */
+ public ArrayList<DiskFloppy> getDiskFloppyDevices()
+ {
+ return Domain.filterDevices( DiskFloppy.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine disk storage devices specified in the Libvirt domain XML
+ * document.
+ *
+ * @return list of virtual machine disk storage devices.
+ */
+ public ArrayList<DiskStorage> getDiskStorageDevices()
+ {
+ return Domain.filterDevices( DiskStorage.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine hostdev devices specified in the Libvirt domain XML document.
+ *
+ * @return list of virtual machine hostdev devices.
+ */
+ public ArrayList<Hostdev> getHostdevDevices()
+ {
+ return Domain.filterDevices( Hostdev.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine network interface devices specified in the Libvirt domain XML
+ * document.
+ *
+ * @return list of virtual machine network interface devices.
+ */
+ public ArrayList<Interface> getInterfaceDevices()
+ {
+ return Domain.filterDevices( Interface.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine graphic devices specified in the Libvirt domain XML document.
+ *
+ * @return list of virtual machine graphic devices.
+ */
+ public ArrayList<Graphics> getGraphicDevices()
+ {
+ return Domain.filterDevices( Graphics.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine sound devices specified in the Libvirt domain XML document.
+ *
+ * @return list of virtual machine sound devices.
+ */
+ public ArrayList<Sound> getSoundDevices()
+ {
+ return Domain.filterDevices( Sound.class, this.getDevices() );
+ }
+
+ /**
+ * Returns list of virtual machine video devices specified in the Libvirt domain XML document.
+ *
+ * @return list of virtual machine video devices.
+ */
+ public ArrayList<Video> getVideoDevices()
+ {
+ return Domain.filterDevices( Video.class, this.getDevices() );
+ }
+
+ /**
+ * Adds a virtual machine device to the Libvirt domain XML document.
+ *
+ * @param device virtual machine device that is added to the Libvirt domain XML document.
+ * @return reference to the added device for configuration purposes if creation was successful.
+ */
+ public Device addDevice( Device device )
+ {
+ Device addedDevice = null;
+
+ if ( device != null ) {
+ Node devicesNode = this.getRootXmlNode().getXmlElement( "devices" );
+
+ if ( devicesNode != null ) {
+ LibvirtXmlNode parentDevicesNode = null;
+ parentDevicesNode = new LibvirtXmlNode( this.getRootXmlNode().getXmlDocument(), devicesNode );
+ addedDevice = Device.createInstance( device, parentDevicesNode );
+ }
+ }
+
+ return addedDevice;
+ }
+
+ /**
+ * Adds a virtual machine controller device to the Libvirt domain XML document.
+ *
+ * @return reference to the added controller device if creation was successful.
+ */
+ public Controller addControllerDevice()
+ {
+ return Controller.class.cast( this.addDevice( new Controller() ) );
+ }
+
+ /**
+ * Adds a virtual machine floppy controller device to the Libvirt domain XML document.
+ *
+ * @return reference to the added floppy controller device if creation was successful.
+ */
+ public ControllerFloppy addControllerFloppyDevice()
+ {
+ return ControllerFloppy.class.cast( this.addDevice( new ControllerFloppy() ) );
+ }
+
+ /**
+ * Adds a virtual machine IDE controller device to the Libvirt domain XML document.
+ *
+ * @return reference to the added IDE controller device if creation was successful.
+ */
+ public ControllerIde addControllerIdeDevice()
+ {
+ return ControllerIde.class.cast( this.addDevice( new ControllerIde() ) );
+ }
+
+ /**
+ * Adds a virtual machine PCI controller device to the Libvirt domain XML document.
+ *
+ * @return reference to the added PCI controller device if creation was successful.
+ */
+ public ControllerPci addControllerPciDevice()
+ {
+ return ControllerPci.class.cast( this.addDevice( new ControllerPci() ) );
+ }
+
+ /**
+ * Adds a virtual machine SATA controller device to the Libvirt domain XML document.
+ *
+ * @return reference to the added SATA controller device if creation was successful.
+ */
+ public ControllerSata addControllerSataDevice()
+ {
+ return ControllerSata.class.cast( this.addDevice( new ControllerSata() ) );
+ }
+
+ /**
+ * Adds a virtual machine SCSI controller device to the Libvirt domain XML document.
+ *
+ * @return reference to the added SCSI controller device if creation was successful.
+ */
+ public ControllerScsi addControllerScsiDevice()
+ {
+ return ControllerScsi.class.cast( this.addDevice( new ControllerScsi() ) );
+ }
+
+ /**
+ * Adds a virtual machine USB controller device to the Libvirt domain XML document.
+ *
+ * @return reference to the added USB controller device if creation was successful.
+ */
+ public ControllerUsb addControllerUsbDevice()
+ {
+ return ControllerUsb.class.cast( this.addDevice( new ControllerUsb() ) );
+ }
+
+ /**
+ * Adds a virtual machine disk device to the Libvirt domain XML document.
+ *
+ * @return reference to the added disk device if creation was successful.
+ */
+ public Disk addDiskDevice()
+ {
+ return Disk.class.cast( this.addDevice( new Disk() ) );
+ }
+
+ /**
+ * Adds a virtual machine CDROM disk device to the Libvirt domain XML document.
+ *
+ * @return reference to the added CDROM disk device if creation was successful.
+ */
+ public DiskCdrom addDiskCdromDevice()
+ {
+ return DiskCdrom.class.cast( this.addDevice( new DiskCdrom() ) );
+ }
+
+ /**
+ * Adds a virtual machine floppy disk device to the Libvirt domain XML document.
+ *
+ * @return reference to the added floppy disk device if creation was successful.
+ */
+ public DiskFloppy addDiskFloppyDevice()
+ {
+ return DiskFloppy.class.cast( this.addDevice( new DiskFloppy() ) );
+ }
+
+ /**
+ * Adds a virtual machine storage disk device to the Libvirt domain XML document.
+ *
+ * @return reference to the added storage disk device if creation was successful.
+ */
+ public DiskStorage addDiskStorageDevice()
+ {
+ return DiskStorage.class.cast( this.addDevice( new DiskStorage() ) );
+ }
+
+ /**
+ * Adds a virtual machine disk device to the Libvirt domain XML document.
+ *
+ * @return reference to the added disk device if creation was successful.
+ */
+ public Hostdev addHostdevDevice()
+ {
+ return Hostdev.class.cast( this.addDevice( new Hostdev() ) );
+ }
+
+ /**
+ * Adds a virtual machine network device to the Libvirt domain XML document.
+ *
+ * @return reference to the added network device if creation was successful.
+ */
+ public Interface addInterfaceDevice()
+ {
+ return Interface.class.cast( this.addDevice( new Interface() ) );
+ }
+
+ /**
+ * Adds a virtual machine network bridge interface device to the Libvirt domain XML document.
+ *
+ * @return reference to the added network interface device if creation was successful.
+ */
+ public InterfaceBridge addInterfaceBridgeDevice()
+ {
+ return InterfaceBridge.class.cast( this.addDevice( new InterfaceBridge() ) );
+ }
+
+ /**
+ * Adds a virtual machine network interface device to the Libvirt domain XML document.
+ *
+ * @return reference to the added network interface device if creation was successful.
+ */
+ public InterfaceNetwork addInterfaceNetworkDevice()
+ {
+ return InterfaceNetwork.class.cast( this.addDevice( new InterfaceNetwork() ) );
+ }
+
+ /**
+ * Adds a virtual machine graphics device to the Libvirt domain XML document.
+ *
+ * @return reference to the added graphics device if creation was successful.
+ */
+ public Graphics addGraphicsDevice()
+ {
+ return Graphics.class.cast( this.addDevice( new Graphics() ) );
+ }
+
+ /**
+ * Adds a virtual machine SDL graphics device to the Libvirt domain XML document.
+ *
+ * @return reference to the added SDL graphics device if creation was successful.
+ */
+ public GraphicsSdl addGraphicsSdlDevice()
+ {
+ return GraphicsSdl.class.cast( this.addDevice( new GraphicsSdl() ) );
+ }
+
+ /**
+ * Adds a virtual machine SPICE graphics device to the Libvirt domain XML document.
+ *
+ * @return reference to the added SPICE graphics device if creation was successful.
+ */
+ public GraphicsSpice addGraphicsSpiceDevice()
+ {
+ return GraphicsSpice.class.cast( this.addDevice( new GraphicsSpice() ) );
+ }
+
+ /**
+ * Adds a virtual machine VNC graphics device to the Libvirt domain XML document.
+ *
+ * @return reference to the added VNC graphics device if creation was successful.
+ */
+ public GraphicsVnc addGraphicsVncDevice()
+ {
+ return GraphicsVnc.class.cast( this.addDevice( new GraphicsVnc() ) );
+ }
+
+ /**
+ * Adds a virtual machine sound device to the Libvirt domain XML document.
+ *
+ * @return reference to the added sound device if creation was successful.
+ */
+ public Sound addSoundDevice()
+ {
+ return Sound.class.cast( this.addDevice( new Sound() ) );
+ }
+
+ /**
+ * Adds a virtual machine video device to the Libvirt domain XML document.
+ *
+ * @return reference to the added video device if creation was successful.
+ */
+ public Video addVideoDevice()
+ {
+ return Video.class.cast( this.addDevice( new Video() ) );
+ }
+
+ /**
+ * Removes boot oder entries in the Libvirt domain XML document.
+ */
+ public void removeBootOrder()
+ {
+ // remove boot order entries of all disk devices
+ for ( Disk diskDevice : this.getDiskDevices() ) {
+ diskDevice.removeBootOrder();
+ }
+
+ // remove boot order entries of all network interface devices
+ for ( Interface interfaceDevice : this.getInterfaceDevices() ) {
+ interfaceDevice.removeBootOrder();
+ }
+
+ // remove boot order entries of all hostdev devices
+ for ( Hostdev hostdevDevice : this.getHostdevDevices() ) {
+ hostdevDevice.removeBootOrder();
+ }
+
+ // remove boot oder entries under the 'os' element
+ this.getRootXmlNode().removeXmlElement( "os/boot" );
+ }
+
+ /**
+ * Removes underlying source for all disk devices in the Libvirt domain XML document.
+ *
+ * @implNote Calling this method will result in an invalid Libvirt domain XML document.
+ */
+ public void removeDiskDevicesStorage()
+ {
+ for ( Disk diskDevice : this.getDiskDevices() ) {
+ diskDevice.removeStorage();
+ }
+ }
+
+ /**
+ * Removes network source for all interface devices in the Libvirt domain XML document.
+ */
+ public void removeInterfaceDevicesSource()
+ {
+ for ( Interface interfaceDevice : this.getInterfaceDevices() ) {
+ interfaceDevice.removeSource();
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/DomainUtils.java b/src/main/java/org/openslx/libvirt/domain/DomainUtils.java
new file mode 100644
index 0000000..2462371
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/DomainUtils.java
@@ -0,0 +1,118 @@
+package org.openslx.libvirt.domain;
+
+import java.math.BigInteger;
+
+/**
+ * Collection of helper functions to maintain a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public final class DomainUtils
+{
+
+ /**
+ * Converts memory value with specified SI unit to absolute value in bytes.
+ *
+ * @param value amount of memory in specified SI unit.
+ * @param unit SI unit name, one of: bytes, KB, k, KiB, MB, M, MiB, GB, G, GiB, TB, T, TiB, for
+ * <code>value</code>.
+ * @return absolute amount of memory in bytes.
+ */
+ public static BigInteger decodeMemory( String value, String unit )
+ {
+ BigInteger factor = null;
+ BigInteger result = new BigInteger( value );
+
+ switch ( unit ) {
+ case "b":
+ case "bytes":
+ factor = new BigInteger( "1" );
+ break;
+ case "KB":
+ factor = new BigInteger( "1000" );
+ break;
+ case "k":
+ case "KiB":
+ factor = new BigInteger( "1024" );
+ break;
+ case "MB":
+ factor = new BigInteger( "1000000" );
+ break;
+ case "M":
+ case "MiB":
+ factor = new BigInteger( "1048576" );
+ break;
+ case "GB":
+ factor = new BigInteger( "1000000000" );
+ break;
+ case "G":
+ case "GiB":
+ factor = new BigInteger( "1073741824" );
+ break;
+ case "TB":
+ factor = new BigInteger( "1000000000000" );
+ break;
+ case "T":
+ case "TiB":
+ factor = new BigInteger( "1099511627776" );
+ break;
+ default:
+ return null;
+ }
+
+ return result.multiply( factor );
+ }
+
+ /**
+ * Convert memory from absolute value in bytes to value in specified SI unit.
+ *
+ * @param value absolute amount of memory in bytes.
+ * @param unit SI unit name, one of: bytes, KB, k, KiB, MB, M, MiB, GB, G, GiB, TB, T, TiB for
+ * returned memory value.
+ * @return amount of memory in specified SI unit.
+ */
+ public static String encodeMemory( BigInteger value, String unit )
+ {
+ BigInteger dividend = null;
+
+ switch ( unit ) {
+ case "b":
+ case "bytes":
+ dividend = new BigInteger( "1" );
+ break;
+ case "KB":
+ dividend = new BigInteger( "1000" );
+ break;
+ case "k":
+ case "KiB":
+ dividend = new BigInteger( "1024" );
+ break;
+ case "MB":
+ dividend = new BigInteger( "1000000" );
+ break;
+ case "M":
+ case "MiB":
+ dividend = new BigInteger( "1048576" );
+ break;
+ case "GB":
+ dividend = new BigInteger( "1000000000" );
+ break;
+ case "G":
+ case "GiB":
+ dividend = new BigInteger( "1073741824" );
+ break;
+ case "TB":
+ dividend = new BigInteger( "1000000000000" );
+ break;
+ case "T":
+ case "TiB":
+ dividend = new BigInteger( "1099511627776" );
+ break;
+ default:
+ return null;
+ }
+
+ return value.divide( dividend ).toString();
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/Controller.java b/src/main/java/org/openslx/libvirt/domain/device/Controller.java
new file mode 100644
index 0000000..626462b
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/Controller.java
@@ -0,0 +1,181 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A controller (PCI, USB, ...) device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class Controller extends Device
+{
+ /**
+ * Creates an empty controller device.
+ */
+ public Controller()
+ {
+ super();
+ }
+
+ /**
+ * Creates a controller device representing an existing Libvirt XML controller device element.
+ *
+ * @param xmlNode existing Libvirt XML controller device element.
+ */
+ public Controller( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Returns index of the controller.
+ *
+ * @return index of the controller.
+ */
+ public int getIndex()
+ {
+ String index = this.getXmlElementAttributeValue( "index" );
+ return Integer.parseInt( index );
+ }
+
+ /**
+ * Sets index for the controller.
+ *
+ * @param index index for the controller.
+ */
+ public void setIndex( int index )
+ {
+ this.setXmlElementAttributeValue( "index", Integer.toString( index ) );
+ }
+
+ /**
+ * Creates a non-existent controller device as Libvirt XML device element.
+ *
+ * @param controller controller device that is created.
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created controller device instance.
+ */
+ public static Controller createInstance( Controller controller, LibvirtXmlNode xmlNode )
+ {
+ Controller addedController = null;
+
+ if ( controller instanceof ControllerFloppy ) {
+ xmlNode.setXmlElementAttributeValue( "type", Type.FLOPPY.toString() );
+ addedController = ControllerFloppy.createInstance( xmlNode );
+ } else if ( controller instanceof ControllerIde ) {
+ xmlNode.setXmlElementAttributeValue( "type", Type.IDE.toString() );
+ addedController = ControllerIde.createInstance( xmlNode );
+ } else if ( controller instanceof ControllerPci ) {
+ xmlNode.setXmlElementAttributeValue( "type", Type.PCI.toString() );
+ addedController = ControllerPci.createInstance( xmlNode );
+ } else if ( controller instanceof ControllerSata ) {
+ xmlNode.setXmlElementAttributeValue( "type", Type.SATA.toString() );
+ addedController = ControllerSata.createInstance( xmlNode );
+ } else if ( controller instanceof ControllerScsi ) {
+ xmlNode.setXmlElementAttributeValue( "type", Type.SCSI.toString() );
+ addedController = ControllerScsi.createInstance( xmlNode );
+ } else if ( controller instanceof ControllerUsb ) {
+ xmlNode.setXmlElementAttributeValue( "type", Type.USB.toString() );
+ addedController = ControllerUsb.createInstance( xmlNode );
+ }
+
+ return addedController;
+ }
+
+ /**
+ * Creates a controller device representing an existing Libvirt XML controller device element.
+ *
+ * @param xmlNode existing Libvirt XML controller device element.
+ * @return controller device instance.
+ */
+ public static Controller newInstance( LibvirtXmlNode xmlNode )
+ {
+
+ Controller deviceController = null;
+ Type type = Type.fromString( xmlNode.getXmlElementAttributeValue( "type" ) );
+
+ if ( type == null ) {
+ return null;
+ }
+
+ switch ( type ) {
+ case FLOPPY:
+ deviceController = ControllerFloppy.newInstance( xmlNode );
+ break;
+ case IDE:
+ deviceController = ControllerIde.newInstance( xmlNode );
+ break;
+ case PCI:
+ deviceController = ControllerPci.newInstance( xmlNode );
+ break;
+ case SATA:
+ deviceController = ControllerSata.newInstance( xmlNode );
+ break;
+ case SCSI:
+ deviceController = ControllerScsi.newInstance( xmlNode );
+ break;
+ case USB:
+ deviceController = ControllerUsb.newInstance( xmlNode );
+ break;
+ }
+
+ return deviceController;
+ }
+
+ /**
+ * Type of controller device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ enum Type
+ {
+ // @formatter:off
+ FLOPPY( "fdc" ),
+ IDE ( "ide" ),
+ PCI ( "pci" ),
+ SATA ( "sata" ),
+ SCSI ( "scsi" ),
+ USB ( "usb" );
+ // @formatter:on
+
+ /**
+ * Name of the controller device type.
+ */
+ private String type = null;
+
+ /**
+ * Creates controller device type.
+ *
+ * @param type valid name of the controller device type in a Libvirt domain XML document.
+ */
+ Type( String type )
+ {
+ this.type = type;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.type;
+ }
+
+ /**
+ * Creates controller device type from its name with error check.
+ *
+ * @param type name of the controller device type in a Libvirt domain XML document.
+ * @return valid controller device type.
+ */
+ public static Type fromString( String type )
+ {
+ for ( Type t : Type.values() ) {
+ if ( t.type.equalsIgnoreCase( type ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/ControllerFloppy.java b/src/main/java/org/openslx/libvirt/domain/device/ControllerFloppy.java
new file mode 100644
index 0000000..5e580bd
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/ControllerFloppy.java
@@ -0,0 +1,54 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A floppy controller device in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class ControllerFloppy extends Controller
+{
+ /**
+ * Creates an empty floppy controller device.
+ */
+ public ControllerFloppy()
+ {
+ super();
+ }
+
+ /**
+ * Creates a floppy controller device representing an existing Libvirt XML floppy controller
+ * device element.
+ *
+ * @param xmlNode existing Libvirt XML controller device element.
+ */
+ public ControllerFloppy( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Creates a non-existent floppy controller device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created floppy controller device instance.
+ */
+ public static ControllerFloppy createInstance( LibvirtXmlNode xmlNode )
+ {
+ return ControllerFloppy.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a floppy controller device representing an existing Libvirt XML floppy controller
+ * device element.
+ *
+ * @param xmlNode existing Libvirt XML controller device element.
+ * @return floppy controller device instance.
+ */
+ public static ControllerFloppy newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new ControllerFloppy( xmlNode );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/ControllerIde.java b/src/main/java/org/openslx/libvirt/domain/device/ControllerIde.java
new file mode 100644
index 0000000..062b67d
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/ControllerIde.java
@@ -0,0 +1,128 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * An IDE controller device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class ControllerIde extends Controller
+{
+ /**
+ * Creates an empty IDE controller device.
+ */
+ public ControllerIde()
+ {
+ super();
+ }
+
+ /**
+ * Creates an IDE controller device representing an existing Libvirt XML IDE controller device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML IDE controller device element.
+ */
+ public ControllerIde( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Returns emulated hardware model of the IDE controller.
+ *
+ * @return hardware model of the IDE controller.
+ */
+ public Model getModel()
+ {
+ String model = this.getXmlElementAttributeValue( "model" );
+ return Model.fromString( model );
+ }
+
+ /**
+ * Sets hardware model for the IDE controller.
+ *
+ * @param model hardware model for the IDE controller.
+ */
+ public void setModel( Model model )
+ {
+ this.setXmlElementAttributeValue( "model", model.toString() );
+ }
+
+ /**
+ * Creates a non-existent IDE controller device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created IDE controller device instance.
+ */
+ public static ControllerIde createInstance( LibvirtXmlNode xmlNode )
+ {
+ return ControllerIde.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates an IDE controller device representing an existing Libvirt XML IDE controller device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML IDE controller device element.
+ * @return IDE controller device instance.
+ */
+ public static ControllerIde newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new ControllerIde( xmlNode );
+ }
+
+ /**
+ * Model of IDE controller device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ enum Model
+ {
+ // @formatter:off
+ PIIX3( "piix3" ),
+ PIIX4( "pixx4" ),
+ ICH6 ( "ich6" );
+ // @formatter:on
+
+ /**
+ * Name of the IDE controller device model.
+ */
+ private String model = null;
+
+ /**
+ * Creates IDE controller device model.
+ *
+ * @param type valid name of the IDE controller device model in a Libvirt domain XML document.
+ */
+ Model( String model )
+ {
+ this.model = model;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.model;
+ }
+
+ /**
+ * Creates IDE controller device model from its name with error check.
+ *
+ * @param type name of the IDE controller device model in a Libvirt domain XML document.
+ * @return valid IDE controller device model.
+ */
+ public static Model fromString( String model )
+ {
+ for ( Model t : Model.values() ) {
+ if ( t.model.equalsIgnoreCase( model ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/ControllerPci.java b/src/main/java/org/openslx/libvirt/domain/device/ControllerPci.java
new file mode 100644
index 0000000..feb8b1a
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/ControllerPci.java
@@ -0,0 +1,145 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A PCI controller device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class ControllerPci extends Controller
+{
+ /**
+ * Creates an empty PCI controller device.
+ */
+ public ControllerPci()
+ {
+ super();
+ }
+
+ /**
+ * Creates a PCI controller device representing an existing Libvirt XML PCI controller device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML PCI controller device element.
+ */
+ public ControllerPci( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Returns model of the PCI controller.
+ *
+ * @return model of the PCI controller.
+ */
+ public Model getModel()
+ {
+ String model = this.getXmlElementAttributeValue( "model" );
+ return Model.fromString( model );
+ }
+
+ /**
+ * Sets model for the PCI controller.
+ *
+ * @param model model for the PCI controller.
+ */
+ public void setModel( Model model )
+ {
+ this.setXmlElementAttributeValue( "model", model.toString() );
+ }
+
+ /**
+ * Returns emulated hardware model of the PCI controller.
+ *
+ * @return emulated hardware model of the PCI controller.
+ */
+ public String getModelEmulated()
+ {
+ return this.getXmlElementAttributeValue( "model", "name" );
+ }
+
+ /**
+ * Creates a non-existent PCI controller device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created PCI controller device instance.
+ */
+ public static ControllerPci createInstance( LibvirtXmlNode xmlNode )
+ {
+ return ControllerPci.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a PCI controller device representing an existing Libvirt XML PCI controller device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML PCI controller device element.
+ * @return PCI controller device instance.
+ */
+ public static ControllerPci newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new ControllerPci( xmlNode );
+ }
+
+ /**
+ * Model of PCI controller device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ enum Model
+ {
+ // @formatter:off
+ PCI_ROOT ( "pci-root" ),
+ PCI_BRDIGE ( "pci-bridge" ),
+ PCIE_ROOT ( "pcie-root" ),
+ PCI_DMI2BRIDGE ( "dmi-to-pci-bridge" ),
+ PCIE_ROOT_PORT ( "pcie-root-port" ),
+ PCIE_SWITCH_UPSTREAM_PORT ( "pcie-switch-upstream-port" ),
+ PCIE_SWITCH_DOWNSTREAM_PORT( "pcie-switch-downstream-port" ),
+ PCI_EXPANDER_BUS ( "pci-expander-bus" ),
+ PCIE_EXPANDER_BUS ( "pcie-expander-bus" ),
+ PCIE2PCI_BRIDGE ( "pcie-to-pci-bridge" );
+ // @formatter:on
+
+ /**
+ * Name of the PCI controller device model.
+ */
+ private String model = null;
+
+ /**
+ * Creates PCI controller device model.
+ *
+ * @param type valid name of the PCI controller device model in a Libvirt domain XML document.
+ */
+ Model( String model )
+ {
+ this.model = model;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.model;
+ }
+
+ /**
+ * Creates PCI controller device model from its name with error check.
+ *
+ * @param type name of the PCI controller device model in a Libvirt domain XML document.
+ * @return valid PCI controller device model.
+ */
+ public static Model fromString( String model )
+ {
+ for ( Model t : Model.values() ) {
+ if ( t.model.equalsIgnoreCase( model ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/ControllerSata.java b/src/main/java/org/openslx/libvirt/domain/device/ControllerSata.java
new file mode 100644
index 0000000..b784ae0
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/ControllerSata.java
@@ -0,0 +1,54 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A SATA controller device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class ControllerSata extends Controller
+{
+ /**
+ * Creates an empty SATA controller device.
+ */
+ public ControllerSata()
+ {
+ super();
+ }
+
+ /**
+ * Creates a SATA controller device representing an existing Libvirt XML SATA controller device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML SATA controller device element.
+ */
+ public ControllerSata( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Creates a non-existent SATA controller device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created SATA controller device instance.
+ */
+ public static ControllerSata createInstance( LibvirtXmlNode xmlNode )
+ {
+ return ControllerSata.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a SATA controller device representing an existing Libvirt XML SATA controller device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML SATA controller device element.
+ * @return SATA controller device instance.
+ */
+ public static ControllerSata newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new ControllerSata( xmlNode );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/ControllerScsi.java b/src/main/java/org/openslx/libvirt/domain/device/ControllerScsi.java
new file mode 100644
index 0000000..16c3a0f
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/ControllerScsi.java
@@ -0,0 +1,138 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A SCSI controller device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class ControllerScsi extends Controller
+{
+ /**
+ * Creates an empty SCSI controller device.
+ */
+ public ControllerScsi()
+ {
+ super();
+ }
+
+ /**
+ * Creates a SCSI controller device representing an existing Libvirt XML SCSI controller device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML SCSI controller device element.
+ */
+ public ControllerScsi( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Returns hardware model of the PCI controller.
+ *
+ * @return hardware model of the PCI controller.
+ */
+ public Model getModel()
+ {
+ String model = this.getXmlElementAttributeValue( "model" );
+ return Model.fromString( model );
+ }
+
+ /**
+ * Sets hardware model for the PCI controller.
+ *
+ * @param model hardware model for the PCI controller.
+ */
+ public void setModel( Model model )
+ {
+ this.setXmlElementAttributeValue( "model", model.toString() );
+ }
+
+ /**
+ * Creates a non-existent SCSI controller device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created SCSI controller device instance.
+ */
+ public static ControllerScsi createInstance( LibvirtXmlNode xmlNode )
+ {
+ return ControllerScsi.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a SCSI controller device representing an existing Libvirt XML SCSI controller device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML SCSI controller device element.
+ * @return SCSI controller device instance.
+ */
+ public static ControllerScsi newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new ControllerScsi( xmlNode );
+ }
+
+ /**
+ * Model of SCSI controller device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ enum Model
+ {
+ // @formatter:off
+ AUTO ( "auto" ),
+ BUSLOGIC ( "buslogic" ),
+ IBMVSCSI ( "ibmvscsi" ),
+ LSISAS1068 ( "lsisas1068" ),
+ LSISAS1078 ( "lsisas1078" ),
+ VIRTIO_SCSI ( "virtio-scsi" ),
+ VMPVSCSI ( "vmpvscsi" ),
+ VIRTIO_TRANSITIONAL ( "virtio-transitional" ),
+ VIRTIO_NON_TRANSITIONAL( "virtio-non-transitional" ),
+ NCR53C90 ( "ncr53c90" ),
+ AM53C974 ( "am53c974" ),
+ DC390 ( "dc390" );
+ // @formatter:on
+
+ /**
+ * Name of the SCSI controller device model.
+ */
+ private String model = null;
+
+ /**
+ * Creates SCSI controller device model.
+ *
+ * @param type valid name of the SCSI controller device model in a Libvirt domain XML
+ * document.
+ */
+ Model( String model )
+ {
+ this.model = model;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.model;
+ }
+
+ /**
+ * Creates SCSI controller device model from its name with error check.
+ *
+ * @param type name of the SCSI controller device model in a Libvirt domain XML document.
+ * @return valid SCSI controller device model.
+ */
+ public static Model fromString( String model )
+ {
+ for ( Model t : Model.values() ) {
+ if ( t.model.equalsIgnoreCase( model ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/ControllerUsb.java b/src/main/java/org/openslx/libvirt/domain/device/ControllerUsb.java
new file mode 100644
index 0000000..695167c
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/ControllerUsb.java
@@ -0,0 +1,139 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A USB controller device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class ControllerUsb extends Controller
+{
+ /**
+ * Creates an empty USB controller device.
+ */
+ public ControllerUsb()
+ {
+ super();
+ }
+
+ /**
+ * Creates an USB controller device representing an existing Libvirt XML USB controller device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML USB controller device element.
+ */
+ public ControllerUsb( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Returns hardware model of the PCI controller.
+ *
+ * @return hardware model of the PCI controller.
+ */
+ public Model getModel()
+ {
+ String model = this.getXmlElementAttributeValue( "model" );
+ return Model.fromString( model );
+ }
+
+ /**
+ * Sets hardware model for the PCI controller.
+ *
+ * @param model hardware model for the PCI controller.
+ */
+ public void setModel( Model model )
+ {
+ this.setXmlElementAttributeValue( "model", model.toString() );
+ }
+
+ /**
+ * Creates a non-existent USB controller device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created USB controller device instance.
+ */
+ public static ControllerUsb createInstance( LibvirtXmlNode xmlNode )
+ {
+ return ControllerUsb.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates an USB controller device representing an existing Libvirt XML USB controller device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML USB controller device element.
+ * @return USB controller device instance.
+ */
+ public static ControllerUsb newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new ControllerUsb( xmlNode );
+ }
+
+ /**
+ * Model of PCI controller device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ public enum Model
+ {
+ // @formatter:off
+ NONE ( "none" ),
+ PIIX3_UHCI ( "piix3-uhci" ),
+ PIIX4_UHCI ( "piix4-uhci" ),
+ EHCI ( "ehci" ),
+ ICH9_EHCI1 ( "ich9-ehci1" ),
+ ICH9_UHCI1 ( "ich9-uhci1" ),
+ ICH9_UHCI2 ( "ich9-uhci2" ),
+ ICH9_UHCI3 ( "ich9-uhci3" ),
+ VT82C686B_UHCI( "vt82c686b-uhci" ),
+ PCI_OHCI ( "pci-ohci" ),
+ NEC_XHCI ( "nec-xhci" ),
+ QUSB1 ( "qusb1" ),
+ QUSB2 ( "qusb2" ),
+ QEMU_XHCI ( "qemu-xhci" );
+ // @formatter:on
+
+ /**
+ * Name of the USB controller device model.
+ */
+ private String model = null;
+
+ /**
+ * Creates USB controller device model.
+ *
+ * @param type valid name of the USB controller device model in a Libvirt domain XML document.
+ */
+ Model( String model )
+ {
+ this.model = model;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.model;
+ }
+
+ /**
+ * Creates USB controller device model from its name with error check.
+ *
+ * @param type name of the USB controller device model in a Libvirt domain XML document.
+ * @return valid USB controller device model.
+ */
+ public static Model fromString( String model )
+ {
+ for ( Model t : Model.values() ) {
+ if ( t.model.equalsIgnoreCase( model ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/Device.java b/src/main/java/org/openslx/libvirt/domain/device/Device.java
new file mode 100644
index 0000000..5c26c55
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/Device.java
@@ -0,0 +1,205 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * A virtual machines device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class Device extends LibvirtXmlNode
+{
+ /**
+ * Creates an empty virtual machine device.
+ */
+ public Device()
+ {
+ super();
+ }
+
+ /**
+ * Creates a virtual machine device representing an existing Libvirt XML device element.
+ *
+ * @param xmlNode existing Libvirt XML device element.
+ */
+ public Device( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Removes device from Libvirt domain XML document.
+ */
+ public void remove()
+ {
+ Node node = this.getXmlElement();
+ node.getParentNode().removeChild( node );
+ }
+
+ /**
+ * Creates a Libvirt XML device element as child of a given Libvirt XML parent node.
+ *
+ * @param xmlParentNode parent Libvirt XML node of the Libvirt XML device element that is
+ * created.
+ * @param deviceType type of the Libvirt XML device element.
+ * @return created Libvirt XML device node.
+ */
+ private static LibvirtXmlNode createDeviceElement( LibvirtXmlNode xmlParentNode, Type deviceType )
+ {
+ // create XML element as part of the Libvirt XML document
+ Document xmlDocument = xmlParentNode.getXmlDocument();
+ Element deviceNode = xmlDocument.createElement( deviceType.toString() );
+
+ // append the created XML element to the Libvirt XML document
+ xmlParentNode.getXmlBaseNode().appendChild( deviceNode );
+
+ return new LibvirtXmlNode( xmlParentNode.getXmlDocument(), deviceNode );
+ }
+
+ /**
+ * Creates a non-existent virtual machine device as Libvirt XML device element.
+ *
+ * @param device virtual machine device that is created.
+ * @param xmlParentNode parent Libvirt XML node of the Libvirt XML device that is created.
+ * @return created virtual machine device instance.
+ */
+ public static Device createInstance( Device device, LibvirtXmlNode xmlParentNode )
+ {
+ Device createdDevice = null;
+
+ if ( device instanceof Controller ) {
+ LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.CONTROLLER );
+ createdDevice = Controller.createInstance( Controller.class.cast( device ), xmlNode );
+ } else if ( device instanceof Disk ) {
+ LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.DISK );
+ createdDevice = Disk.createInstance( Disk.class.cast( device ), xmlNode );
+ } else if ( device instanceof Hostdev ) {
+ LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.HOSTDEV );
+ createdDevice = Hostdev.createInstance( Hostdev.class.cast( device ), xmlNode );
+ } else if ( device instanceof Interface ) {
+ LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.INTERFACE );
+ createdDevice = Interface.createInstance( Interface.class.cast( device ), xmlNode );
+ } else if ( device instanceof Graphics ) {
+ LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.GRAPHICS );
+ createdDevice = Graphics.createInstance( Graphics.class.cast( device ), xmlNode );
+ } else if ( device instanceof Sound ) {
+ LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.SOUND );
+ createdDevice = Sound.createInstance( xmlNode );
+ } else if ( device instanceof Video ) {
+ LibvirtXmlNode xmlNode = Device.createDeviceElement( xmlParentNode, Type.VIDEO );
+ createdDevice = Video.createInstance( xmlNode );
+ }
+
+ return createdDevice;
+ }
+
+ /**
+ * Creates a virtual machine device representing an existing Libvirt XML device element.
+ *
+ * @param xmlNode existing Libvirt XML device element.
+ * @return virtual machine device instance.
+ */
+ public static Device newInstance( LibvirtXmlNode xmlNode )
+ {
+
+ Node element = xmlNode.getXmlElement();
+
+ if ( element == null ) {
+ return null;
+ } else {
+ Device device = null;
+ Type type = Type.fromString( element.getNodeName() );
+
+ if ( type == null ) {
+ return null;
+ }
+
+ switch ( type ) {
+ case CONTROLLER:
+ device = Controller.newInstance( xmlNode );
+ break;
+ case DISK:
+ device = Disk.newInstance( xmlNode );
+ break;
+ case HOSTDEV:
+ device = Hostdev.newInstance( xmlNode );
+ break;
+ case INTERFACE:
+ device = Interface.newInstance( xmlNode );
+ break;
+ case GRAPHICS:
+ device = Graphics.newInstance( xmlNode );
+ break;
+ case SOUND:
+ device = Sound.newInstance( xmlNode );
+ break;
+ case VIDEO:
+ device = Video.newInstance( xmlNode );
+ break;
+ }
+
+ return device;
+ }
+ }
+
+ /**
+ * Type of virtual machine devices.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ enum Type
+ {
+ // @formatter:off
+ CONTROLLER( "controller" ),
+ DISK ( "disk" ),
+ HOSTDEV ( "hostdev" ),
+ INTERFACE ( "interface" ),
+ GRAPHICS ( "graphics" ),
+ SOUND ( "sound" ),
+ VIDEO ( "video" );
+ // @formatter:on
+
+ /**
+ * Name of the virtual machine device type.
+ */
+ private String type = null;
+
+ /**
+ * Creates virtual machine device type.
+ *
+ * @param type valid name of the virtual machine device type in a Libvirt domain XML document.
+ */
+ Type( String type )
+ {
+ this.type = type;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.type;
+ }
+
+ /**
+ * Creates virtual machine device type from its name with error check.
+ *
+ * @param type name of the virtual machine device type in a Libvirt domain XML document.
+ * @return valid virtual machine device type.
+ */
+ public static Type fromString( String type )
+ {
+ for ( Type t : Type.values() ) {
+ if ( t.type.equalsIgnoreCase( type ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/Disk.java b/src/main/java/org/openslx/libvirt/domain/device/Disk.java
new file mode 100644
index 0000000..464e7b6
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/Disk.java
@@ -0,0 +1,427 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+import org.w3c.dom.Node;
+
+/**
+ * A disk (floppy, CDROM, ...) device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class Disk extends Device
+{
+ /**
+ * Creates an empty disk device.
+ */
+ public Disk()
+ {
+ super();
+ }
+
+ /**
+ * Creates a disk device representing an existing Libvirt XML disk device element.
+ *
+ * @param xmlNode existing Libvirt XML disk device element.
+ */
+ public Disk( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Returns storage type of the disk device.
+ *
+ * @return storage type of underlying source for the disk device.
+ */
+ public StorageType getStorageType()
+ {
+ String storageType = this.getXmlElementAttributeValue( "type" );
+ return StorageType.fromString( storageType );
+ }
+
+ /**
+ * Sets storage type for the disk device.
+ *
+ * @param storageType storage type of underlying source for the disk device.
+ *
+ * @implNote Please call {@link #setStorageSource(String)} after calling this method, otherwise
+ * the underlying source for the disk device may be invalid.
+ */
+ protected void setStorageType( StorageType storageType )
+ {
+ this.setXmlElementAttributeValue( "type", storageType.toString() );
+ }
+
+ /**
+ * Returns underlying source of disk device.
+ *
+ * @return file path to underlying source of disk device.
+ */
+ public String getStorageSource()
+ {
+ StorageType storageType = this.getStorageType();
+ String storageSource = null;
+
+ switch ( storageType ) {
+ case FILE:
+ storageSource = this.getXmlElementAttributeValue( "source", "file" );
+ break;
+ case BLOCK:
+ storageSource = this.getXmlElementAttributeValue( "source", "bdev" );
+ break;
+ }
+
+ return storageSource;
+ }
+
+ /**
+ * Sets underlying source for disk device.
+ *
+ * @param source file path to underlying source for disk device.
+ *
+ * @implNote Please call {@link #setStorageType(StorageType)} before calling this method,
+ * otherwise the underlying source for the disk device is not set.
+ */
+ protected void setStorageSource( String source )
+ {
+ StorageType storageType = this.getStorageType();
+
+ // remove all attributes from sub-element 'source'
+ this.removeXmlElementAttributes( "source" );
+
+ // rewrite specific attribute depending on the storage type
+ switch ( storageType ) {
+ case FILE:
+ this.setXmlElementAttributeValue( "source", "file", source );
+ break;
+ case BLOCK:
+ this.setXmlElementAttributeValue( "source", "bdev", source );
+ break;
+ }
+ }
+
+ /**
+ * Sets storage type and underlying source for disk device.
+ *
+ * @param storageType storage type of underlying source for the disk device.
+ * @param source file path to underlying source for disk device.
+ */
+ public void setStorage( StorageType storageType, String source )
+ {
+ this.setStorageType( storageType );
+ this.setStorageSource( source );
+ }
+
+ /**
+ * Removes underlying source of the disk device.
+ *
+ * @implNote Calling this method will result in an invalid Libvirt domain XML content.
+ */
+ public void removeStorage()
+ {
+ this.removeXmlElement( "source" );
+ }
+
+ /**
+ * Removes boot oder entry of the disk device.
+ */
+ public void removeBootOrder()
+ {
+ this.removeXmlElement( "boot" );
+ }
+
+ /**
+ * Returns read only state of disk device.
+ *
+ * @return read only state of disk device.
+ */
+ public boolean isReadOnly()
+ {
+ Node readOnly = this.getXmlElement( "readonly" );
+
+ if ( readOnly == null ) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Sets read only state for disk device.
+ *
+ * @param readOnly state for disk device and its read only functionality.
+ */
+ public void setReadOnly( boolean readOnly )
+ {
+ if ( readOnly ) {
+ this.setXmlElement( "readonly" );
+ } else {
+ this.removeXmlElement( "readonly" );
+ }
+ }
+
+ /**
+ * Returns bus type of the disk device.
+ *
+ * @return bus type of the disk device.
+ */
+ public BusType getBusType()
+ {
+ String busType = this.getXmlElementAttributeValue( "target", "bus" );
+ return BusType.fromString( busType );
+ }
+
+ /**
+ * Sets bus type for the disk device.
+ *
+ * @param busType bus type for the disk device.
+ */
+ public void setBusType( BusType busType )
+ {
+ this.setXmlElementAttributeValue( "target", "bus", busType.toString() );
+ }
+
+ /**
+ * Returns target device of the disk device.
+ *
+ * @return target device of the disk device.
+ */
+ public String getTargetDevice()
+ {
+ return this.getXmlElementAttributeValue( "target", "dev" );
+ }
+
+ /**
+ * Sets target device for the disk device.
+ *
+ * @param target device for the disk device.
+ */
+ public void setTargetDevice( String targetDevice )
+ {
+ this.setXmlElementAttributeValue( "target", "dev", targetDevice );
+ }
+
+ /**
+ * Creates a non-existent disk device as Libvirt XML device element.
+ *
+ * @param disk disk device that is created.
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created disk device instance.
+ */
+ public static Disk createInstance( Disk disk, LibvirtXmlNode xmlNode )
+ {
+ Disk addedDisk = null;
+
+ if ( disk instanceof DiskCdrom ) {
+ xmlNode.setXmlElementAttributeValue( "device", Type.CDROM.toString() );
+ addedDisk = DiskCdrom.createInstance( xmlNode );
+ } else if ( disk instanceof DiskFloppy ) {
+ xmlNode.setXmlElementAttributeValue( "device", Type.FLOPPY.toString() );
+ addedDisk = DiskFloppy.createInstance( xmlNode );
+ } else if ( disk instanceof DiskStorage ) {
+ xmlNode.setXmlElementAttributeValue( "device", Type.STORAGE.toString() );
+ addedDisk = DiskStorage.createInstance( xmlNode );
+ }
+
+ return addedDisk;
+ }
+
+ /**
+ * Creates a disk device representing an existing Libvirt XML disk device element.
+ *
+ * @param xmlNode existing Libvirt XML disk device element.
+ * @return disk device instance.
+ */
+ public static Disk newInstance( LibvirtXmlNode xmlNode )
+ {
+ Disk deviceDisk = null;
+ Type type = Type.fromString( xmlNode.getXmlElementAttributeValue( "device" ) );
+
+ if ( type == null ) {
+ return null;
+ }
+
+ switch ( type ) {
+ case CDROM:
+ deviceDisk = DiskCdrom.newInstance( xmlNode );
+ break;
+ case FLOPPY:
+ deviceDisk = DiskFloppy.newInstance( xmlNode );
+ break;
+ case STORAGE:
+ deviceDisk = DiskStorage.newInstance( xmlNode );
+ break;
+ }
+
+ return deviceDisk;
+ }
+
+ /**
+ * Type of disk device.
+ *
+ * Indicates how a disk is to be exposed to the guest OS.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ enum Type
+ {
+ // @formatter:off
+ CDROM ( "cdrom" ),
+ FLOPPY ( "floppy" ),
+ STORAGE( "disk" );
+ // @formatter:on
+
+ /**
+ * Name of the disk device type.
+ */
+ private String type = null;
+
+ /**
+ * Creates disk device type.
+ *
+ * @param type valid name of the disk device type in a Libvirt domain XML document.
+ */
+ Type( String type )
+ {
+ this.type = type;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.type;
+ }
+
+ /**
+ * Creates disk device type from its name with error check.
+ *
+ * @param type name of the disk device type in a Libvirt domain XML document.
+ * @return valid disk device type.
+ */
+ public static Type fromString( String type )
+ {
+ for ( Type t : Type.values() ) {
+ if ( t.type.equalsIgnoreCase( type ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Storage type of a disk device.
+ *
+ * The storage type refers to the underlying source for the disk.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ public enum StorageType
+ {
+ // @formatter:off
+ FILE ( "file" ),
+ BLOCK ( "block" );
+ // @formatter:on
+
+ /**
+ * Name of the disk device type.
+ */
+ private String storageType = null;
+
+ /**
+ * Creates disk device storage type.
+ *
+ * @param storageType valid name of the disk device storage type in a Libvirt domain XML
+ * document.
+ */
+ StorageType( String storageType )
+ {
+ this.storageType = storageType;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.storageType;
+ }
+
+ /**
+ * Creates disk device storage type from its name with error check.
+ *
+ * @param storageType name of the disk device storage type in a Libvirt domain XML document.
+ * @return valid disk device storage type.
+ */
+ public static StorageType fromString( String storageType )
+ {
+ for ( StorageType t : StorageType.values() ) {
+ if ( t.storageType.equalsIgnoreCase( storageType ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Bus type (IDE, SATA, ...) of a disk device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ public enum BusType
+ {
+ // @formatter:off
+ IDE ( "ide" ),
+ FDC ( "fdc" ),
+ SATA ( "sata" ),
+ SCSI ( "scsi" ),
+ SD ( "sd" ),
+ USB ( "usb" ),
+ VIRTIO( "virtio" ),
+ XEN ( "xen" );
+ // @formatter:on
+
+ /**
+ * Name of the disk device bus type.
+ */
+ private String busType = null;
+
+ /**
+ * Creates disk device bus type.
+ *
+ * @param busType valid name of the disk device bus type in a Libvirt domain XML document.
+ */
+ BusType( String busType )
+ {
+ this.busType = busType;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.busType;
+ }
+
+ /**
+ * Creates disk device bus type from its name with error check.
+ *
+ * @param busType name of the disk device bus type in a Libvirt domain XML document.
+ * @return valid disk device bus type.
+ */
+ public static BusType fromString( String busType )
+ {
+ for ( BusType t : BusType.values() ) {
+ if ( t.busType.equalsIgnoreCase( busType ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/DiskCdrom.java b/src/main/java/org/openslx/libvirt/domain/device/DiskCdrom.java
new file mode 100644
index 0000000..2ae08e1
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/DiskCdrom.java
@@ -0,0 +1,55 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A CDROM disk device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class DiskCdrom extends Disk
+{
+ /**
+ * Creates an empty CDROM disk device.
+ */
+ public DiskCdrom()
+ {
+ super();
+ }
+
+ /**
+ * Creates a CDROM disk device representing an existing Libvirt XML CDROM disk device element.
+ *
+ * @param xmlNode existing Libvirt XML CDROM disk device element.
+ */
+ public DiskCdrom( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+
+ // restrict CDROM disk device default read/write access always to readonly
+ this.setReadOnly( true );
+ }
+
+ /**
+ * Creates a non-existent CDROM disk device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created CDROM disk device instance.
+ */
+ public static DiskCdrom createInstance( LibvirtXmlNode xmlNode )
+ {
+ return DiskCdrom.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a CDROM disk device representing an existing Libvirt XML CDROM disk device element.
+ *
+ * @param xmlNode existing Libvirt XML CDROM disk device element.
+ * @return CDROM disk device instance.
+ */
+ public static DiskCdrom newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new DiskCdrom( xmlNode );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/DiskFloppy.java b/src/main/java/org/openslx/libvirt/domain/device/DiskFloppy.java
new file mode 100644
index 0000000..ce9733b
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/DiskFloppy.java
@@ -0,0 +1,52 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A floppy disk device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class DiskFloppy extends Disk
+{
+ /**
+ * Creates an empty floppy disk device.
+ */
+ public DiskFloppy()
+ {
+ super();
+ }
+
+ /**
+ * Creates a floppy disk device representing an existing Libvirt XML floppy disk device element.
+ *
+ * @param xmlNode existing Libvirt XML floppy disk device element.
+ */
+ public DiskFloppy( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Creates a non-existent floppy disk device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created floppy disk device instance.
+ */
+ public static DiskFloppy createInstance( LibvirtXmlNode xmlNode )
+ {
+ return DiskFloppy.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a floppy disk device representing an existing Libvirt XML floppy disk device element.
+ *
+ * @param xmlNode existing Libvirt XML floppy disk device element.
+ * @return floppy disk device instance.
+ */
+ public static DiskFloppy newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new DiskFloppy( xmlNode );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/DiskStorage.java b/src/main/java/org/openslx/libvirt/domain/device/DiskStorage.java
new file mode 100644
index 0000000..7fca789
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/DiskStorage.java
@@ -0,0 +1,54 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A storage (HDD, SSD, ...) disk device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class DiskStorage extends Disk
+{
+ /**
+ * Creates an empty storage disk device.
+ */
+ public DiskStorage()
+ {
+ super();
+ }
+
+ /**
+ * Creates a storage disk device representing an existing Libvirt XML storage disk device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML storage disk device element.
+ */
+ public DiskStorage( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Creates a non-existent storage disk device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created storage disk device instance.
+ */
+ public static DiskStorage createInstance( LibvirtXmlNode xmlNode )
+ {
+ return DiskStorage.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a storage disk device representing an existing Libvirt XML storage disk device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML storage disk device element.
+ * @return storage disk device instance.
+ */
+ public static DiskStorage newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new DiskStorage( xmlNode );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/Graphics.java b/src/main/java/org/openslx/libvirt/domain/device/Graphics.java
new file mode 100644
index 0000000..314dba2
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/Graphics.java
@@ -0,0 +1,138 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A graphics (display) device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class Graphics extends Device
+{
+ /**
+ * Creates an empty graphics device.
+ */
+ public Graphics()
+ {
+ super();
+ }
+
+ /**
+ * Creates a graphics device representing an existing Libvirt XML graphics device element.
+ *
+ * @param xmlNode existing Libvirt XML graphics device element.
+ */
+ public Graphics( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Creates a non-existent graphics device as Libvirt XML device element.
+ *
+ * @param graphics graphics device that is created.
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created graphics device instance.
+ */
+ public static Graphics createInstance( Graphics graphics, LibvirtXmlNode xmlNode )
+ {
+ Graphics addedGraphics = null;
+
+ if ( graphics instanceof GraphicsSdl ) {
+ xmlNode.setXmlElementAttributeValue( "type", Type.SDL.toString() );
+ addedGraphics = GraphicsSdl.createInstance( xmlNode );
+ } else if ( graphics instanceof GraphicsSpice ) {
+ xmlNode.setXmlElementAttributeValue( "type", Type.SPICE.toString() );
+ addedGraphics = GraphicsSpice.createInstance( xmlNode );
+ } else if ( graphics instanceof GraphicsVnc ) {
+ xmlNode.setXmlElementAttributeValue( "type", Type.VNC.toString() );
+ addedGraphics = GraphicsVnc.createInstance( xmlNode );
+ }
+
+ return addedGraphics;
+ }
+
+ /**
+ * Creates a graphics device representing an existing Libvirt XML graphics device element.
+ *
+ * @param xmlNode existing Libvirt XML graphics device element.
+ * @return graphics device instance.
+ */
+ public static Graphics newInstance( LibvirtXmlNode xmlNode )
+ {
+ Graphics deviceGraphics = null;
+ Type type = Type.fromString( xmlNode.getXmlElementAttributeValue( "type" ) );
+
+ if ( type == null ) {
+ return null;
+ }
+
+ switch ( type ) {
+ case SDL:
+ deviceGraphics = GraphicsSdl.newInstance( xmlNode );
+ break;
+ case SPICE:
+ deviceGraphics = GraphicsSpice.newInstance( xmlNode );
+ break;
+ case VNC:
+ deviceGraphics = GraphicsVnc.newInstance( xmlNode );
+ break;
+ }
+
+ return deviceGraphics;
+ }
+
+ /**
+ * Type of graphics device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ enum Type
+ {
+ // @formatter:off
+ SDL ( "sdl" ),
+ SPICE( "spice" ),
+ VNC ( "vnc" );
+ // @formatter:on
+
+ /**
+ * Name of graphics device type.
+ */
+ private String type = null;
+
+ /**
+ * Creates graphics device type.
+ *
+ * @param type valid name of the graphics device type in a Libvirt domain XML document.
+ */
+ Type( String type )
+ {
+ this.type = type;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.type;
+ }
+
+ /**
+ * Creates graphics device type from its name with error check.
+ *
+ * @param type name of the graphics device type in a Libvirt domain XML document.
+ * @return valid graphics device type.
+ */
+ public static Type fromString( String type )
+ {
+ for ( Type t : Type.values() ) {
+ if ( t.type.equalsIgnoreCase( type ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/GraphicsSdl.java b/src/main/java/org/openslx/libvirt/domain/device/GraphicsSdl.java
new file mode 100644
index 0000000..c77f56d
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/GraphicsSdl.java
@@ -0,0 +1,54 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A graphics SDL device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class GraphicsSdl extends Graphics
+{
+ /**
+ * Creates an empty graphics SDL device.
+ */
+ public GraphicsSdl()
+ {
+ super();
+ }
+
+ /**
+ * Creates a graphics SDL device representing an existing Libvirt XML graphics SDL device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML graphics SDL device element.
+ */
+ public GraphicsSdl( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Creates a non-existent graphics SDL device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created graphics SDL device instance.
+ */
+ public static GraphicsSdl createInstance( LibvirtXmlNode xmlNode )
+ {
+ return GraphicsSdl.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a graphics SDL device representing an existing Libvirt XML graphics SDL device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML graphics SDL device element.
+ * @return graphics SDL device instance.
+ */
+ public static GraphicsSdl newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new GraphicsSdl( xmlNode );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/GraphicsSpice.java b/src/main/java/org/openslx/libvirt/domain/device/GraphicsSpice.java
new file mode 100644
index 0000000..f087296
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/GraphicsSpice.java
@@ -0,0 +1,74 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A graphics SPICE device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class GraphicsSpice extends Graphics
+{
+ /**
+ * Creates an empty graphics SPICE device.
+ */
+ public GraphicsSpice()
+ {
+ super();
+ }
+
+ /**
+ * Creates a graphics SPICE device representing an existing Libvirt XML graphics SPICE device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML graphics SPCIE device element.
+ */
+ public GraphicsSpice( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Returns the state whether OpenGL hardware acceleration is enabled or not.
+ *
+ * @return tate whether OpenGL hardware acceleration is enabled or not.
+ */
+ public boolean isOpenGlEnabled()
+ {
+ return this.getXmlElementAttributeValueAsBool( "gl", "enable" );
+ }
+
+ /**
+ * Sets the state whether OpenGL hardware acceleration is enabled or not.
+ *
+ * @param enabled state whether OpenGL hardware acceleration is enabled or not.
+ */
+ public void setOpenGl( boolean enabled )
+ {
+ this.setXmlElementAttributeValue( "gl", "enable", enabled );
+ }
+
+ /**
+ * Creates a non-existent graphics SPICE device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created graphics SPICE device instance.
+ */
+ public static GraphicsSpice createInstance( LibvirtXmlNode xmlNode )
+ {
+ return GraphicsSpice.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a graphics SPICE device representing an existing Libvirt XML graphics SPICE device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML graphics SPICE device element.
+ * @return graphics SPICE device instance.
+ */
+ public static GraphicsSpice newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new GraphicsSpice( xmlNode );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/GraphicsVnc.java b/src/main/java/org/openslx/libvirt/domain/device/GraphicsVnc.java
new file mode 100644
index 0000000..f595699
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/GraphicsVnc.java
@@ -0,0 +1,54 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A graphics VNC device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class GraphicsVnc extends Graphics
+{
+ /**
+ * Creates an empty graphics VNC device.
+ */
+ public GraphicsVnc()
+ {
+ super();
+ }
+
+ /**
+ * Creates a graphics VNC device representing an existing Libvirt XML graphics VNC device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML graphics VNC device element.
+ */
+ public GraphicsVnc( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Creates a non-existent graphics VNC device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created graphics VNC device instance.
+ */
+ public static GraphicsVnc createInstance( LibvirtXmlNode xmlNode )
+ {
+ return GraphicsVnc.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a graphics VNC device representing an existing Libvirt XML graphics VNC device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML graphics VNC device element.
+ * @return graphics VNC device instance.
+ */
+ public static GraphicsVnc newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new GraphicsVnc( xmlNode );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/Hostdev.java b/src/main/java/org/openslx/libvirt/domain/device/Hostdev.java
new file mode 100644
index 0000000..cb09099
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/Hostdev.java
@@ -0,0 +1,139 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A hostdev device node in a Libvirt domain XML document for PCI, USB, ... passthrough.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class Hostdev extends Device
+{
+ /**
+ * Creates an empty hostdev device.
+ */
+ public Hostdev()
+ {
+ super();
+ }
+
+ /**
+ * Creates a hostdev device representing an existing Libvirt XML hostdev device element.
+ *
+ * @param xmlNode existing Libvirt XML hostdev device element.
+ */
+ public Hostdev( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Removes boot oder entry of the hostdev device.
+ */
+ public void removeBootOrder()
+ {
+ this.removeXmlElement( "boot" );
+ }
+
+ /**
+ * Creates a non-existent hostdev device as Libvirt XML device element.
+ *
+ * @param hostdev hostdev device that is created.
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created hostdev device instance.
+ */
+ public static Hostdev createInstance( Hostdev hostdev, LibvirtXmlNode xmlNode )
+ {
+ Hostdev addedHostdev = null;
+
+ if ( hostdev instanceof HostdevPci ) {
+ xmlNode.setXmlElementAttributeValue( "device", Type.PCI.toString() );
+ addedHostdev = HostdevPci.createInstance( xmlNode );
+ } else if ( hostdev instanceof HostdevUsb ) {
+ xmlNode.setXmlElementAttributeValue( "device", Type.USB.toString() );
+ addedHostdev = HostdevUsb.createInstance( xmlNode );
+ }
+
+ return addedHostdev;
+ }
+
+ /**
+ * Creates a hostdev device representing an existing Libvirt XML hostdev device element.
+ *
+ * @param xmlNode existing Libvirt XML hostdev device element.
+ * @return hostdev device instance.
+ */
+ public static Hostdev newInstance( LibvirtXmlNode xmlNode )
+ {
+ Hostdev deviceHostdev = null;
+ Type type = Type.fromString( xmlNode.getXmlElementAttributeValue( "type" ) );
+
+ if ( type == null ) {
+ return null;
+ }
+
+ switch ( type ) {
+ case PCI:
+ deviceHostdev = HostdevPci.newInstance( xmlNode );
+ break;
+ case USB:
+ deviceHostdev = HostdevUsb.newInstance( xmlNode );
+ break;
+ }
+
+ return deviceHostdev;
+ }
+
+ /**
+ * Type of hostdev device subsystem passthrough.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ enum Type
+ {
+ // @formatter:off
+ PCI( "pci" ),
+ USB( "usb" );
+ // @formatter:on
+
+ /**
+ * Name of the hostdev device type.
+ */
+ private String type = null;
+
+ /**
+ * Creates hostdev device type.
+ *
+ * @param type valid name of the hostdev device type in a Libvirt domain XML document.
+ */
+ Type( String type )
+ {
+ this.type = type;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.type;
+ }
+
+ /**
+ * Creates hostdev device type from its name with error check.
+ *
+ * @param type name of the hostdev device storage in a Libvirt domain XML document.
+ * @return valid hostdev device type.
+ */
+ public static Type fromString( String type )
+ {
+ for ( Type t : Type.values() ) {
+ if ( t.type.equalsIgnoreCase( type ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/HostdevPci.java b/src/main/java/org/openslx/libvirt/domain/device/HostdevPci.java
new file mode 100644
index 0000000..3b26fb0
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/HostdevPci.java
@@ -0,0 +1,79 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A hostdev PCI device node in a Libvirt domain XML document for PCI passthrough.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class HostdevPci extends Hostdev
+{
+ /**
+ * Creates an empty hostdev PCI device.
+ */
+ public HostdevPci()
+ {
+ super();
+ }
+
+ /**
+ * Creates a hostdev PCI device representing an existing Libvirt XML hostdev PCI device element.
+ *
+ * @param xmlNode existing Libvirt XML hostdev PCI device element.
+ */
+ public HostdevPci( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Checks if PCI hostdev device is managed.
+ *
+ * If {@link #isManaged()} returns <code>true</code> the hostdev PCI device is detached from the
+ * host before being passed on to the guest and reattached to the host after the guest exits.
+ *
+ * @return state whether PCI hostdev device is managed.
+ */
+ public boolean isManaged()
+ {
+ return this.getXmlElementAttributeValueAsBool( "managed" );
+ }
+
+ /**
+ * Sets state whether PCI hostdev device is managed.
+ *
+ * If the <code>managed</code> parameter is set to <code>true</code> the PCI hostdev device is
+ * detached from the host before being passed on to the guest and reattached to the host after
+ * the guest exits.
+ *
+ * @return state whether PCI hostdev device is managed.
+ */
+ public void setManaged( boolean managed )
+ {
+ this.setXmlElementAttributeValue( "managed", managed );
+ }
+
+ /**
+ * Creates a non-existent hostdev PCI device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created hostdev PCI device instance.
+ */
+ public static HostdevPci createInstance( LibvirtXmlNode xmlNode )
+ {
+ return HostdevPci.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a hostdev PCI device representing an existing Libvirt XML hostdev PCI device element.
+ *
+ * @param xmlNode existing Libvirt XML hostdev PCI device element.
+ * @return hostdev PCI device instance.
+ */
+ public static HostdevPci newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new HostdevPci( xmlNode );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/HostdevUsb.java b/src/main/java/org/openslx/libvirt/domain/device/HostdevUsb.java
new file mode 100644
index 0000000..e1fcc0c
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/HostdevUsb.java
@@ -0,0 +1,52 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A hostdev USB device node in a Libvirt domain XML document for USB passthrough.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class HostdevUsb extends Hostdev
+{
+ /**
+ * Creates an empty hostdev USB device.
+ */
+ public HostdevUsb()
+ {
+ super();
+ }
+
+ /**
+ * Creates a hostdev USB device representing an existing Libvirt XML hostdev USB device element.
+ *
+ * @param xmlNode existing Libvirt XML hostdev USB device element.
+ */
+ public HostdevUsb( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Creates a non-existent hostdev USB device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created hostdev USB device instance.
+ */
+ public static HostdevUsb createInstance( LibvirtXmlNode xmlNode )
+ {
+ return HostdevUsb.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a hostdev USB device representing an existing Libvirt XML hostdev USB device element.
+ *
+ * @param xmlNode existing Libvirt XML hostdev USB device element.
+ * @return hostdev USB device instance.
+ */
+ public static HostdevUsb newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new HostdevUsb( xmlNode );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/Interface.java b/src/main/java/org/openslx/libvirt/domain/device/Interface.java
new file mode 100644
index 0000000..b09c7da
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/Interface.java
@@ -0,0 +1,316 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A network interface device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class Interface extends Device
+{
+ /**
+ * Creates an empty network device.
+ */
+ public Interface()
+ {
+ super();
+ }
+
+ /**
+ * Creates a network device representing an existing Libvirt XML network interface device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML network interface device element.
+ */
+ public Interface( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Returns hardware model of the network device.
+ *
+ * @return hardware model of the network device.
+ */
+ public Model getModel()
+ {
+ String model = this.getXmlElementAttributeValue( "model", "type" );
+ return Model.fromString( model );
+ }
+
+ /**
+ * Sets hardware model for the network device.
+ *
+ * @param model hardware model for the network device.
+ */
+ public void setModel( Model model )
+ {
+ this.setXmlElementAttributeValue( "model", "type", model.toString() );
+ }
+
+ /**
+ * Returns type of the network device.
+ *
+ * @return type of the network device.
+ */
+ public Type getType()
+ {
+ return Type.fromString( this.getXmlElementAttributeValue( "type" ) );
+ }
+
+ /**
+ * Sets type of the network device.
+ *
+ * @return type of the network device.
+ */
+ public void setType(Type type)
+ {
+ String source = this.getSource();
+
+ // change type and set source again
+ this.setXmlElementAttributeValue( "type", type.toString() );
+ this.setSource( source );
+ }
+
+ /**
+ * Returns the source of the network device.
+ *
+ * @return source of the network device.
+ */
+ public String getSource()
+ {
+ Type type = this.getType();
+ String source = null;
+
+ switch ( type ) {
+ case BRIDGE:
+ source = this.getXmlElementAttributeValue( "source", "bridge" );
+ break;
+ case NETWORK:
+ source = this.getXmlElementAttributeValue( "source", "network" );
+ break;
+ }
+
+ return source;
+ }
+
+ /**
+ * Sets the source for the network device.
+ *
+ * @param source for the network device.
+ */
+ public void setSource( String source )
+ {
+ Type type = this.getType();
+
+ // remove all attributes from sub-element 'source'
+ this.removeXmlElementAttributes( "source" );
+
+ switch ( type ) {
+ case BRIDGE:
+ this.setXmlElementAttributeValue( "source", "bridge", source );
+ break;
+ case NETWORK:
+ this.setXmlElementAttributeValue( "source", "network", source );
+ break;
+ }
+ }
+
+ /**
+ * Removes boot oder entry of the network interface device.
+ */
+ public void removeBootOrder()
+ {
+ this.removeXmlElement( "boot" );
+ }
+
+ /**
+ * Removes network source of the network interface device.
+ */
+ public void removeSource()
+ {
+ this.removeXmlElement( "source" );
+ }
+
+ /**
+ * Creates a non-existent network interface device as Libvirt XML device element.
+ *
+ * @param iface network device that is created.
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created network device instance.
+ */
+ public static Interface createInstance( Interface iface, LibvirtXmlNode xmlNode )
+ {
+ Interface addedInterface = null;
+
+ if ( iface instanceof InterfaceBridge ) {
+ xmlNode.setXmlElementAttributeValue( "type", Type.BRIDGE.toString() );
+ addedInterface = InterfaceBridge.createInstance( xmlNode );
+ } else if ( iface instanceof InterfaceNetwork ) {
+ xmlNode.setXmlElementAttributeValue( "type", Type.NETWORK.toString() );
+ addedInterface = InterfaceNetwork.createInstance( xmlNode );
+ }
+
+ return addedInterface;
+ }
+
+ /**
+ * Creates a network interface device representing an existing Libvirt XML network interface
+ * device element.
+ *
+ * @param xmlNode existing Libvirt XML network interface device element.
+ * @return network interface device instance.
+ */
+ public static Interface newInstance( LibvirtXmlNode xmlNode )
+ {
+ Interface deviceInterface = null;
+ Type type = Type.fromString( xmlNode.getXmlElementAttributeValue( "type" ) );
+
+ if ( type == null ) {
+ return null;
+ }
+
+ switch ( type ) {
+ case BRIDGE:
+ deviceInterface = InterfaceBridge.newInstance( xmlNode );
+ break;
+ case NETWORK:
+ deviceInterface = InterfaceNetwork.newInstance( xmlNode );
+ break;
+ }
+
+ return deviceInterface;
+ }
+
+ /**
+ * Type of network interface device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ public enum Type
+ {
+ // @formatter:off
+ BRIDGE ( "bridge" ),
+ NETWORK( "network" );
+ // @formatter:on
+
+ /**
+ * Name of the network interface device type.
+ */
+ private String type = null;
+
+ /**
+ * Creates network interface device type.
+ *
+ * @param type valid name of the network interface device type in a Libvirt domain XML
+ * document.
+ */
+ Type( String type )
+ {
+ this.type = type;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.type;
+ }
+
+ /**
+ * Creates network interface device type from its name with error check.
+ *
+ * @param type name of the network interface device type in a Libvirt domain XML document.
+ * @return valid network interface device type.
+ */
+ public static Type fromString( String type )
+ {
+ for ( Type t : Type.values() ) {
+ if ( t.type.equalsIgnoreCase( type ) ) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Model of network interface device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ public enum Model
+ {
+ // @formatter:off
+ E1000 ( "e1000" ),
+ E1000_82544GC ( "e1000-82544gc" ),
+ E1000_82545EM ( "e1000-82545em" ),
+ E1000E ( "e1000e" ),
+ I82550 ( "i82550" ),
+ I82551 ( "i82551" ),
+ I82557A ( "i82557a" ),
+ I82557B ( "i82557b" ),
+ I82557C ( "i82557c" ),
+ I82558A ( "i82558a" ),
+ I82558B ( "i82558b" ),
+ I82559A ( "i82559a" ),
+ I82559B ( "i82559b" ),
+ I82559C ( "i82559c" ),
+ I82559ER ( "i82559er" ),
+ I82562 ( "i82562" ),
+ I82801 ( "i82801" ),
+ NE2K_PCI ( "ne2k_pci" ),
+ PCNET ( "pcnet" ),
+ RTL8139 ( "rtl8139" ),
+ TULIP ( "tulip" ),
+ VIRTIO ( "virtio" ),
+ VIRTIO_NET_PCI ( "virtio-net-pci" ),
+ VIRTIO_NET_PCI_NON_TRANSITIONAL( "virtio-net-pci-non-transitional" ),
+ VIRTIO_NET_PCI_TRANSITIONAL ( "virtio-net-pci-transitional" ),
+ VMXNET3 ( "vmxnet3" );
+ // @formatter:on
+
+ /**
+ * Name of the network interface device model.
+ */
+ private String model = null;
+
+ /**
+ * Creates network interface device model.
+ *
+ * @param type valid name of the network interface device model in a Libvirt domain XML
+ * document.
+ */
+ Model( String model )
+ {
+ this.model = model;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.model;
+ }
+
+ /**
+ * Creates network interface device model from its name with error check.
+ *
+ * @param type name of the network interface device model in a Libvirt domain XML document.
+ * @return valid network interface device model.
+ */
+ public static Model fromString( String model )
+ {
+ for ( Model m : Model.values() ) {
+ if ( m.model.equalsIgnoreCase( model ) ) {
+ return m;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/InterfaceBridge.java b/src/main/java/org/openslx/libvirt/domain/device/InterfaceBridge.java
new file mode 100644
index 0000000..02eabb0
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/InterfaceBridge.java
@@ -0,0 +1,54 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A network bridge interface device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class InterfaceBridge extends Interface
+{
+ /**
+ * Creates an empty network bridge interface device.
+ */
+ public InterfaceBridge()
+ {
+ super();
+ }
+
+ /**
+ * Creates a network bridge interface device representing an existing Libvirt XML network bridge
+ * interface device element.
+ *
+ * @param xmlNode existing Libvirt XML network bridge interface device element.
+ */
+ public InterfaceBridge( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Creates a non-existent network bridge interface device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created network bridge interface device instance.
+ */
+ public static InterfaceBridge createInstance( LibvirtXmlNode xmlNode )
+ {
+ return InterfaceBridge.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a network bridge interface device representing an existing Libvirt XML network bridge
+ * interface device element.
+ *
+ * @param xmlNode existing Libvirt XML network bridge interface device element.
+ * @return network bridge interface device instance.
+ */
+ public static InterfaceBridge newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new InterfaceBridge( xmlNode );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/InterfaceNetwork.java b/src/main/java/org/openslx/libvirt/domain/device/InterfaceNetwork.java
new file mode 100644
index 0000000..ae1fd40
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/InterfaceNetwork.java
@@ -0,0 +1,54 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A network interface device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class InterfaceNetwork extends Interface
+{
+ /**
+ * Creates an empty network interface device.
+ */
+ public InterfaceNetwork()
+ {
+ super();
+ }
+
+ /**
+ * Creates a network interface device representing an existing Libvirt XML network interface
+ * device element.
+ *
+ * @param xmlNode existing Libvirt XML network interface device element.
+ */
+ public InterfaceNetwork( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Creates a non-existent network interface device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created network interface device device instance.
+ */
+ public static InterfaceNetwork createInstance( LibvirtXmlNode xmlNode )
+ {
+ return InterfaceNetwork.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a network interface device representing an existing Libvirt XML network interface
+ * device element.
+ *
+ * @param xmlNode existing Libvirt XML network interface device element.
+ * @return network interface device instance.
+ */
+ public static InterfaceNetwork newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new InterfaceNetwork( xmlNode );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/Sound.java b/src/main/java/org/openslx/libvirt/domain/device/Sound.java
new file mode 100644
index 0000000..e424ed4
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/Sound.java
@@ -0,0 +1,128 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A sound device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class Sound extends Device
+{
+ /**
+ * Creates an empty sound device.
+ */
+ public Sound()
+ {
+ super();
+ }
+
+ /**
+ * Creates a sound device representing an existing Libvirt XML sound device element.
+ *
+ * @param xmlNode existing Libvirt XML sound device element.
+ */
+ public Sound( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Returns hardware model of the sound device.
+ *
+ * @return hardware model of the sound device.
+ */
+ public Model getModel()
+ {
+ String model = this.getXmlElementAttributeValue( "model" );
+ return Model.fromString( model );
+ }
+
+ /**
+ * Sets hardware model for the sound device.
+ *
+ * @param model hardware model for the sound device.
+ */
+ public void setModel( Model model )
+ {
+ this.setXmlElementAttributeValue( "model", model.toString() );
+ }
+
+ /**
+ * Creates a non-existent sound device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created sound device instance.
+ */
+ public static Sound createInstance( LibvirtXmlNode xmlNode )
+ {
+ return Sound.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a sound device representing an existing Libvirt XML sound device element.
+ *
+ * @param xmlNode existing Libvirt XML sound device element.
+ * @return sound device instance.
+ */
+ public static Sound newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new Sound( xmlNode );
+ }
+
+ /**
+ * Model of sound device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ public enum Model
+ {
+ // @formatter:off
+ AC97 ( "ac97" ),
+ ES1370( "es1370" ),
+ ICH6 ( "ich6" ),
+ ICH9 ( "ich9" ),
+ SB16 ( "sb16" );
+ // @formatter:on
+
+ /**
+ * Name of the sound device model.
+ */
+ private String model;
+
+ /**
+ * Creates sound device model.
+ *
+ * @param type valid name of the sound device model in a Libvirt domain XML document.
+ */
+ Model( String model )
+ {
+ this.model = model;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.model;
+ }
+
+ /**
+ * Creates sound device model from its name with error check.
+ *
+ * @param type name of the sound device model in a Libvirt domain XML document.
+ * @return valid sound device model.
+ */
+ public static Model fromString( String model )
+ {
+ for ( Model m : Model.values() ) {
+ if ( m.model.equalsIgnoreCase( model ) ) {
+ return m;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/Video.java b/src/main/java/org/openslx/libvirt/domain/device/Video.java
new file mode 100644
index 0000000..e901b85
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/Video.java
@@ -0,0 +1,188 @@
+package org.openslx.libvirt.domain.device;
+
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A video (GPU) device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class Video extends Device
+{
+ /**
+ * Creates an empty video device.
+ */
+ public Video()
+ {
+ super();
+ }
+
+ /**
+ * Creates a video device representing an existing Libvirt XML video device element.
+ *
+ * @param xmlNode existing Libvirt XML video device element.
+ */
+ public Video( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Returns hardware model of the video device.
+ *
+ * @return hardware model of the video device.
+ */
+ public Model getModel()
+ {
+ String model = this.getXmlElementAttributeValue( "model", "type" );
+ return Model.fromString( model );
+ }
+
+ /**
+ * Sets hardware model for the video device.
+ *
+ * @param model hardware model for the video device.
+ */
+ public void setModel( Model model )
+ {
+ this.setXmlElementAttributeValue( "model", "type", model.toString() );
+ }
+
+ /**
+ * Checks whether 2D hardware video acceleration is turned on or off.
+ *
+ * @return state of 2D hardware video acceleration.
+ */
+ public boolean get2DAcceleration()
+ {
+ return this.getXmlElementAttributeValueAsBool( "model/acceleration", "accel2d" );
+ }
+
+ /**
+ * Turns 2D hardware video acceleration on or off.
+ *
+ * @param acceleration state of 2D hardware video acceleration.
+ */
+ public void set2DAcceleration( boolean acceleration )
+ {
+ Model model = this.getModel();
+
+ if ( model != null ) {
+ if ( model == Model.VIRTIO ) {
+ // only set acceleration on supported Virtio GPUs
+ this.setXmlElementAttributeValue( "model/acceleration", "accel2d", acceleration );
+ } else {
+ String errorMsg = new String(
+ "Video card model '" + model.toString() + "' does not support enabled 2D hardware acceleration." );
+ throw new IllegalArgumentException( errorMsg );
+ }
+ }
+ }
+
+ /**
+ * Checks whether 3D hardware video acceleration is turned on or off.
+ *
+ * @return state of 3D hardware video acceleration.
+ */
+ public boolean get3DAcceleration()
+ {
+ return this.getXmlElementAttributeValueAsBool( "model/acceleration", "accel3d" );
+ }
+
+ /**
+ * Turns 3D hardware video acceleration on or off.
+ *
+ * @param acceleration state of 3D hardware video acceleration.
+ */
+ public void set3DAcceleration( boolean acceleration )
+ {
+ Model model = this.getModel();
+
+ if ( model == Model.VIRTIO ) {
+ // only set acceleration on supported Virtio GPUs
+ this.setXmlElementAttributeValue( "model/acceleration", "accel3d", acceleration );
+ } else {
+ String errorMsg = new String(
+ "Video card model '" + model.toString() + "' does not support enabled 3D hardware acceleration." );
+ throw new IllegalArgumentException( errorMsg );
+ }
+ }
+
+ /**
+ * Creates a non-existent video device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created video device instance.
+ */
+ public static Video createInstance( LibvirtXmlNode xmlNode )
+ {
+ return Video.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a video device representing an existing Libvirt XML video device element.
+ *
+ * @param xmlNode existing Libvirt XML video device element.
+ * @return video device instance.
+ */
+ public static Video newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new Video( xmlNode );
+ }
+
+ /**
+ * Model of video device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ public enum Model
+ {
+ // @formatter:off
+ NONE ( "none" ),
+ QXL ( "qxl" ),
+ VGA ( "vga" ),
+ VMVGA ( "vmvga" ),
+ VIRTIO( "virtio" );
+ // @formatter:on
+
+ /**
+ * Name of the video device model.
+ */
+ private String model = null;
+
+ /**
+ * Creates video device model.
+ *
+ * @param type valid name of the video device model in a Libvirt domain XML document.
+ */
+ Model( String model )
+ {
+ this.model = model;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.model;
+ }
+
+ /**
+ * Creates video device model from its name with error check.
+ *
+ * @param type name of the video device model in a Libvirt domain XML document.
+ * @return valid video device model.
+ */
+ public static Model fromString( String model )
+ {
+ for ( Model m : Model.values() ) {
+ if ( m.model.equalsIgnoreCase( model ) ) {
+ return m;
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlCreatable.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlCreatable.java
new file mode 100644
index 0000000..e799ace
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlCreatable.java
@@ -0,0 +1,26 @@
+package org.openslx.libvirt.xml;
+
+import org.w3c.dom.Node;
+
+/**
+ * Serializability of a Libvirt XML object from/to its XML representation.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public interface LibvirtXmlCreatable
+{
+ /**
+ * Serializing an object from its XML representation.
+ *
+ * @param xmlNode The object's XML representation.
+ */
+ void fromXmlNode( Node xmlNode );
+
+ /**
+ * Serializing the object to its XML representation.
+ *
+ * @return XML representation of the object.
+ */
+ Node toXmlNode();
+}
diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlDocument.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlDocument.java
new file mode 100644
index 0000000..8fe642b
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlDocument.java
@@ -0,0 +1,373 @@
+package org.openslx.libvirt.xml;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.commons.io.IOUtils;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * A generic representation of a Libvirt XML file.
+ *
+ * @implNote Base class to derive the representation of specific Libvirt XML files.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public abstract class LibvirtXmlDocument implements LibvirtXmlSerializable, LibvirtXmlValidatable
+{
+ /**
+ * Document builder to parse Libvirt XML document from file.
+ */
+ private DocumentBuilder domBuilder = null;
+
+ /**
+ * Representation of a Libvirt XML document.
+ */
+ private Document xmlDocument = null;
+
+ /**
+ * XML transformer to transform Libvirt XML document to a file.
+ */
+ private Transformer xmlTransformer = null;
+
+ /**
+ * XML root node of the Libvirt XML document.
+ */
+ private LibvirtXmlNode rootXmlNode = null;
+
+ /**
+ * RNG schema validator to validate the Libvirt XML document content.
+ */
+ private LibvirtXmlSchemaValidator rngValidator = null;
+
+ /**
+ * Creates and initializes XML context to create and transform a Libvirt XML file from/to a file.
+ *
+ * @param rngSchema RNG schema to validate the Libvirt XML document content.
+ *
+ * @throws LibvirtXmlDocumentException error occured during setup of the XML context to read and
+ * write from/to a Libvirt XML file.
+ */
+ private void createXmlContext( InputStream rngSchema ) throws LibvirtXmlDocumentException
+ {
+ // used for XML input
+ try {
+ DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
+ domFactory.setIgnoringElementContentWhitespace( true );
+ domFactory.setNamespaceAware( true );
+ this.domBuilder = domFactory.newDocumentBuilder();
+ } catch ( ParserConfigurationException e ) {
+ String errorMsg = new String( "Setting up XML context for reading from the Libvirt XML document failed." );
+ throw new LibvirtXmlDocumentException( errorMsg );
+ }
+
+ // used for XML output
+ try {
+ // use hack to load specific transformer factory implementation for XSLT
+ System.setProperty( TransformerFactory.class.getName(),
+ "org.apache.xalan.processor.TransformerFactoryImpl" );
+
+ // create XML transformer factory to create XML transformer with specific indentation
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+
+ // create XML transformer and apply settings for output XML transformation
+ InputStream xslOutputSchemaStream = LibvirtXmlResources.getLibvirtXsl( "xml-output-transformation.xsl" );
+ StreamSource xslOutputSchema = new StreamSource( xslOutputSchemaStream );
+ this.xmlTransformer = transformerFactory.newTransformer( xslOutputSchema );
+ } catch ( TransformerConfigurationException e ) {
+ String errorMsg = new String( "Setting up XML context for writing to the Libvirt XML document failed." );
+ throw new LibvirtXmlDocumentException( errorMsg );
+ }
+
+ // used for XML validation with RNG schema files
+ if ( rngSchema != null ) {
+ try {
+ this.rngValidator = new LibvirtXmlSchemaValidator( rngSchema );
+ } catch ( SAXException e ) {
+ String errorMsg = new String( "Setting up XML context for validating to the Libvirt XML document failed." );
+ e.printStackTrace();
+ throw new LibvirtXmlDocumentException( errorMsg );
+ }
+ }
+ }
+
+ /**
+ * Creates a Libvirt XML document from a given XML content.
+ *
+ * @param xml XML content as {@link String}.
+ *
+ * @throws LibvirtXmlDocumentException creation of XML context failed.
+ * @throws LibvirtXmlSerializationException serialization of the XML content failed.
+ * @throws LibvirtXmlValidationException XML content is not a valid Libvirt XML.
+ */
+ public LibvirtXmlDocument( String xml )
+ throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException
+ {
+ this( xml, null );
+ }
+
+ /**
+ * Creates a Libvirt XML document from a given XML content.
+ *
+ * @param xml XML content as {@link String}.
+ * @param rngSchema RNG schema to validate XML content.
+ *
+ * @throws LibvirtXmlDocumentException creation of XML context failed.
+ * @throws LibvirtXmlSerializationException serialization of the XML content failed.
+ * @throws LibvirtXmlValidationException XML content is not a valid Libvirt XML.
+ */
+ public LibvirtXmlDocument( String xml, InputStream rngSchema )
+ throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException
+ {
+ this.createXmlContext( rngSchema );
+ this.fromXml( xml );
+ this.validateXml();
+ }
+
+ /**
+ * Creates a Libvirt XML document from a given XML content.
+ *
+ * @param xml XML content as {@link File}.
+ *
+ * @throws LibvirtXmlDocumentException creation of XML context failed.
+ * @throws LibvirtXmlSerializationException serialization of the XML content failed.
+ * @throws LibvirtXmlValidationException XML content is not a valid Libvirt XML.
+ */
+ public LibvirtXmlDocument( File xml )
+ throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException
+ {
+ this( xml, null );
+ }
+
+ /**
+ * Creates a Libvirt XML document from a given XML content.
+ *
+ * @param xml XML content as {@link File}.
+ * @param rngSchema RNG schema to validate XML content.
+ *
+ * @throws LibvirtXmlDocumentException creation of XML context failed.
+ * @throws LibvirtXmlSerializationException serialization of the XML content failed.
+ * @throws LibvirtXmlValidationException XML content is not a valid Libvirt XML.
+ */
+ public LibvirtXmlDocument( File xml, InputStream rngSchema )
+ throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException
+ {
+ this.createXmlContext( rngSchema );
+ this.fromXml( xml );
+ this.validateXml();
+ }
+
+ /**
+ * Creates a Libvirt XML document from a given XML content.
+ *
+ * @param xml XML content as {@link InputStream}.
+ *
+ * @throws LibvirtXmlDocumentException creation of XML context failed.
+ * @throws LibvirtXmlSerializationException serialization of the XML content failed.
+ * @throws LibvirtXmlValidationException XML content is not a valid Libvirt XML.
+ */
+ public LibvirtXmlDocument( InputStream xml )
+ throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException
+ {
+ this( xml, null );
+ }
+
+ /**
+ * Creates a Libvirt XML document from a given XML content.
+ *
+ * @param xml XML content as {@link InputStream}.
+ * @param rngSchema RNG schema to validate XML content.
+ *
+ * @throws LibvirtXmlDocumentException creation of XML context failed.
+ * @throws LibvirtXmlSerializationException serialization of the XML content failed.
+ * @throws LibvirtXmlValidationException XML content is not a valid Libvirt XML.
+ */
+ public LibvirtXmlDocument( InputStream xml, InputStream rngSchema )
+ throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException
+ {
+ this.createXmlContext( rngSchema );
+ this.fromXml( xml );
+ this.validateXml();
+ }
+
+ /**
+ * Creates a Libvirt XML document from a given XML content.
+ *
+ * @param xml XML content as {@link InputSource}.
+ *
+ * @throws LibvirtXmlDocumentException creation of XML context failed.
+ * @throws LibvirtXmlSerializationException serialization of the XML content failed.
+ * @throws LibvirtXmlValidationException XML content is not a valid Libvirt XML.
+ */
+ public LibvirtXmlDocument( InputSource xml )
+ throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException
+ {
+ this( xml, null );
+ }
+
+ /**
+ * Creates a Libvirt XML document from a given XML content.
+ *
+ * @param xml XML content as {@link InputSource}.
+ * @param rngSchema RNG schema to validate XML content.
+ *
+ * @throws LibvirtXmlDocumentException creation of XML context failed.
+ * @throws LibvirtXmlSerializationException serialization of the XML content failed.
+ * @throws LibvirtXmlValidationException XML content is not a valid Libvirt XML.
+ */
+ public LibvirtXmlDocument( InputSource xml, InputStream rngSchema )
+ throws LibvirtXmlDocumentException, LibvirtXmlSerializationException, LibvirtXmlValidationException
+ {
+ this.createXmlContext( rngSchema );
+ this.fromXml( xml );
+ this.validateXml();
+ }
+
+ /**
+ * Returns the XML root node of the Libvirt XML document.
+ *
+ * @return root node of the Libvirt XML document.
+ */
+ public LibvirtXmlNode getRootXmlNode()
+ {
+ return this.rootXmlNode;
+ }
+
+ @Override
+ public void fromXml( String xml ) throws LibvirtXmlSerializationException
+ {
+ try {
+ this.xmlDocument = this.domBuilder.parse( xml );
+ this.xmlDocument.getDocumentElement().normalize();
+ } catch ( SAXException e ) {
+ e.printStackTrace();
+ } catch ( IOException e ) {
+ e.printStackTrace();
+ }
+
+ this.rootXmlNode = new LibvirtXmlNode( this.xmlDocument, this.xmlDocument.getDocumentElement() );
+ }
+
+ @Override
+ public void fromXml( File xml ) throws LibvirtXmlSerializationException
+ {
+ try {
+ this.xmlDocument = this.domBuilder.parse( xml );
+ this.xmlDocument.getDocumentElement().normalize();
+ } catch ( SAXException e ) {
+ throw new LibvirtXmlSerializationException( e.getLocalizedMessage() );
+ } catch ( IOException e ) {
+ throw new LibvirtXmlSerializationException( e.getLocalizedMessage() );
+ }
+
+ this.rootXmlNode = new LibvirtXmlNode( this.xmlDocument, this.xmlDocument.getDocumentElement() );
+ }
+
+ @Override
+ public void fromXml( InputStream xml ) throws LibvirtXmlSerializationException
+ {
+ try {
+ this.xmlDocument = this.domBuilder.parse( xml );
+ this.xmlDocument.getDocumentElement().normalize();
+ } catch ( SAXException e ) {
+ throw new LibvirtXmlSerializationException( e.getLocalizedMessage() );
+ } catch ( IOException e ) {
+ throw new LibvirtXmlSerializationException( e.getLocalizedMessage() );
+ }
+
+ this.rootXmlNode = new LibvirtXmlNode( this.xmlDocument, this.xmlDocument.getDocumentElement() );
+ }
+
+ @Override
+ public void fromXml( InputSource xml ) throws LibvirtXmlSerializationException
+ {
+ try {
+ this.xmlDocument = this.domBuilder.parse( xml );
+ this.xmlDocument.getDocumentElement().normalize();
+ } catch ( SAXException e ) {
+ throw new LibvirtXmlSerializationException( e.getLocalizedMessage() );
+ } catch ( IOException e ) {
+ throw new LibvirtXmlSerializationException( e.getLocalizedMessage() );
+ }
+
+ this.rootXmlNode = new LibvirtXmlNode( this.xmlDocument, this.xmlDocument.getDocumentElement() );
+ }
+
+ @Override
+ @SuppressWarnings( "deprecation" )
+ public String toXml() throws LibvirtXmlSerializationException
+ {
+ StringWriter xmlWriter = null;
+ String xml = null;
+
+ try {
+ xmlWriter = new StringWriter();
+ DOMSource source = new DOMSource( this.xmlDocument );
+ StreamResult xmlString = new StreamResult( xmlWriter );
+ this.xmlTransformer.transform( source, xmlString );
+ xml = xmlWriter.toString() + System.lineSeparator();
+ xmlWriter.close();
+ } catch ( TransformerException | IOException e ) {
+ throw new LibvirtXmlSerializationException( e.getLocalizedMessage() );
+ } finally {
+ IOUtils.closeQuietly( xmlWriter );
+ }
+
+ return xml;
+ }
+
+ @Override
+ @SuppressWarnings( "deprecation" )
+ public void toXml( File xml ) throws LibvirtXmlSerializationException
+ {
+ FileWriter xmlWriter = null;
+
+ try {
+ xmlWriter = new FileWriter( xml );
+ DOMSource source = new DOMSource( this.xmlDocument );
+ StreamResult xmlStream = new StreamResult( xmlWriter );
+ this.xmlTransformer.transform( source, xmlStream );
+ xmlWriter.append( System.lineSeparator() );
+ xmlWriter.close();
+ } catch ( TransformerException | IOException e ) {
+ throw new LibvirtXmlSerializationException( e.getLocalizedMessage() );
+ } finally {
+ IOUtils.closeQuietly( xmlWriter );
+ }
+ }
+
+ @Override
+ public void validateXml() throws LibvirtXmlValidationException
+ {
+ if ( this.rngValidator != null ) {
+ this.rngValidator.validate( this.xmlDocument );
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ try {
+ return this.toXml();
+ } catch ( LibvirtXmlSerializationException e ) {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlDocumentException.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlDocumentException.java
new file mode 100644
index 0000000..f8605ed
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlDocumentException.java
@@ -0,0 +1,25 @@
+package org.openslx.libvirt.xml;
+
+/**
+ * An exception of a Libvirt XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class LibvirtXmlDocumentException extends Exception
+{
+ /**
+ * Version number for serialization.
+ */
+ private static final long serialVersionUID = -7423926322035713576L;
+
+ /**
+ * Creates an document exception including an error message.
+ *
+ * @param errorMsg message to describe a specific document error.
+ */
+ public LibvirtXmlDocumentException( String errorMsg )
+ {
+ super( errorMsg );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlEditable.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlEditable.java
new file mode 100644
index 0000000..1ddddce
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlEditable.java
@@ -0,0 +1,241 @@
+package org.openslx.libvirt.xml;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Editability of XML nodes based on {@link XPath} expressions.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public interface LibvirtXmlEditable
+{
+ /**
+ * Returns XML node selected by a {@link XPath} expression
+ *
+ * @param expression {@link XPath} expression to select XML node.
+ * @return selected XML node.
+ */
+ public Node getXmlNode( String expression );
+
+ /**
+ * Returns XML nodes selected by a {@link XPath} expression
+ *
+ * @param expression {@link XPath} expression to select XML nodes.
+ * @return selected XML nodes.
+ */
+ public NodeList getXmlNodes( String expression );
+
+ /**
+ * Return current XML root element.
+ *
+ * @return current XML root element.
+ */
+ public default Node getXmlElement()
+ {
+ return this.getXmlElement( null );
+ }
+
+ /**
+ * Returns XML element from selection by a {@link XPath} expression.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ * @return selected XML element.
+ */
+ public Node getXmlElement( String expression );
+
+ /**
+ * Sets an XML element selected by a {@link XPath} expression.
+ *
+ * If the XML element selected by the given {@link XPath} expression does not exists, the XML
+ * element will be created.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ */
+ public default void setXmlElement( String expression )
+ {
+ this.setXmlElement( expression, null );
+ }
+
+ /**
+ * Sets a XML element selected by a {@link XPath} expression and appends child XML node.
+ *
+ * If the XML element selected by the given {@link XPath} expression does not exists, the XML
+ * element will be created and the given XML child node is appended.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ * @param child XML node that will be appended to the selected XML element.
+ */
+ public void setXmlElement( String expression, Node child );
+
+ /**
+ * Returns the text value of a XML element selected by a {@link XPath} expression.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ * @return Text value of the selected XML element.
+ */
+ public String getXmlElementValue( String expression );
+
+ /**
+ * Sets the text value of a XML element selected by a {@link XPath} expression.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ * @param value text value to set selected XML element's text.
+ */
+ public void setXmlElementValue( String expression, String value );
+
+ /**
+ * Removes a XML element and all its childs selected by a {@link XPath} expression.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ */
+ public void removeXmlElement( String expression );
+
+ /**
+ * Removes all child elements of a XML element selected by a {@link XPath} expression.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ */
+ public void removeXmlElementChilds( String expression );
+
+ /**
+ * Returns the text value of a XML attribute from the current XML root element.
+ *
+ * @param attributeName name to select XML attribute of the current XML root element.
+ * @return attribute text of the XML attribute from the current XML root element as
+ * {@link String}.
+ */
+ public default String getXmlElementAttributeValue( String attributeName )
+ {
+ return this.getXmlElementAttributeValue( null, attributeName );
+ }
+
+ /**
+ * Returns the binary choice of a XML attribute from the current XML root element.
+ *
+ * If the text value of the XML attribute equals to <i>yes</i>, the returned {@link boolean}
+ * value is set to <i>true</i>. Otherwise, if the text value of the XML attribute equals to
+ * <i>no</i>, the returned {@link boolean} value is set to <i>false</i>.
+ *
+ * @param attributeName name to select XML attribute of the current XML root element.
+ * @return attribute value of the XML attribute from the current XML root element as
+ * {@link boolean}.
+ */
+ public default boolean getXmlElementAttributeValueAsBool( String attributeName )
+ {
+ return "yes".equals( this.getXmlElementAttributeValue( attributeName ) );
+ }
+
+ /**
+ * Returns the binary choice of a XML attribute from a XML element selected by a
+ * {@link XPath}expression.
+ *
+ * If the text value of the XML attribute equals to <i>yes</i>, the returned {@link boolean}
+ * value is set to <i>true</i>. Otherwise, if the text value of the XML attribute equals to
+ * <i>no</i>, the returned {@link boolean} value is set to <i>false</i>.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ * @param attributeName name to select XML attribute of the current XML root element.
+ * @return attribute value of the XML attribute from the current XML root element as
+ * {@link boolean}.
+ */
+ public default boolean getXmlElementAttributeValueAsBool( String expression, String attributeName )
+ {
+ return "yes".equals( this.getXmlElementAttributeValue( expression, attributeName ) );
+ }
+
+ /**
+ * Returns the text value of a XML attribute from a XML element selected by a
+ * {@link XPath}expression.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ * @param attributeName name to select XML attribute of the selected XML element.
+ * @return attribute text of the XML attribute from the selected XML element.
+ */
+ public String getXmlElementAttributeValue( String expression, String attributeName );
+
+ /**
+ * Sets the text value of a XML attribute from the current XML root element.
+ *
+ * @param attributeName name to select XML attribute of the current XML root element.
+ * @param value XML attribute value for the selected XML attribute from the current XML root
+ * element.
+ */
+ public default void setXmlElementAttributeValue( String attributeName, String value )
+ {
+ this.setXmlElementAttributeValue( null, attributeName, value );
+ }
+
+ /**
+ * Sets the binary choice value of a XML attribute from the current XML root element.
+ *
+ * If the binary choice value for the XML attribute equals to <i>true</i>, the text value of the
+ * selected XML attribute is set to <i>yes</i>. Otherwise, if the binary choice value for the
+ * selected XML attribute equals to <i>false</i>, the text value of the selected XML attribute is
+ * set to <i>no</i>.
+ *
+ * @param attributeName name to select XML attribute of the selected XML element.
+ * @param value binary choice value for the selected XML attribute from the selected XML element.
+ */
+ public default void setXmlElementAttributeValue( String attributeName, boolean value )
+ {
+ final String valueYesNo = value ? "yes" : "no";
+ this.setXmlElementAttributeValue( attributeName, valueYesNo );
+ }
+
+ /**
+ * Sets the binary choice value of a XML attribute from a XML element selected by a
+ * {@link XPath} expression.
+ *
+ * If the binary choice value for the XML attribute equals to <i>true</i>, the text value of the
+ * selected XML attribute is set to <i>yes</i>. Otherwise, if the binary choice value for the
+ * selected XML attribute equals to <i>false</i>, the text value of the selected XML attribute is
+ * set to <i>no</i>.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ * @param attributeName name to select XML attribute of the selected XML element.
+ * @param value binary choice value for the selected XML attribute from the selected XML element.
+ */
+ public default void setXmlElementAttributeValue( String expression, String attributeName, boolean value )
+ {
+ final String valueYesNo = value ? "yes" : "no";
+ this.setXmlElementAttributeValue( expression, attributeName, valueYesNo );
+ }
+
+ /**
+ * Sets the text value of a XML attribute from a XML element selected by a
+ * {@link XPath} expression.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ * @param attributeName name to select XML attribute of the selected XML element.
+ * @param value XML attribute value for the selected XML attribute from the selected XML element.
+ */
+ public void setXmlElementAttributeValue( String expression, String attributeName, String value );
+
+ /**
+ * Removes an XML attribute from the current XML root element.
+ *
+ * @param attributeName name of the attribute which should be deleted.
+ */
+ public default void removeXmlElementAttribute( String attributeName )
+ {
+ this.removeXmlElementAttribute( null, attributeName );
+ }
+
+ /**
+ * Removes an XML attribute from a XML element selected by a {@link XPath} expression.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ * @param attributeName name of the attribute which should be deleted.
+ */
+ public void removeXmlElementAttribute( String expression, String attributeName );
+
+ /**
+ * Removes all XML attributes from a XML element selected by a {@link XPath} expression.
+ *
+ * @param expression {@link XPath} expression to select XML element.
+ */
+ public void removeXmlElementAttributes( String expression );
+
+}
diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java
new file mode 100644
index 0000000..93e28de
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlNode.java
@@ -0,0 +1,356 @@
+package org.openslx.libvirt.xml;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * A representation of a XML node as part of a {@link LibvirtXMLDocument}.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class LibvirtXmlNode implements LibvirtXmlCreatable, LibvirtXmlEditable
+{
+ /**
+ * Separation character for internal {@link XPath} expressions.
+ */
+ private static final String XPATH_EXPRESSION_SEPARATOR = "/";
+
+ /**
+ * Current XML node selection character for internal {@link XPath} expressions.
+ */
+ private static final String XPATH_EXPRESSION_CURRENT_NODE = ".";
+
+ /**
+ * Factory to create {@link XPath} objects.
+ */
+ private XPathFactory xPathFactory = null;
+
+ /**
+ * Representation of the XML document, in which this {@link LibvirtXmlNode} is part of.
+ */
+ private Document xmlDocument = null;
+
+ /**
+ * Current XML base node as XML root anchor for relative internal {@link XPath} expressions.
+ */
+ private Node xmlBaseNode = null;
+
+ /**
+ * Create and initialize {@link XPath} context to define and compile custom {@link XPath}
+ * expressions.
+ */
+ private void createXPathContext()
+ {
+ this.xPathFactory = XPathFactory.newInstance();
+ }
+
+ /**
+ * Creates empty Libvirt XML node, which does not belong to any XML document and does not specify
+ * any XML base node.
+ *
+ * @implNote Please call {@link LibvirtXmlNode#setXmlDocument(Document)} and
+ * {@link LibvirtXmlNode#setXmlBaseNode(Node)} manually to obtain a functional Libvirt
+ * XML node.
+ */
+ public LibvirtXmlNode()
+ {
+ this( null, null );
+ }
+
+ /**
+ * Creates Libvirt XML node from a existing Libvirt XML node by reference.
+ *
+ * @param xmlNode existing Libvirt XML node.
+ */
+ public LibvirtXmlNode( LibvirtXmlNode xmlNode )
+ {
+ this( xmlNode.getXmlDocument(), xmlNode.getXmlBaseNode() );
+ }
+
+ /**
+ * Creates Libvirt XML node as part of a existing XML document.
+ *
+ * @param xmlDocument existing XML document.
+ *
+ * @implNote Please call {@link LibvirtXmlNode#setXmlBaseNode(Node)} manually to obtain a
+ * functional Libvirt XML node.
+ */
+ public LibvirtXmlNode( Document xmlDocument )
+ {
+ this( xmlDocument, null );
+ }
+
+ /**
+ * Creates Libvirt XML node with a specific XML base node.
+ *
+ * @param xmlBaseNode existing XML base node.
+ *
+ * @implNote Please call {@link LibvirtXmlNode#setXmlDocument(Document)} manually to obtain a
+ * functional Libvirt XML node.
+ */
+ public LibvirtXmlNode( Node xmlBaseNode )
+ {
+ this( null, xmlBaseNode );
+ }
+
+ /**
+ * Creates Libvirt XML node with a specific XML base node as part of a XML document.
+ *
+ * @param xmlDocument existing XML document.
+ * @param xmlBaseNode existing XML base node.
+ */
+ public LibvirtXmlNode( Document xmlDocument, Node xmlBaseNode )
+ {
+ this.createXPathContext();
+
+ this.setXmlDocument( xmlDocument );
+ this.setXmlBaseNode( xmlBaseNode );
+ }
+
+ /**
+ * Returns referenced XML document.
+ *
+ * @return referenced XML document.
+ */
+ public Document getXmlDocument()
+ {
+ return this.xmlDocument;
+ }
+
+ /**
+ * Sets existing XML document for Libvirt XML node.
+ *
+ * @param xmlDocument existing XML document.
+ */
+ public void setXmlDocument( Document xmlDocument )
+ {
+ this.xmlDocument = xmlDocument;
+ }
+
+ /**
+ * Returns current XML base node.
+ *
+ * @return current XML base node as XML root anchor of relative internal {@link XPath}
+ * expressions.
+ */
+ public Node getXmlBaseNode()
+ {
+ return this.xmlBaseNode;
+ }
+
+ /**
+ * Sets existing XML base node for Libvirt XML node.
+ *
+ * @param xmlBaseNode existing XML base node as XML root anchor for relative internal
+ * {@link XPath} expressions.
+ */
+ public void setXmlBaseNode( Node xmlBaseNode )
+ {
+ this.xmlBaseNode = xmlBaseNode;
+ }
+
+ @Override
+ public Node getXmlNode( String expression )
+ {
+ NodeList nodes = this.getXmlNodes( expression );
+ return nodes.item( 0 );
+ }
+
+ @Override
+ public NodeList getXmlNodes( String expression )
+ {
+ Object nodes = null;
+
+ try {
+ XPath xPath = this.xPathFactory.newXPath();
+ XPathExpression xPathExpr = xPath.compile( expression );
+ nodes = xPathExpr.evaluate( this.xmlBaseNode, XPathConstants.NODESET );
+ } catch ( XPathExpressionException e ) {
+ e.printStackTrace();
+ }
+
+ return NodeList.class.cast( nodes );
+ }
+
+ @Override
+ public Node getXmlElement( String expression )
+ {
+ String completeExpression = null;
+
+ if ( expression == null ) {
+ completeExpression = XPATH_EXPRESSION_CURRENT_NODE;
+ } else if ( expression.isEmpty() ) {
+ completeExpression = XPATH_EXPRESSION_CURRENT_NODE;
+ } else {
+ completeExpression = XPATH_EXPRESSION_CURRENT_NODE + XPATH_EXPRESSION_SEPARATOR + expression;
+ }
+
+ Node node = this.getXmlNode( completeExpression );
+
+ if ( node != null && node.getNodeType() == Node.ELEMENT_NODE ) {
+ return node;
+ } else {
+ return null;
+ }
+ }
+
+ private Node createXmlElement( String expression )
+ {
+ Node parentNode = this.xmlBaseNode;
+ Node currentNode = parentNode;
+
+ if ( expression != null && !expression.isEmpty() ) {
+ String[] nodeNames = expression.split( XPATH_EXPRESSION_SEPARATOR );
+ String partialExpression = XPATH_EXPRESSION_CURRENT_NODE;
+
+ for ( int i = 0; i < nodeNames.length; i++ ) {
+ partialExpression += XPATH_EXPRESSION_SEPARATOR + nodeNames[i];
+ currentNode = this.getXmlNode( partialExpression );
+
+ if ( currentNode == null ) {
+ parentNode.appendChild( this.xmlDocument.createElement( nodeNames[i] ) );
+ currentNode = parentNode.getLastChild();
+ }
+
+ parentNode = currentNode;
+ }
+ }
+
+ return currentNode;
+ }
+
+ @Override
+ public void setXmlElement( String expression, Node child )
+ {
+ Node node = this.createXmlElement( expression );
+
+ if ( child != null ) {
+ node.appendChild( child );
+ }
+ }
+
+ @Override
+ public String getXmlElementValue( String expression )
+ {
+ Node node = this.getXmlElement( expression );
+
+ if ( node != null ) {
+ return node.getTextContent();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void setXmlElementValue( String expression, String value )
+ {
+ Node node = this.createXmlElement( expression );
+ node.setTextContent( value );
+ }
+
+ @Override
+ public void removeXmlElement( String expression )
+ {
+ Node node = this.getXmlElement( expression );
+
+ if ( node != null ) {
+ node.getParentNode().removeChild( node );
+ }
+ }
+
+ @Override
+ public void removeXmlElementChilds( String expression )
+ {
+ Node node = this.getXmlElement( expression );
+
+ if ( node != null ) {
+ for ( int i = 0; i < node.getChildNodes().getLength(); i++ ) {
+ Node child = node.getChildNodes().item( 0 );
+ node.removeChild( child );
+ }
+ }
+ }
+
+ @Override
+ public String getXmlElementAttributeValue( String expression, String attributeName )
+ {
+ Node node = null;
+
+ if ( expression != null && !expression.isEmpty() ) {
+ node = this.getXmlElement( expression );
+ } else {
+ node = this.xmlBaseNode;
+ }
+
+ if ( node == null ) {
+ return null;
+ } else {
+ Node attribute = node.getAttributes().getNamedItem( attributeName );
+
+ if ( attribute == null ) {
+ return null;
+ } else {
+ return attribute.getNodeValue();
+ }
+ }
+ }
+
+ @Override
+ public void setXmlElementAttributeValue( String expression, String attributeName, String value )
+ {
+ Node node = this.createXmlElement( expression );
+ Node attribute = node.getAttributes().getNamedItem( attributeName );
+
+ if ( attribute == null ) {
+ Element element = Element.class.cast( node );
+ element.setAttribute( attributeName, value );
+ } else {
+ attribute.setNodeValue( value );
+ }
+ }
+
+ @Override
+ public void removeXmlElementAttribute( String expression, String attributeName )
+ {
+ Node node = this.getXmlElement( expression );
+
+ if ( node != null ) {
+ Node attribute = node.getAttributes().getNamedItem( attributeName );
+ node.getAttributes().removeNamedItem( attribute.getNodeName() );
+ }
+ }
+
+ @Override
+ public void removeXmlElementAttributes( String expression )
+ {
+ Node node = this.getXmlElement( expression );
+
+ if ( node != null ) {
+ for ( int i = 0; i < node.getAttributes().getLength(); i++ ) {
+ Node attribute = node.getAttributes().item( 0 );
+ node.getAttributes().removeNamedItem( attribute.getNodeName() );
+ }
+ }
+ }
+
+ @Override
+ public void fromXmlNode( Node xmlNode )
+ {
+ this.setXmlBaseNode( xmlNode );
+ }
+
+ @Override
+ public Node toXmlNode()
+ {
+ return this.getXmlBaseNode();
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlResources.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlResources.java
new file mode 100644
index 0000000..38c818b
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlResources.java
@@ -0,0 +1,52 @@
+package org.openslx.libvirt.xml;
+
+import java.io.File;
+import java.io.InputStream;
+
+/**
+ * Collection of resource utils for a Libvirt XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public final class LibvirtXmlResources
+{
+ /**
+ * File path prefix of the absolute path to the libvirt resource folder in a *.jar file.
+ */
+ private static final String LIBVIRT_PREFIX_PATH = File.separator + "libvirt";
+
+ /**
+ * File path prefix of the absolute path to the libvirt XSL resource folder in a *.jar file.
+ */
+ private static final String LIBVIRT_PREFIX_PATH_XSL = LIBVIRT_PREFIX_PATH + File.separator + "xsl";
+
+ /**
+ * File path prefix of the absolute path to the libvirt RNG resource folder in a *.jar file.
+ */
+ private static final String LIBVIRT_PREFIX_PATH_RNG = LIBVIRT_PREFIX_PATH + File.separator + "rng";
+
+ /**
+ * Returns a Libvirt XSL resource as stream.
+ *
+ * @param libvirtXslFileName file name of the XSL resource in the resources *.jar folder.
+ * @return Libvirt XSL resource as stream.
+ */
+ public static InputStream getLibvirtXsl( String libvirtXslFileName )
+ {
+ String libvirtXslPath = LibvirtXmlResources.LIBVIRT_PREFIX_PATH_XSL + File.separator + libvirtXslFileName;
+ return LibvirtXmlResources.class.getResourceAsStream( libvirtXslPath );
+ }
+
+ /**
+ * Returns a Libvirt RNG schema resource as stream.
+ *
+ * @param libvirtRngFileName file name of the RNG schema resource in the resources *.jar folder.
+ * @return Libvirt RNG schema resource as stream.
+ */
+ public static InputStream getLibvirtRng( String libvirtRngFileName )
+ {
+ String libvirtRngPath = LibvirtXmlResources.LIBVIRT_PREFIX_PATH_RNG + File.separator + libvirtRngFileName;
+ return LibvirtXmlResources.class.getResourceAsStream( libvirtRngPath );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSchemaValidator.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSchemaValidator.java
new file mode 100644
index 0000000..e074948
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSchemaValidator.java
@@ -0,0 +1,282 @@
+package org.openslx.libvirt.xml;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import javax.xml.XMLConstants;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.SAXException;
+
+/**
+ * Resource resolver input for RelaxNG schemas.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+class LibvirtXmlSchemaResourceInput implements LSInput
+{
+ /**
+ * Stores the public identification of the schema resource.
+ */
+ private String publicId;
+
+ /**
+ * Stores the system identification of the schema resource.
+ */
+ private String systemId;
+
+ /**
+ * Stream to process and read the schema resource.
+ */
+ private BufferedInputStream inputStream;
+
+ /**
+ * Creates a resource resolver input for a RelaxNG schema.
+ *
+ * @param publicId public identification of the schema resource.
+ * @param sysId system identification of the schema resource.
+ * @param input stream of the schema resource.
+ */
+ public LibvirtXmlSchemaResourceInput( String publicId, String sysId, InputStream input )
+ {
+ this.publicId = publicId;
+ this.systemId = sysId;
+ this.inputStream = new BufferedInputStream( input );
+ }
+
+ @Override
+ public String getBaseURI()
+ {
+ return null;
+ }
+
+ @Override
+ public InputStream getByteStream()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean getCertifiedText()
+ {
+ return false;
+ }
+
+ @Override
+ public Reader getCharacterStream()
+ {
+ return null;
+ }
+
+ @Override
+ public String getEncoding()
+ {
+ return null;
+ }
+
+ @Override
+ public String getPublicId()
+ {
+ return this.publicId;
+ }
+
+ @Override
+ public String getStringData()
+ {
+ String data = null;
+
+ synchronized ( this.inputStream ) {
+ try {
+ int inputLength = this.inputStream.available();
+ byte[] input = new byte[ inputLength ];
+ this.inputStream.read( input );
+ data = new String( input );
+ } catch ( IOException e ) {
+ e.printStackTrace();
+ }
+ }
+
+ return data;
+ }
+
+ @Override
+ public String getSystemId()
+ {
+ return this.systemId;
+ }
+
+ @Override
+ public void setBaseURI( String arg0 )
+ {
+ }
+
+ @Override
+ public void setByteStream( InputStream arg0 )
+ {
+ }
+
+ @Override
+ public void setCertifiedText( boolean arg0 )
+ {
+ }
+
+ @Override
+ public void setCharacterStream( Reader arg0 )
+ {
+ }
+
+ @Override
+ public void setEncoding( String arg0 )
+ {
+ }
+
+ @Override
+ public void setPublicId( String arg0 )
+ {
+ this.publicId = arg0;
+ }
+
+ @Override
+ public void setStringData( String arg0 )
+ {
+ }
+
+ @Override
+ public void setSystemId( String arg0 )
+ {
+ this.systemId = arg0;
+ }
+}
+
+/**
+ * Resource resolver for RelaxNG schemas.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+class LibvirtXmlSchemaResourceResolver implements LSResourceResolver
+{
+ @Override
+ public LSInput resolveResource( String type, String namespaceURI, String publicId, String systemId, String baseURI )
+ {
+ InputStream rngResourceStream = LibvirtXmlResources.getLibvirtRng( systemId );
+ return new LibvirtXmlSchemaResourceInput( publicId, systemId, rngResourceStream );
+ }
+}
+
+/**
+ * Validator for validation of Libvirt XML documents with RelaxNG schemas.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class LibvirtXmlSchemaValidator
+{
+ /**
+ * RelaxNG based validator for validation of Libvirt XML documents.
+ */
+ private Validator rngSchemaValidator;
+
+ /**
+ * Creates a validator for validation of Libvirt XML documents with RelaxNG schemas.
+ *
+ * @param rngSchema
+ * @throws SAXException
+ */
+ public LibvirtXmlSchemaValidator( InputStream rngSchema ) throws SAXException
+ {
+ this.createValidationContext( rngSchema );
+ }
+
+ /**
+ * Creates context for validation of Libvirt XML documents with a RelaxNG schema.
+ *
+ * @param rngSchema RelaxNG schema used for validation with {@link #validate(Document)}.
+ *
+ * @throws SAXException Loading, creation and processing of <code>rngSchema</code> has failed.
+ */
+ private void createValidationContext( InputStream rngSchema ) throws SAXException
+ {
+ // use hack to load specific schema factory implementation for RelaxNG schemas
+ System.setProperty( SchemaFactory.class.getName() + ":" + XMLConstants.RELAXNG_NS_URI,
+ "com.thaiopensource.relaxng.jaxp.XMLSyntaxSchemaFactory" );
+
+ // create schema resource resolver to resolve schema resources during parsing and validation
+ LibvirtXmlSchemaResourceResolver schemaResolver = new LibvirtXmlSchemaResourceResolver();
+
+ // create schema factory to be able to create a RelaxNG schema validator
+ SchemaFactory factory = SchemaFactory.newInstance( XMLConstants.RELAXNG_NS_URI );
+ factory.setResourceResolver( schemaResolver );
+ Schema schema = factory.newSchema( new StreamSource( rngSchema ) );
+
+ // create the RelaxNG schema validator
+ this.rngSchemaValidator = schema.newValidator();
+ this.rngSchemaValidator.setResourceResolver( schemaResolver );
+ }
+
+ /**
+ * Transforms a DOM source to a Stream source.
+ *
+ * @param domSource DOM source of a Libvirt XML document.
+ * @return Stream source of a Libvirt XML document.
+ *
+ * @throws TransformerException Transformation of DOM source to a Stream source has failed.
+ *
+ * @implNote This utility method is necessary in {@link #validate(Document)} to be able to
+ * validate a DOM Libvirt XML document with the schema and validator implementation for
+ * RelaxNG schema files from
+ * <code>com.thaiopensource.relaxng.jaxp.XMLSyntaxSchemaFactory</code>.
+ */
+ private static StreamSource toStreamSource( DOMSource domSource ) throws TransformerException
+ {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ StreamResult result = new StreamResult( outputStream );
+
+ // create identity transformer
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ transformer.transform( domSource, result );
+
+ ByteArrayInputStream inputStream = new ByteArrayInputStream( outputStream.toByteArray() );
+ return new StreamSource( inputStream );
+ }
+
+ /**
+ * Validates a given (and parsed) DOM Libvirt XML document.
+ *
+ * Validation takes place if the specified <code>xmlDocument</code> is non-null, otherwise the
+ * validation succeeds immediately. If the validation of the <code>xmlDocument</code> fails, a
+ * validation exception is thrown.
+ *
+ * @param xmlDocument Libvirt XML document.
+ *
+ * @throws LibvirtXmlValidationException Validation of Libvirt XML document failed.
+ */
+ public void validate( Document xmlDocument ) throws LibvirtXmlValidationException
+ {
+ if ( xmlDocument != null ) {
+ try {
+ DOMSource domSource = new DOMSource( xmlDocument );
+ StreamSource source = LibvirtXmlSchemaValidator.toStreamSource( domSource );
+ this.rngSchemaValidator.validate( source );
+ } catch ( SAXException | TransformerException | IOException e ) {
+ throw new LibvirtXmlValidationException( e.getLocalizedMessage() );
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSerializable.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSerializable.java
new file mode 100644
index 0000000..6f11ce5
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSerializable.java
@@ -0,0 +1,57 @@
+package org.openslx.libvirt.xml;
+
+import java.io.File;
+import java.io.InputStream;
+
+import org.xml.sax.InputSource;
+
+/**
+ * Serializability of a Libvirt XML document from/to a XML file.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public abstract interface LibvirtXmlSerializable
+{
+ /**
+ * Serialize Libvirt XML document from {@link String}.
+ *
+ * @param xml {@link String} containing XML content.
+ */
+ public void fromXml( String xml ) throws LibvirtXmlSerializationException;
+
+ /**
+ * Serialize Libvirt XML document from {@link File}.
+ *
+ * @param xml {@link File} containing XML content.
+ */
+ public void fromXml( File xml ) throws LibvirtXmlSerializationException;
+
+ /**
+ * Serialize Libvirt XML document from {@link InputStream}.
+ *
+ * @param xml {@link InputStream} providing XML content.
+ */
+ void fromXml( InputStream xml ) throws LibvirtXmlSerializationException;
+
+ /**
+ * Serialize Libvirt XML document from {@link InputSource}.
+ *
+ * @param xml {@link InputSource} providing XML content.
+ */
+ public void fromXml( InputSource xml ) throws LibvirtXmlSerializationException;
+
+ /**
+ * Serialize Libvirt XML document to {@link String}.
+ *
+ * @return XML {@link String} containing Libvirt XML document content.
+ */
+ public String toXml() throws LibvirtXmlSerializationException;
+
+ /**
+ * Serialize Libvirt XML document to {@link File}.
+ *
+ * @param xml XML {@link File} containing Libvirt XML document content.
+ */
+ public void toXml( File xml ) throws LibvirtXmlSerializationException;
+}
diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSerializationException.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSerializationException.java
new file mode 100644
index 0000000..d522107
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlSerializationException.java
@@ -0,0 +1,25 @@
+package org.openslx.libvirt.xml;
+
+/**
+ * An exception of an serialization error during Libvirt XML serialization.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class LibvirtXmlSerializationException extends Exception
+{
+ /**
+ * Version number for serialization.
+ */
+ private static final long serialVersionUID = 7995955592221349949L;
+
+ /**
+ * Creates a XML serialization exception including an error message.
+ *
+ * @param errorMsg message to describe a specific XML serialization error.
+ */
+ public LibvirtXmlSerializationException( String errorMsg )
+ {
+ super( errorMsg );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlValidatable.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlValidatable.java
new file mode 100644
index 0000000..8574cc4
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlValidatable.java
@@ -0,0 +1,18 @@
+package org.openslx.libvirt.xml;
+
+/**
+ * Validatability of Libvirt XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public abstract interface LibvirtXmlValidatable
+{
+ /**
+ * Validates the XML document's content and report error if document is not a valid Libvirt XML
+ * document.
+ *
+ * @throws LibvirtXmlValidationException XML content is not a valid Libvirt XML.
+ */
+ public void validateXml() throws LibvirtXmlValidationException;
+}
diff --git a/src/main/java/org/openslx/libvirt/xml/LibvirtXmlValidationException.java b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlValidationException.java
new file mode 100644
index 0000000..24e9db7
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/xml/LibvirtXmlValidationException.java
@@ -0,0 +1,25 @@
+package org.openslx.libvirt.xml;
+
+/**
+ * An exception of an unsuccessful Libvirt XML validation.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class LibvirtXmlValidationException extends Exception
+{
+ /**
+ * Version number for serialization.
+ */
+ private static final long serialVersionUID = 2299967599483742777L;
+
+ /**
+ * Creates a validation exception including an error message.
+ *
+ * @param errorMsg message to describe a specific Libvirt XML error.
+ */
+ public LibvirtXmlValidationException( String errorMsg )
+ {
+ super( errorMsg );
+ }
+}
diff --git a/src/main/java/org/openslx/util/vm/DiskImage.java b/src/main/java/org/openslx/util/vm/DiskImage.java
index 15b3800..617fadd 100644
--- a/src/main/java/org/openslx/util/vm/DiskImage.java
+++ b/src/main/java/org/openslx/util/vm/DiskImage.java
@@ -5,6 +5,8 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
+import java.util.List;
+import java.util.function.Predicate;
import org.apache.log4j.Logger;
import org.openslx.bwlp.thrift.iface.Virtualizer;
@@ -26,8 +28,7 @@ public class DiskImage
public enum ImageFormat
{
- VMDK( "vmdk" ), QCOW2( "qcow2" ), VDI( "vdi" ),
- DOCKER("dockerfile");
+ VMDK( "vmdk" ), QCOW2( "qcow2" ), VDI( "vdi" ), DOCKER( "dockerfile" );
public final String extension;
@@ -53,7 +54,7 @@ public class DiskImage
return VDI;
if ( virtId.equals( TConst.VIRT_QEMU ) )
return QCOW2;
- if ( virtId.equals( TConst.VIRT_DOCKER) )
+ if ( virtId.equals( TConst.VIRT_DOCKER ) )
return DOCKER;
return null;
}
@@ -166,23 +167,193 @@ public class DiskImage
return;
}
- // TODO: qcow
+ // qcow2 disk image
file.seek( 0 );
if ( file.readInt() == QEMU_MAGIC ) {
- // dummy values
- this.isStandalone = true;
- this.isCompressed = false;
- this.isSnapshot = false;
+ //
+ // qcow2 (version 2 and 3) header format:
+ //
+ // magic (4 byte)
+ // version (4 byte)
+ // backing_file_offset (8 byte)
+ // backing_file_size (4 byte)
+ // cluster_bits (4 byte)
+ // size (8 byte)
+ // crypt_method (4 byte)
+ // l1_size (4 byte)
+ // l1_table_offset (8 byte)
+ // refcount_table_offset (8 byte)
+ // refcount_table_clusters (4 byte)
+ // nb_snapshots (4 byte)
+ // snapshots_offset (8 byte)
+ // incompatible_features (8 byte) [*]
+ // compatible_features (8 byte) [*]
+ // autoclear_features (8 byte) [*]
+ // refcount_order (8 byte) [*]
+ // header_length (4 byte) [*]
+ //
+ // [*] these fields are only available in the qcow2 version 3 header format
+ //
+
+ //
+ // check qcow2 file format version
+ //
+ file.seek( 4 );
+ final int qcowVersion = file.readInt();
+ if ( qcowVersion < 2 || qcowVersion > 3 ) {
+ // disk image format is not a qcow2 disk format
+ throw new UnknownImageFormatException();
+ } else {
+ // disk image format is a valid qcow2 disk format
+ this.hwVersion = qcowVersion;
+ this.subFormat = null;
+ }
+
+ //
+ // check if qcow2 image does not refer to any backing file
+ //
+ file.seek( 8 );
+ this.isStandalone = ( file.readLong() == 0 ) ? true : false;
+
+ //
+ // check if qcow2 image does not contain any snapshot
+ //
+ file.seek( 56 );
+ this.isSnapshot = ( file.readInt() == 0 ) ? true : false;
+
+ //
+ // check if qcow2 image uses extended L2 tables
+ //
+ boolean qcowUseExtendedL2 = false;
+
+ // extended L2 tables are only possible in qcow2 version 3 header format
+ if ( qcowVersion == 3 ) {
+ // read incompatible feature bits
+ file.seek( 72 );
+ final long qcowIncompatibleFeatures = file.readLong();
+
+ // support for extended L2 tables is enabled if bit 4 is set
+ qcowUseExtendedL2 = ( ( ( qcowIncompatibleFeatures & 0x000000000010 ) >>> 4 ) == 1 );
+ }
+
+ //
+ // check if qcow2 image contains compressed clusters
+ //
+ boolean qcowCompressed = false;
+
+ // get number of entries in L1 table
+ file.seek( 36 );
+ final int qcowL1TableSize = file.readInt();
+
+ // check if a valid L1 table is present
+ if ( qcowL1TableSize > 0 ) {
+ // qcow2 image contains active L1 table with more than 0 entries: l1_size > 0
+ // search for first L2 table and its first entry to get compression bit
+
+ // get cluster bits to calculate the cluster size
+ file.seek( 20 );
+ final int qcowClusterBits = file.readInt();
+ final int qcowClusterSize = ( 1 << qcowClusterBits );
+
+ // entries of a L1 table have always the size of 8 byte (64 bit)
+ final int qcowL1TableEntrySize = 8;
+
+ // entries of a L2 table have either the size of 8 or 16 byte (64 or 128 bit)
+ final int qcowL2TableEntrySize = ( qcowUseExtendedL2 ) ? 16 : 8;
+
+ // calculate number of L2 table entries
+ final int qcowL2TableSize = qcowClusterSize / qcowL2TableEntrySize;
+
+ // get offset of L1 table
+ file.seek( 40 );
+ long qcowL1TableOffset = file.readLong();
+
+ // check for each L2 table referenced from an L1 table its entries
+ // until a compressed cluster descriptor is found
+ for ( long i = 0; i < qcowL1TableSize; i++ ) {
+ // get offset of current L2 table from the current L1 table entry
+ long qcowL1TableEntryOffset = qcowL1TableOffset + ( i * qcowL1TableEntrySize );
+ file.seek( qcowL1TableEntryOffset );
+ long qcowL1TableEntry = file.readLong();
+
+ // extract offset (bits 9 - 55) from L1 table entry
+ long qcowL2TableOffset = ( qcowL1TableEntry & 0x00fffffffffffe00L );
+
+ if ( qcowL2TableOffset == 0 ) {
+ // L2 table and all clusters described by this L2 table are unallocated
+ continue;
+ }
+
+ // get each L2 table entry and check if it is a compressed cluster descriptor
+ for ( long j = 0; j < qcowL2TableSize; j++ ) {
+ // get current L2 table entry
+ long qcowL2TableEntryOffset = qcowL2TableOffset + ( j * qcowL2TableEntrySize );
+ file.seek( qcowL2TableEntryOffset );
+ long qcowL2TableEntry = file.readLong();
+
+ // extract cluster type (standard or compressed) (bit 62)
+ boolean qcowClusterCompressed = ( ( ( qcowL2TableEntry & 0x4000000000000000L ) >>> 62 ) == 1 );
+
+ // check if qcow2 disk image contains at least one compressed cluster descriptor
+ if ( qcowClusterCompressed ) {
+ qcowCompressed = true;
+ break;
+ }
+ }
+
+ // terminate if one compressed cluster descriptor is already found
+ if ( qcowCompressed ) {
+ break;
+ }
+ }
+ } else {
+ // qcow2 image does not contain an active L1 table with any entry: l1_size = 0
+ qcowCompressed = false;
+ }
+
+ this.isCompressed = qcowCompressed;
this.format = ImageFormat.QCOW2;
- this.subFormat = null;
this.diskDescription = null;
- this.hwVersion = 0;
+
return;
}
}
throw new UnknownImageFormatException();
}
+
+ /**
+ * Creates new disk image and checks if image is supported by hypervisor's image formats.
+ *
+ * @param disk file to a disk storing the virtual machine content.
+ * @param supportedImageTypes list of supported image types of a hypervisor's image format.
+ * @throws FileNotFoundException cannot find virtual machine image file.
+ * @throws IOException cannot access the virtual machine image file.
+ * @throws UnknownImageFormatException virtual machine image file has an unknown image format.
+ */
+ public DiskImage( File disk, List<ImageFormat> supportedImageTypes )
+ throws FileNotFoundException, IOException, UnknownImageFormatException
+ {
+ this( disk );
+ if ( !this.isSupportedByHypervisor( supportedImageTypes ) ) {
+ throw new UnknownImageFormatException();
+ }
+ }
+
+ /**
+ * Checks if image format is supported by a list of supported hypervisor image formats.
+ *
+ * @param supportedImageTypes list of supported image types of a hypervisor.
+ * @return <code>true</code> if image type is supported by the hypervisor; otherwise
+ * <code>false</code>.
+ */
+ public boolean isSupportedByHypervisor( List<ImageFormat> supportedImageTypes )
+ {
+ Predicate<ImageFormat> matchDiskFormat = supportedImageType -> supportedImageType.toString()
+ .equalsIgnoreCase( this.getImageFormat().toString() );
+ return supportedImageTypes.stream().anyMatch( matchDiskFormat );
+ }
+
private int findNull( byte[] buffer )
{
for ( int i = 0; i < buffer.length; ++i ) {
diff --git a/src/main/java/org/openslx/util/vm/DockerMetaDataDummy.java b/src/main/java/org/openslx/util/vm/DockerMetaDataDummy.java
index eea4d8b..246f390 100644
--- a/src/main/java/org/openslx/util/vm/DockerMetaDataDummy.java
+++ b/src/main/java/org/openslx/util/vm/DockerMetaDataDummy.java
@@ -3,16 +3,25 @@ package org.openslx.util.vm;
import org.apache.log4j.Logger;
import org.openslx.bwlp.thrift.iface.Virtualizer;
import org.openslx.thrifthelper.TConst;
+import org.openslx.util.vm.DiskImage.ImageFormat;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
public class DockerMetaDataDummy extends VmMetaData {
- private static final Logger LOGGER = Logger.getLogger(DockerMetaDataDummy.class);
+ /**
+ * List of supported image formats by the Docker hypervisor.
+ */
+ private static final List<DiskImage.ImageFormat> SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList(
+ Arrays.asList( ImageFormat.DOCKER ) );
+
+ private static final Logger LOGGER = Logger.getLogger( DockerMetaDataDummy.class);
private final Virtualizer virtualizer = new Virtualizer(TConst.VIRT_DOCKER, "Docker");
@@ -71,6 +80,12 @@ public class DockerMetaDataDummy extends VmMetaData {
@Override public byte[] getFilteredDefinitionArray() {
return containerDefinition;
}
+
+ @Override
+ public List<DiskImage.ImageFormat> getSupportedImageFormats()
+ {
+ return DockerMetaDataDummy.SUPPORTED_IMAGE_FORMATS;
+ }
@Override public void applySettingsForLocalEdit() {
diff --git a/src/main/java/org/openslx/util/vm/QemuMetaData.java b/src/main/java/org/openslx/util/vm/QemuMetaData.java
index 201ffd8..d3b8451 100644
--- a/src/main/java/org/openslx/util/vm/QemuMetaData.java
+++ b/src/main/java/org/openslx/util/vm/QemuMetaData.java
@@ -1,233 +1,854 @@
package org.openslx.util.vm;
import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
+import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
-import java.util.Map;
+import java.util.Map.Entry;
-import org.apache.log4j.Logger;
import org.openslx.bwlp.thrift.iface.OperatingSystem;
import org.openslx.bwlp.thrift.iface.Virtualizer;
+import org.openslx.libvirt.domain.Domain;
+import org.openslx.libvirt.domain.device.ControllerUsb;
+import org.openslx.libvirt.domain.device.Disk.BusType;
+import org.openslx.libvirt.domain.device.Disk.StorageType;
+import org.openslx.libvirt.domain.device.DiskCdrom;
+import org.openslx.libvirt.domain.device.DiskFloppy;
+import org.openslx.libvirt.domain.device.DiskStorage;
+import org.openslx.libvirt.domain.device.Graphics;
+import org.openslx.libvirt.domain.device.GraphicsSpice;
+import org.openslx.libvirt.domain.device.Interface;
+import org.openslx.libvirt.domain.device.Sound;
+import org.openslx.libvirt.domain.device.Video;
+import org.openslx.libvirt.xml.LibvirtXmlDocumentException;
+import org.openslx.libvirt.xml.LibvirtXmlSerializationException;
+import org.openslx.libvirt.xml.LibvirtXmlValidationException;
import org.openslx.thrifthelper.TConst;
import org.openslx.util.vm.DiskImage.ImageFormat;
-import org.openslx.util.vm.DiskImage.UnknownImageFormatException;
-public class QemuMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, VBoxHWVersionMeta, VBoxEthernetDevTypeMeta, VBoxUsbSpeedMeta>
+/**
+ * Metadata to describe the hardware type of a QEMU sound card.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+class QemuSoundCardMeta
{
+ /**
+ * Stores the hardware model of the QEMU sound card.
+ */
+ private final Sound.Model model;
+
+ /**
+ * Creates metadata to describe the hardware model of a QEMU sound card.
+ *
+ * @param model hardware model of the QEMU sound card.
+ */
+ public QemuSoundCardMeta( Sound.Model model )
+ {
+ this.model = model;
+ }
- private final Map<String, String> arguments = new HashMap<String, String>();
- // the above map's elements will take the place of <args> in the config string
- private String config;
- private static final Logger LOGGER = Logger.getLogger( QemuMetaData.class );
+ /**
+ * Returns hardware model of the QEMU sound card.
+ *
+ * @return hardware model of the QEMU sound card.
+ */
+ public Sound.Model getModel()
+ {
+ return this.model;
+ }
+}
- private static final Virtualizer virtualizer = new Virtualizer( TConst.VIRT_QEMU, "QEMU-KVM" );
+/**
+ * Metadata to describe the hardware acceleration state of QEMU virtual graphics.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+class QemuDDAccelMeta
+{
+ /**
+ * Stores state of the hardware acceleration for QEMU virtual graphics.
+ */
+ private final boolean enabled;
+
+ /**
+ * Creates metadata to describe the hardware acceleration state of QEMU virtual graphics.
+ *
+ * @param enabled state of the hardware acceleration for QEMU virtual graphics.
+ */
+ public QemuDDAccelMeta( boolean enabled )
+ {
+ this.enabled = enabled;
+ }
- public QemuMetaData( List<OperatingSystem> osList, File file ) throws FileNotFoundException, IOException, UnsupportedVirtualizerFormatException
+ /**
+ * Returns state of the hardware acceleration of QEMU virtual graphics.
+ *
+ * @return state of the hardware acceleration for QEMU virtual graphics.
+ */
+ public boolean isEnabled()
+ {
+ return this.enabled;
+ }
+}
+
+/**
+ * Metadata to describe the version of a QEMU virtual machine configuration.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+class QemuHWVersionMeta
+{
+ /**
+ * Stores the version of a QEMU virtual machine configuration.
+ */
+ private final int version;
+
+ /**
+ * Creates metadata to describe the version of a QEMU virtual machine configuration.
+ *
+ * @param version version of the QEMU virtual machine configuration.
+ */
+ public QemuHWVersionMeta( int version )
+ {
+ this.version = version;
+ }
+
+ /**
+ * Returns version of the QEMU virtual machine configuration.
+ *
+ * @return version of the QEMU virtual machine configuration.
+ */
+ public int getVersion()
+ {
+ return this.version;
+ }
+}
+
+/**
+ * Metadata to describe the hardware type of a QEMU ethernet device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+class QemuEthernetDevTypeMeta
+{
+ /**
+ * Stores the hardware model of the QEMU ethernet device.
+ */
+ private final Interface.Model model;
+
+ /**
+ * Creates metadata to describe the hardware type of a QEMU ethernet device.
+ *
+ * @param model hardware type of the QEMU ethernet device.
+ */
+ public QemuEthernetDevTypeMeta( Interface.Model model )
+ {
+ this.model = model;
+ }
+
+ /**
+ * Returns the hardware type of a QEMU ethernet device.
+ *
+ * @return hardware type of the QEMU ethernet device.
+ */
+ public Interface.Model getModel()
+ {
+ return this.model;
+ }
+}
+
+/**
+ * Metadata to describe a QEMU USB controller.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+class QemuUsbSpeedMeta
+{
+ /**
+ * Stores the USB speed of the QEMU USB controller.
+ */
+ private final int speed;
+
+ /**
+ * Stores the QEMU hardware model of the USB controller.
+ */
+ private final ControllerUsb.Model model;
+
+ /**
+ * Creates metadata to describe a QEMU USB controller.
+ *
+ * @param speed USB speed of the QEMU USB controller.
+ * @param model QEMU hardware model of the USB controller.
+ */
+ public QemuUsbSpeedMeta( int speed, ControllerUsb.Model model )
+ {
+ this.speed = speed;
+ this.model = model;
+ }
+
+ /**
+ * Returns the speed of the QEMU USB controller.
+ *
+ * @return speed of the QEMU USB controller.
+ */
+ public int getSpeed()
+ {
+ return this.speed;
+ }
+
+ /**
+ * Returns QEMU hardware model of the USB controller.
+ *
+ * @return hardware model of the QEMU USB controller.
+ */
+ public ControllerUsb.Model getModel()
+ {
+ return this.model;
+ }
+}
+
+/**
+ * Virtual machine configuration (managed by Libvirt) for the QEMU hypervisor.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class QemuMetaData extends
+ VmMetaData<QemuSoundCardMeta, QemuDDAccelMeta, QemuHWVersionMeta, QemuEthernetDevTypeMeta, QemuUsbSpeedMeta>
+{
+ /**
+ * Default bridge name of the network bridge connected to the LAN.
+ */
+ public static final String NETWORK_DEFAULT_BRIDGE = "brBwLehrpool";
+
+ /**
+ * Default network name of the isolated host network (host only).
+ */
+ public static final String NETWORK_DEFAULT_HOST_ONLY = "host";
+
+ /**
+ * Default network name of the NAT network.
+ */
+ public static final String NETWORK_DEFAULT_NAT = "nat";
+
+ /**
+ * Default physical CDROM drive of the hypervisor host.
+ */
+ public static final String CDROM_DEFAULT_PHYSICAL_DRIVE = "/dev/sr0";
+
+ /**
+ * List of supported image formats by the QEMU hypervisor.
+ */
+ private static final List<DiskImage.ImageFormat> SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList(
+ Arrays.asList( ImageFormat.QCOW2, ImageFormat.VMDK, ImageFormat.VDI ) );
+
+ /**
+ * Representation of a QEMU hypervisor (managed by Libvirt).
+ */
+ private static final Virtualizer VIRTUALIZER = new Virtualizer( TConst.VIRT_QEMU, "QEMU" );
+
+ /**
+ * Libvirt XML configuration file to modify configuration of virtual machine for QEMU.
+ */
+ private Domain vmConfig = null;
+
+ /**
+ * Stores current index of added HDD device to the Libvirt XML configuration file.
+ */
+ private int vmDeviceIndexHddAdd = 0;
+
+ /**
+ * Stores current index of added CDROM device to the Libvirt XML configuration file.
+ */
+ private int vmDeviceIndexCdromAdd = 0;
+
+ /**
+ * Stores current index of added ethernet device to the Libvirt XML configuration file.
+ */
+ private int vmDeviceIndexEthernetAdd = 0;
+
+ /**
+ * Creates new virtual machine configuration (managed by Libvirt) for the QEMU hypervisor.
+ *
+ * @param osList list of operating systems.
+ * @param file image file for the QEMU hypervisor.
+ * @throws UnsupportedVirtualizerFormatException Libvirt XML configuration cannot be processed.
+ */
+ public QemuMetaData( List<OperatingSystem> osList, File file ) throws UnsupportedVirtualizerFormatException
{
super( osList );
- DiskImage di;
+
try {
- di = new DiskImage( file );
- } catch ( UnknownImageFormatException e ) {
- di = null;
+ // read and parse Libvirt domain XML configuration document
+ this.vmConfig = new Domain( file );
+ } catch ( LibvirtXmlDocumentException e ) {
+ throw new UnsupportedVirtualizerFormatException( e.getLocalizedMessage() );
+ } catch ( LibvirtXmlSerializationException e ) {
+ throw new UnsupportedVirtualizerFormatException( e.getLocalizedMessage() );
+ } catch ( LibvirtXmlValidationException e ) {
+ throw new UnsupportedVirtualizerFormatException( e.getLocalizedMessage() );
}
- if ( di == null || di.format != ImageFormat.QCOW2 ) {
- throw new UnsupportedVirtualizerFormatException( "This is not a qcow2 disk image" );
+
+ // register virtual hardware models for graphical editing of virtual devices (GPU, sound, USB, ...)
+ this.registerVirtualHW();
+
+ // set display name of VM
+ this.displayName = vmConfig.getName();
+
+ // this property cannot be checked with the Libvirt domain XML configuration
+ // to check if machine is in a paused/suspended state, look in the QEMU qcow2 image for snapshots and machine states
+ this.isMachineSnapshot = false;
+
+ // add HDDs, SSDs to QEMU metadata
+ for ( DiskStorage storageDiskDevice : this.vmConfig.getDiskStorageDevices() ) {
+ this.addHddMetaData( storageDiskDevice );
}
- config = "qemu-system-i386 <args> <image> -enable-kvm\nqemu-system-x86_64 <args> <image> -enable-kvm";
- displayName = file.getName().substring( 0, file.getName().indexOf( "." ) );
- setOs( "anyOs" );
- hdds.add( new HardDisk( "anychipset", DriveBusType.IDE, file.getAbsolutePath() ) );
- makeStartSequence();
}
- // initiates the arguments map with a default working sequence that will later be used in the definition array
- public void makeStartSequence()
+ /**
+ * Adds an existing and observed storage disk device to the HDD metadata.
+ *
+ * @param storageDiskDevice existing and observed storage disk that should be added to the
+ * metadata.
+ */
+ private void addHddMetaData( DiskStorage storageDiskDevice )
{
- arguments.put( "cpu", "host" );
- arguments.put( "smp", "2" );
- arguments.put( "m", "1024" );
- arguments.put( "vga", "std" );
+ String hddChipsetModel = null;
+ DriveBusType hddChipsetBus = QemuMetaDataUtils.convertBusType( storageDiskDevice.getBusType() );
+ String hddImagePath = storageDiskDevice.getStorageSource();
+
+ this.hdds.add( new HardDisk( hddChipsetModel, hddChipsetBus, hddImagePath ) );
}
- private String configWithArgs()
+ @Override
+ public byte[] getFilteredDefinitionArray()
{
- String tempString = "";
- for ( String key : arguments.keySet() ) {
- tempString += "-" + key + " " + arguments.get( key ) + " ";
- }
- return config.replaceAll( "<args>", tempString );
+ // remove UUID in Libvirt domain XML configuration
+ this.vmConfig.removeUuid();
+
+ // removes all specified boot order entries
+ this.vmConfig.removeBootOrder();
+
+ // removes all referenced storage files of all specified CDROMs, Floppy drives and HDDs
+ this.vmConfig.removeDiskDevicesStorage();
+
+ // removes all source networks of all specified network interfaces
+ this.vmConfig.removeInterfaceDevicesSource();
+
+ // output filtered Libvirt domain XML configuration
+ String configuration = this.vmConfig.toString();
+ return configuration.getBytes( StandardCharsets.UTF_8 );
}
@Override
- public byte[] getFilteredDefinitionArray()
+ public List<DiskImage.ImageFormat> getSupportedImageFormats()
{
- return configWithArgs().getBytes( StandardCharsets.UTF_8 );
+ return QemuMetaData.SUPPORTED_IMAGE_FORMATS;
}
@Override
public void applySettingsForLocalEdit()
{
+ // NOT implemented yet
}
@Override
public boolean addHddTemplate( File diskImage, String hddMode, String redoDir )
{
- String tempS = config.replaceAll( "<image>", diskImage.getAbsolutePath() );
- config = tempS;
- hdds.add( new HardDisk( "anychipset", DriveBusType.IDE, diskImage.getAbsolutePath() ) );
- return true;
+ return this.addHddTemplate( diskImage.getAbsolutePath(), hddMode, redoDir );
}
@Override
public boolean addHddTemplate( String diskImagePath, String hddMode, String redoDir )
{
- String tempS = config.replaceAll( "<image>", diskImagePath );
- config = tempS;
- hdds.add( new HardDisk( "anychipset", DriveBusType.IDE, diskImagePath ) );
- return true;
+ return this.addHddTemplate( this.vmDeviceIndexHddAdd++, diskImagePath, hddMode, redoDir );
+ }
+
+ /**
+ * Adds hard disk drive (HDD) to the QEMU virtual machine configuration.
+ *
+ * @param index current index of HDD to be added to the virtual machine configuration.
+ * @param diskImagePath path to the virtual disk image for the HDD.
+ * @param hddMode operation mode of the HDD.
+ * @param redoDir directory for the redo log if an independent non-persistent
+ * <code>hddMode</code> is set.
+ * @return result state of adding the HDD.
+ */
+ public boolean addHddTemplate( int index, String diskImagePath, String hddMode, String redoDir )
+ {
+ ArrayList<DiskStorage> storageDiskDevices = this.vmConfig.getDiskStorageDevices();
+ DiskStorage storageDiskDevice = QemuMetaDataUtils.getArrayIndex( storageDiskDevices, index );
+
+ if ( storageDiskDevice == null ) {
+ // HDD does not exist, so create new storage (HDD) device
+ storageDiskDevice = this.vmConfig.addDiskStorageDevice();
+ storageDiskDevice.setReadOnly( false );
+ storageDiskDevice.setBusType( BusType.VIRTIO );
+ String targetDevName = QemuMetaDataUtils.createAlphabeticalDeviceName( "vd", index );
+ storageDiskDevice.setTargetDevice( targetDevName );
+ storageDiskDevice.setStorage( StorageType.FILE, diskImagePath );
+
+ // add new created HDD to the metadata of the QemuMetaData object, too
+ this.addHddMetaData( storageDiskDevice );
+ } else {
+ // HDD exists, so update existing storage (HDD) device
+ storageDiskDevice.setStorage( StorageType.FILE, diskImagePath );
+ }
+
+ return false;
}
@Override
public boolean addDefaultNat()
{
- return true;
+ return this.addEthernet( EtherType.NAT );
}
@Override
public void setOs( String vendorOsId )
{
- setOs( TConst.VIRT_QEMU, vendorOsId );
+ this.setOs( vendorOsId );
}
@Override
public boolean addDisplayName( String name )
{
- // TODO Auto-generated method stub
- return false;
+ this.vmConfig.setName( name );
+
+ final boolean statusName = this.vmConfig.getName().equals( name );
+
+ return statusName;
}
@Override
public boolean addRam( int mem )
{
- this.arguments.put( "m", Integer.toString( mem ) );
- return true;
+ BigInteger memory = BigInteger.valueOf( mem );
+
+ this.vmConfig.setMemory( memory );
+ this.vmConfig.setCurrentMemory( memory );
+
+ final boolean isMemorySet = this.vmConfig.getMemory().toString().equals( memory.toString() );
+ final boolean isCurrentMemorySet = this.vmConfig.getCurrentMemory().toString().equals( memory.toString() );
+
+ return isMemorySet && isCurrentMemorySet;
}
@Override
public void addFloppy( int index, String image, boolean readOnly )
{
- // TODO Auto-generated method stub
-
+ ArrayList<DiskFloppy> floppyDiskDevices = this.vmConfig.getDiskFloppyDevices();
+ DiskFloppy floppyDiskDevice = QemuMetaDataUtils.getArrayIndex( floppyDiskDevices, index );
+
+ if ( floppyDiskDevice == null ) {
+ // floppy device does not exist, so create new floppy device
+ floppyDiskDevice = this.vmConfig.addDiskFloppyDevice();
+ floppyDiskDevice.setBusType( BusType.FDC );
+ String targetDevName = QemuMetaDataUtils.createAlphabeticalDeviceName( "fd", index );
+ floppyDiskDevice.setTargetDevice( targetDevName );
+ floppyDiskDevice.setReadOnly( readOnly );
+ floppyDiskDevice.setStorage( StorageType.FILE, image );
+ } else {
+ // floppy device exists, so update existing floppy device
+ floppyDiskDevice.setReadOnly( readOnly );
+ floppyDiskDevice.setStorage( StorageType.FILE, image );
+ }
}
@Override
public boolean addCdrom( String image )
{
- // TODO Auto-generated method stub
+ return this.addCdrom( this.vmDeviceIndexCdromAdd++, image );
+ }
+
+ /**
+ * Adds CDROM drive to the QEMU virtual machine configuration.
+ *
+ * @param index current index of CDROM drive to be added to the virtual machine configuration.
+ * @param image path to a virtual image that will be inserted as CDROM into the drive.
+ * @return result state of adding the CDROM drive.
+ */
+ public boolean addCdrom( int index, String image )
+ {
+ ArrayList<DiskCdrom> cdromDiskDevices = this.vmConfig.getDiskCdromDevices();
+ DiskCdrom cdromDiskDevice = QemuMetaDataUtils.getArrayIndex( cdromDiskDevices, index );
+
+ if ( cdromDiskDevice == null ) {
+ // CDROM device does not exist, so create new CDROM device
+ cdromDiskDevice = this.vmConfig.addDiskCdromDevice();
+ cdromDiskDevice.setBusType( BusType.SATA );
+ String targetDevName = QemuMetaDataUtils.createAlphabeticalDeviceName( "sd", index );
+ cdromDiskDevice.setTargetDevice( targetDevName );
+ cdromDiskDevice.setReadOnly( true );
+
+ if ( image == null ) {
+ cdromDiskDevice.setStorage( StorageType.BLOCK, CDROM_DEFAULT_PHYSICAL_DRIVE );
+ } else {
+ cdromDiskDevice.setStorage( StorageType.FILE, image );
+ }
+ } else {
+ // CDROM device exists, so update existing CDROM device
+ cdromDiskDevice.setReadOnly( true );
+
+ if ( image == null ) {
+ cdromDiskDevice.setStorage( StorageType.BLOCK, CDROM_DEFAULT_PHYSICAL_DRIVE );
+ } else {
+ cdromDiskDevice.setStorage( StorageType.FILE, image );
+ }
+ }
+
return false;
}
@Override
public boolean addCpuCoreCount( int nrOfCores )
{
- this.arguments.put( "smp", Integer.toString( nrOfCores ) );
- return true;
+ this.vmConfig.setVCpu( nrOfCores );
+
+ boolean isVCpuSet = this.vmConfig.getVCpu() == nrOfCores;
+
+ return isVCpuSet;
}
@Override
- public void setSoundCard( VmMetaData.SoundCardType type )
+ public void setSoundCard( SoundCardType type )
{
+ QemuSoundCardMeta soundDeviceConfig = this.soundCards.get( type );
+ ArrayList<Sound> soundDevices = this.vmConfig.getSoundDevices();
+ Sound.Model soundDeviceModel = soundDeviceConfig.getModel();
+
+ if ( soundDevices.isEmpty() ) {
+ // create new sound device with 'soundDeviceModel' hardware
+ Sound soundDevice = this.vmConfig.addSoundDevice();
+ soundDevice.setModel( soundDeviceModel );
+ } else {
+ // update sound device model type of existing sound devices
+ for ( Sound soundDevice : soundDevices ) {
+ soundDevice.setModel( soundDeviceModel );
+ }
+ }
}
@Override
- public VmMetaData.SoundCardType getSoundCard()
+ public SoundCardType getSoundCard()
{
- return null;
+ ArrayList<Sound> soundDevices = this.vmConfig.getSoundDevices();
+ SoundCardType soundDeviceType = SoundCardType.DEFAULT;
+
+ if ( soundDevices.isEmpty() ) {
+ // the VM configuration does not contain a sound card device
+ soundDeviceType = SoundCardType.NONE;
+ } else {
+ // the VM configuration at least one sound card device, so return the type of the first one
+ Sound.Model soundDeviceModel = soundDevices.get( 0 ).getModel();
+ soundDeviceType = QemuMetaDataUtils.convertSoundDeviceModel( soundDeviceModel );
+ }
+
+ return soundDeviceType;
}
@Override
- public void setDDAcceleration( VmMetaData.DDAcceleration type )
+ public void setDDAcceleration( DDAcceleration type )
{
+ QemuDDAccelMeta accelerationConfig = this.ddacc.get( type );
+ ArrayList<Graphics> graphicDevices = this.vmConfig.getGraphicDevices();
+ ArrayList<Video> videoDevices = this.vmConfig.getVideoDevices();
+ final boolean accelerationEnabled = accelerationConfig.isEnabled();
+
+ boolean acceleratedGraphicsAvailable = false;
+
+ if ( graphicDevices.isEmpty() ) {
+ // add new graphics device with enabled acceleration to VM configuration
+ GraphicsSpice graphicSpiceDevice = this.vmConfig.addGraphicsSpiceDevice();
+ graphicSpiceDevice.setOpenGl( true );
+ acceleratedGraphicsAvailable = true;
+ } else {
+ // enable graphic acceleration of existing graphics devices
+ for ( Graphics graphicDevice : graphicDevices ) {
+ // set hardware acceleration for SPICE based graphics output
+ // other graphic devices do not support hardware acceleration
+ if ( graphicDevice instanceof GraphicsSpice ) {
+ GraphicsSpice.class.cast( graphicDevice ).setOpenGl( true );
+ acceleratedGraphicsAvailable = true;
+ }
+ }
+ }
+
+ // only configure hardware acceleration of video card(s) if graphics with hardware acceleration is available
+ if ( acceleratedGraphicsAvailable ) {
+ if ( videoDevices.isEmpty() ) {
+ // add new video device with enabled acceleration to VM configuration
+ Video videoDevice = this.vmConfig.addVideoDevice();
+ videoDevice.setModel( Video.Model.VIRTIO );
+ videoDevice.set2DAcceleration( true );
+ videoDevice.set3DAcceleration( true );
+ } else {
+ // enable graphic acceleration of existing graphics and video devices
+ for ( Video videoDevice : videoDevices ) {
+ // set hardware acceleration for Virtio GPUs
+ // other GPUs do not support hardware acceleration
+ if ( videoDevice.getModel() == Video.Model.VIRTIO ) {
+ videoDevice.set2DAcceleration( accelerationEnabled );
+ videoDevice.set3DAcceleration( accelerationEnabled );
+ }
+ }
+ }
+ }
}
@Override
- public VmMetaData.DDAcceleration getDDAcceleration()
+ public DDAcceleration getDDAcceleration()
{
- return null;
+ ArrayList<Graphics> graphicsDevices = this.vmConfig.getGraphicDevices();
+ ArrayList<Video> videoDevices = this.vmConfig.getVideoDevices();
+ DDAcceleration accelerationState = DDAcceleration.OFF;
+
+ boolean acceleratedGraphicsAvailable = false;
+ boolean acceleratedVideoDevAvailable = false;
+
+ // search for hardware accelerated graphics
+ for ( Graphics graphicDevice : graphicsDevices ) {
+ // only SPICE based graphic devices support hardware acceleration
+ if ( graphicDevice instanceof GraphicsSpice ) {
+ acceleratedGraphicsAvailable = true;
+ break;
+ }
+ }
+
+ // search for hardware accelerated video devices
+ for ( Video videoDevice : videoDevices ) {
+ // only Virtio based video devices support hardware acceleration
+ if ( videoDevice.getModel() == Video.Model.VIRTIO ) {
+ acceleratedVideoDevAvailable = true;
+ break;
+ }
+ }
+
+ // hardware acceleration is available if at least one accelerated graphics and video device is available
+ if ( acceleratedGraphicsAvailable && acceleratedVideoDevAvailable ) {
+ accelerationState = DDAcceleration.ON;
+ } else {
+ accelerationState = DDAcceleration.OFF;
+ }
+
+ return accelerationState;
}
@Override
- public void setHWVersion( VmMetaData.HWVersion type )
+ public void setHWVersion( HWVersion type )
{
+ // NOT supported by the QEMU hypervisor
}
@Override
- public VmMetaData.HWVersion getHWVersion()
+ public HWVersion getHWVersion()
{
+ // NOT supported by the QEMU hypervisor
return null;
}
@Override
- public void setEthernetDevType( int cardIndex, VmMetaData.EthernetDevType type )
+ public void setEthernetDevType( int cardIndex, EthernetDevType type )
{
+ QemuEthernetDevTypeMeta networkDeviceConfig = this.networkCards.get( type );
+ ArrayList<Interface> networkDevices = this.vmConfig.getInterfaceDevices();
+ Interface networkDevice = QemuMetaDataUtils.getArrayIndex( networkDevices, cardIndex );
+ Interface.Model networkDeviceModel = networkDeviceConfig.getModel();
+
+ if ( networkDevice != null ) {
+ networkDevice.setModel( networkDeviceModel );
+ }
}
@Override
- public VmMetaData.EthernetDevType getEthernetDevType( int cardIndex )
+ public EthernetDevType getEthernetDevType( int cardIndex )
{
- return null;
+ ArrayList<Interface> networkDevices = this.vmConfig.getInterfaceDevices();
+ Interface networkDevice = QemuMetaDataUtils.getArrayIndex( networkDevices, cardIndex );
+ EthernetDevType networkDeviceType = EthernetDevType.NONE;
+
+ if ( networkDevice == null ) {
+ // network interface device is not present
+ networkDeviceType = EthernetDevType.NONE;
+ } else {
+ // get model of existing network interface device
+ Interface.Model networkDeviceModel = networkDevice.getModel();
+ networkDeviceType = QemuMetaDataUtils.convertNetworkDeviceModel( networkDeviceModel );
+ }
+
+ return networkDeviceType;
}
@Override
- public byte[] getDefinitionArray()
+ public void setMaxUsbSpeed( UsbSpeed speed )
{
- return configWithArgs().getBytes( StandardCharsets.UTF_8 );
+ QemuUsbSpeedMeta usbControllerConfig = this.usbSpeeds.get( speed );
+ ArrayList<ControllerUsb> usbControllerDevices = this.vmConfig.getUsbControllerDevices();
+ ControllerUsb.Model usbControllerModel = usbControllerConfig.getModel();
+
+ if ( usbControllerDevices.isEmpty() ) {
+ // add new USB controller with specified speed 'usbControllerModel'
+ ControllerUsb usbControllerDevice = this.vmConfig.addControllerUsbDevice();
+ usbControllerDevice.setModel( usbControllerModel );
+ } else {
+ // update model of all USB controller devices to support the maximum speed
+ for ( ControllerUsb usbControllerDevice : usbControllerDevices ) {
+ usbControllerDevice.setModel( usbControllerModel );
+ }
+ }
}
@Override
- public boolean addEthernet( VmMetaData.EtherType type )
+ public UsbSpeed getMaxUsbSpeed()
{
- return false;
+ ArrayList<ControllerUsb> usbControllerDevices = this.vmConfig.getUsbControllerDevices();
+ UsbSpeed maxUsbSpeed = VmMetaData.UsbSpeed.NONE;
+ int maxUsbSpeedNumeric = 0;
+
+ for ( ControllerUsb usbControllerDevice : usbControllerDevices ) {
+ ControllerUsb.Model usbControllerModel = usbControllerDevice.getModel();
+
+ for ( Entry<UsbSpeed, QemuUsbSpeedMeta> usbSpeedEntry : this.usbSpeeds.entrySet() ) {
+ QemuUsbSpeedMeta usbSpeed = usbSpeedEntry.getValue();
+ if ( usbSpeed.getSpeed() > maxUsbSpeedNumeric && usbSpeed.getModel() == usbControllerModel ) {
+ maxUsbSpeed = usbSpeedEntry.getKey();
+ maxUsbSpeedNumeric = usbSpeed.getSpeed();
+ }
+ }
+ }
+
+ return maxUsbSpeed;
}
@Override
- public Virtualizer getVirtualizer()
+ public byte[] getDefinitionArray()
{
- return virtualizer;
+ String configuration = this.vmConfig.toString();
+
+ if ( configuration == null ) {
+ return null;
+ } else {
+ // append newline at the end of the XML content to match the structure of an original Libvirt XML file
+ configuration += System.lineSeparator();
+ return configuration.getBytes( StandardCharsets.UTF_8 );
+ }
}
@Override
- public boolean tweakForNonPersistent()
+ public boolean addEthernet( EtherType type )
+ {
+ return this.addEthernet( this.vmDeviceIndexEthernetAdd++, type );
+ }
+
+ /**
+ * Adds an ethernet card to the QEMU virtual machine configuration.
+ *
+ * @param index current index of the ethernet card to be added to the virtual machine
+ * configuration.
+ * @param type card model of the ethernet card.
+ * @return result state of adding the ethernet card.
+ */
+ public boolean addEthernet( int index, EtherType type )
{
+ QemuEthernetDevTypeMeta defaultNetworkDeviceConfig = this.networkCards.get( EthernetDevType.AUTO );
+ ArrayList<Interface> interfaceDevices = this.vmConfig.getInterfaceDevices();
+ Interface interfaceDevice = QemuMetaDataUtils.getArrayIndex( interfaceDevices, index );
+
+ final Interface.Model defaultNetworkDeviceModel = defaultNetworkDeviceConfig.getModel();
+
+ if ( interfaceDevice == null ) {
+ // network interface device does not exist, so create new network interface device
+ switch ( type ) {
+ case BRIDGED:
+ // add network bridge interface device
+ interfaceDevice = this.vmConfig.addInterfaceBridgeDevice();
+ interfaceDevice.setModel( defaultNetworkDeviceModel );
+ interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_BRIDGE );
+ break;
+ case HOST_ONLY:
+ // add network interface device with link to the isolated host network
+ interfaceDevice = this.vmConfig.addInterfaceNetworkDevice();
+ interfaceDevice.setModel( defaultNetworkDeviceModel );
+ interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_HOST_ONLY );
+ break;
+ case NAT:
+ // add network interface device with link to the NAT network
+ interfaceDevice = this.vmConfig.addInterfaceNetworkDevice();
+ interfaceDevice.setModel( defaultNetworkDeviceModel );
+ interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_NAT );
+ break;
+ }
+ } else {
+ // network interface device exists, so update existing network interface device
+ switch ( type ) {
+ case BRIDGED:
+ interfaceDevice.setType( Interface.Type.BRIDGE );
+ interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_BRIDGE );
+ break;
+ case HOST_ONLY:
+ interfaceDevice.setType( Interface.Type.NETWORK );
+ interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_HOST_ONLY );
+ break;
+ case NAT:
+ interfaceDevice.setType( Interface.Type.NETWORK );
+ interfaceDevice.setSource( QemuMetaData.NETWORK_DEFAULT_NAT );
+ break;
+ }
+ }
+
return false;
}
@Override
- public void registerVirtualHW()
+ public Virtualizer getVirtualizer()
{
+ return QemuMetaData.VIRTUALIZER;
}
@Override
- public void setMaxUsbSpeed( VmMetaData.UsbSpeed speed )
+ public boolean tweakForNonPersistent()
{
- // TODO: Actual speed setting?
- if ( speed == null || speed == VmMetaData.UsbSpeed.NONE ) {
- arguments.remove( "usb" );
- } else {
- arguments.put( "usb", "" );
- }
+ // NOT implemented yet
+ return false;
}
@Override
- public VmMetaData.UsbSpeed getMaxUsbSpeed()
+ public void registerVirtualHW()
{
- if ( arguments.containsKey( "usb" ) )
- return VmMetaData.UsbSpeed.USB2_0; // TODO
- return VmMetaData.UsbSpeed.NONE;
+ // @formatter:off
+ soundCards.put( VmMetaData.SoundCardType.NONE, new QemuSoundCardMeta( null ) );
+ soundCards.put( VmMetaData.SoundCardType.DEFAULT, new QemuSoundCardMeta( Sound.Model.ICH9 ) );
+ soundCards.put( VmMetaData.SoundCardType.SOUND_BLASTER, new QemuSoundCardMeta( Sound.Model.SB16 ) );
+ soundCards.put( VmMetaData.SoundCardType.ES, new QemuSoundCardMeta( Sound.Model.ES1370 ) );
+ soundCards.put( VmMetaData.SoundCardType.AC, new QemuSoundCardMeta( Sound.Model.AC97 ) );
+ soundCards.put( VmMetaData.SoundCardType.HD_AUDIO, new QemuSoundCardMeta( Sound.Model.ICH9 ) );
+
+ ddacc.put( VmMetaData.DDAcceleration.OFF, new QemuDDAccelMeta( false ) );
+ ddacc.put( VmMetaData.DDAcceleration.ON, new QemuDDAccelMeta( true ) );
+
+ hwversion.put( VmMetaData.HWVersion.DEFAULT, new QemuHWVersionMeta( 0 ) );
+
+ networkCards.put( VmMetaData.EthernetDevType.NONE, new QemuEthernetDevTypeMeta( null ) );
+ networkCards.put( VmMetaData.EthernetDevType.AUTO, new QemuEthernetDevTypeMeta( Interface.Model.VIRTIO_NET_PCI ) );
+ networkCards.put( VmMetaData.EthernetDevType.PCNETPCI2, new QemuEthernetDevTypeMeta( Interface.Model.PCNET ) );
+ networkCards.put( VmMetaData.EthernetDevType.E1000, new QemuEthernetDevTypeMeta( Interface.Model.E1000 ) );
+ networkCards.put( VmMetaData.EthernetDevType.E1000E, new QemuEthernetDevTypeMeta( Interface.Model.E1000E ) );
+ networkCards.put( VmMetaData.EthernetDevType.VMXNET3, new QemuEthernetDevTypeMeta( Interface.Model.VMXNET3 ) );
+ networkCards.put( VmMetaData.EthernetDevType.PARAVIRT, new QemuEthernetDevTypeMeta( Interface.Model.VIRTIO_NET_PCI ) );
+
+ usbSpeeds.put( VmMetaData.UsbSpeed.NONE, new QemuUsbSpeedMeta( 0, ControllerUsb.Model.NONE ) );
+ usbSpeeds.put( VmMetaData.UsbSpeed.USB1_1, new QemuUsbSpeedMeta( 1, ControllerUsb.Model.ICH9_UHCI1 ) );
+ usbSpeeds.put( VmMetaData.UsbSpeed.USB2_0, new QemuUsbSpeedMeta( 2, ControllerUsb.Model.ICH9_EHCI1 ) );
+ usbSpeeds.put( VmMetaData.UsbSpeed.USB3_0, new QemuUsbSpeedMeta( 3, ControllerUsb.Model.QEMU_XHCI ) );
+ // @formatter:on
}
-
}
diff --git a/src/main/java/org/openslx/util/vm/QemuMetaDataUtils.java b/src/main/java/org/openslx/util/vm/QemuMetaDataUtils.java
new file mode 100644
index 0000000..42c3fb6
--- /dev/null
+++ b/src/main/java/org/openslx/util/vm/QemuMetaDataUtils.java
@@ -0,0 +1,188 @@
+package org.openslx.util.vm;
+
+import java.util.ArrayList;
+
+import org.openslx.libvirt.domain.device.Disk;
+import org.openslx.libvirt.domain.device.Interface;
+import org.openslx.libvirt.domain.device.Disk.BusType;
+import org.openslx.libvirt.domain.device.Sound;
+import org.openslx.util.vm.VmMetaData.DriveBusType;
+import org.openslx.util.vm.VmMetaData.EthernetDevType;
+import org.openslx.util.vm.VmMetaData.SoundCardType;
+
+/**
+ * Collection of utils to convert data types from bwLehrpool to Libvirt and vice versa.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class QemuMetaDataUtils
+{
+ /**
+ * Converts a Libvirt disk device bus type to a VM metadata driver bus type.
+ *
+ * @param busType Libvirt disk device bus type.
+ * @return VM metadata bus type of the disk drive.
+ */
+ public static DriveBusType convertBusType( Disk.BusType busType )
+ {
+ DriveBusType type = null;
+
+ switch ( busType ) {
+ case IDE:
+ type = DriveBusType.IDE;
+ break;
+ case SATA:
+ type = DriveBusType.SATA;
+ break;
+ case SCSI:
+ type = DriveBusType.SCSI;
+ break;
+ default:
+ type = null;
+ break;
+ }
+
+ return type;
+ }
+
+ /**
+ * Converts a VM metadata driver bus type to a Libvirt disk device bus type.
+ *
+ * @param busType VM metadata bus type of the disk drive.
+ * @return Libvirt disk device bus type.
+ */
+ public static Disk.BusType convertBusType( DriveBusType busType )
+ {
+ Disk.BusType type = null;
+
+ switch ( busType ) {
+ case IDE:
+ type = BusType.IDE;
+ break;
+ case SATA:
+ type = BusType.SATA;
+ break;
+ case SCSI:
+ type = BusType.SCSI;
+ break;
+ }
+
+ return type;
+ }
+
+ /**
+ * Converts a Libvirt sound device model to a VM metadata sound card type.
+ *
+ * @param soundDeviceModel Libvirt sound device model.
+ * @return VM metadata sound card type.
+ */
+ public static SoundCardType convertSoundDeviceModel( Sound.Model soundDeviceModel )
+ {
+ SoundCardType type = SoundCardType.NONE;
+
+ switch ( soundDeviceModel ) {
+ case AC97:
+ type = SoundCardType.AC;
+ break;
+ case ES1370:
+ type = SoundCardType.ES;
+ break;
+ case ICH6:
+ type = SoundCardType.HD_AUDIO;
+ break;
+ case ICH9:
+ type = SoundCardType.HD_AUDIO;
+ break;
+ case SB16:
+ type = SoundCardType.SOUND_BLASTER;
+ break;
+ }
+
+ return type;
+ }
+
+ /**
+ * Converts a Libvirt network device model to a VM metadata ethernet device type.
+ *
+ * @param soundDeviceModel Libvirt network device model.
+ * @return VM metadata ethernet device type.
+ */
+ public static EthernetDevType convertNetworkDeviceModel( Interface.Model networkDeviceModel )
+ {
+ EthernetDevType type = EthernetDevType.NONE;
+
+ switch ( networkDeviceModel ) {
+ case E1000:
+ type = EthernetDevType.E1000;
+ break;
+ case E1000E:
+ type = EthernetDevType.E1000E;
+ break;
+ case PCNET:
+ type = EthernetDevType.PCNETPCI2;
+ break;
+ case VIRTIO:
+ type = EthernetDevType.PARAVIRT;
+ break;
+ case VIRTIO_NET_PCI:
+ type = EthernetDevType.PARAVIRT;
+ break;
+ case VIRTIO_NET_PCI_NON_TRANSITIONAL:
+ type = EthernetDevType.PARAVIRT;
+ break;
+ case VIRTIO_NET_PCI_TRANSITIONAL:
+ type = EthernetDevType.PARAVIRT;
+ break;
+ case VMXNET3:
+ type = EthernetDevType.VMXNET3;
+ break;
+ default:
+ type = EthernetDevType.AUTO;
+ break;
+ }
+
+ return type;
+ }
+
+ /**
+ * Returns an item from a given {@link ArrayList}.
+ *
+ * The item is selected by a given index. If the item is not available within the
+ * {@link ArrayList}, <code>null</code> is returned.
+ *
+ * @param <T> type of the {@link ArrayList}.
+ * @param array {@link ArrayList} of type <code>T</code>.
+ * @param index selects the item from the {@link ArrayList}.
+ * @return selected item of the {@link ArrayList}.
+ */
+ public static <T> T getArrayIndex( ArrayList<T> array, int index )
+ {
+ T ret;
+
+ try {
+ ret = array.get( index );
+ } catch ( IndexOutOfBoundsException e ) {
+ ret = null;
+ }
+
+ return ret;
+ }
+
+ /**
+ * Creates an alphabetical device name constructed from a device prefix and a device number.
+ *
+ * @param devicePrefix prefix of the constructed device name.
+ * @param deviceNumber number of the device.
+ * @return alphabetical device name.
+ */
+ public static String createAlphabeticalDeviceName( String devicePrefix, int deviceNumber )
+ {
+ if ( deviceNumber < 0 || deviceNumber >= ( 'z' - 'a' ) ) {
+ String errorMsg = new String( "Device number is out of range to be able to create a valid device name." );
+ throw new IllegalArgumentException( errorMsg );
+ }
+
+ return devicePrefix + ( 'a' + deviceNumber );
+ }
+}
diff --git a/src/main/java/org/openslx/util/vm/VboxMetaData.java b/src/main/java/org/openslx/util/vm/VboxMetaData.java
index da5189e..82936a7 100644
--- a/src/main/java/org/openslx/util/vm/VboxMetaData.java
+++ b/src/main/java/org/openslx/util/vm/VboxMetaData.java
@@ -6,6 +6,7 @@ import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
import java.util.UUID;
@@ -14,6 +15,7 @@ import org.apache.log4j.Logger;
import org.openslx.bwlp.thrift.iface.OperatingSystem;
import org.openslx.bwlp.thrift.iface.Virtualizer;
import org.openslx.thrifthelper.TConst;
+import org.openslx.util.vm.DiskImage.ImageFormat;
import org.openslx.util.vm.VboxConfig.PlaceHolder;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
@@ -77,6 +79,12 @@ class VBoxUsbSpeedMeta
public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta, VBoxHWVersionMeta, VBoxEthernetDevTypeMeta, VBoxUsbSpeedMeta>
{
+ /**
+ * List of supported image formats by the VirtualBox hypervisor.
+ */
+ private static final List<DiskImage.ImageFormat> SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList(
+ Arrays.asList( ImageFormat.VDI ) );
+
private static final Logger LOGGER = Logger.getLogger( VboxMetaData.class );
private static final Virtualizer virtualizer = new Virtualizer( TConst.VIRT_VIRTUALBOX, "VirtualBox" );
@@ -125,6 +133,12 @@ public class VboxMetaData extends VmMetaData<VBoxSoundCardMeta, VBoxDDAccelMeta,
{
return virtualizer;
}
+
+ @Override
+ public List<DiskImage.ImageFormat> getSupportedImageFormats()
+ {
+ return VboxMetaData.SUPPORTED_IMAGE_FORMATS;
+ }
@Override
public void applySettingsForLocalEdit()
diff --git a/src/main/java/org/openslx/util/vm/VmMetaData.java b/src/main/java/org/openslx/util/vm/VmMetaData.java
index dca9e27..616d971 100644
--- a/src/main/java/org/openslx/util/vm/VmMetaData.java
+++ b/src/main/java/org/openslx/util/vm/VmMetaData.java
@@ -282,6 +282,13 @@ public abstract class VmMetaData<T, U, V, W, X>
}
/**
+ * Returns list of image formats supported by the VM's hypervisor.
+ *
+ * @return list of image formats.
+ */
+ public abstract List<DiskImage.ImageFormat> getSupportedImageFormats();
+
+ /**
* Apply config options that are desired when locally editing a VM. for vmware,
* this disables automatic DPI scaling of the guest.
*/
@@ -310,7 +317,7 @@ public abstract class VmMetaData<T, U, V, W, X>
try {
return new QemuMetaData( osList, file );
} catch ( Exception e ) {
- LOGGER.info( "Not a QEmu file", e );
+ LOGGER.info( "Not a Qemu file", e );
}
try {
return new DockerMetaDataDummy(osList, file);
diff --git a/src/main/java/org/openslx/util/vm/VmwareMetaData.java b/src/main/java/org/openslx/util/vm/VmwareMetaData.java
index 2835e22..1793655 100644
--- a/src/main/java/org/openslx/util/vm/VmwareMetaData.java
+++ b/src/main/java/org/openslx/util/vm/VmwareMetaData.java
@@ -3,6 +3,8 @@ package org.openslx.util.vm;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -15,6 +17,7 @@ import org.openslx.bwlp.thrift.iface.OperatingSystem;
import org.openslx.bwlp.thrift.iface.Virtualizer;
import org.openslx.thrifthelper.TConst;
import org.openslx.util.Util;
+import org.openslx.util.vm.DiskImage.ImageFormat;
import org.openslx.util.vm.VmwareConfig.ConfigEntry;
class VmWareSoundCardMeta
@@ -73,7 +76,12 @@ class VmwareUsbSpeed
public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAccelMeta, VmWareHWVersionMeta, VmWareEthernetDevTypeMeta, VmwareUsbSpeed>
{
-
+ /**
+ * List of supported image formats by the VMware hypervisor.
+ */
+ private static final List<DiskImage.ImageFormat> SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableList(
+ Arrays.asList( ImageFormat.VMDK ) );
+
private static final Logger LOGGER = Logger.getLogger( VmwareMetaData.class );
private static final Virtualizer virtualizer = new Virtualizer( TConst.VIRT_VMWARE, "VMware" );
@@ -246,6 +254,12 @@ public class VmwareMetaData extends VmMetaData<VmWareSoundCardMeta, VmWareDDAcce
}
@Override
+ public List<DiskImage.ImageFormat> getSupportedImageFormats()
+ {
+ return VmwareMetaData.SUPPORTED_IMAGE_FORMATS;
+ }
+
+ @Override
public boolean addHddTemplate( File diskImage, String hddMode, String redoDir )
{
return addHddTemplate( diskImage.getName(), hddMode, redoDir );