diff options
author | Stephan Schwär | 2021-02-19 00:09:54 +0100 |
---|---|---|
committer | Stephan Schwär | 2021-02-19 00:09:54 +0100 |
commit | 62dce8c2b4e519f689e89038ff2afe4496f60628 (patch) | |
tree | 7c6802a436e2beb943065b5a377b61eb77d93170 /src/main/java/org/openslx | |
parent | [docker] Check recieved content. (diff) | |
parent | Add automatic RelaxNG schema validation for Libvirt domain XML documents (diff) | |
download | master-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')
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 ); |