true the 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 hostdev device is managed.
+ */
+ public boolean isManaged()
+ {
+ return this.getXmlElementAttributeValueAsBool( "managed" );
+ }
+
+ /**
+ * Sets state whether hostdev device is managed.
+ *
+ * If the managed parameter is set to true the hostdev device is
+ * detached from the host before being passed on to the guest and reattached to the host after
+ * the guest exits.
+ *
+ * @param managed state whether hostdev device is managed or not.
+ */
+ public void setManaged( boolean managed )
+ {
+ this.setXmlElementAttributeValueYesNo( "managed", managed );
+ }
+
/**
* Removes boot oder entry of the hostdev device.
*/
@@ -47,11 +74,13 @@ public class Hostdev extends Device
{
Hostdev addedHostdev = null;
+ xmlNode.setXmlElementAttributeValue( "mode", "subsystem" );
+
if ( hostdev instanceof HostdevPci ) {
- xmlNode.setXmlElementAttributeValue( "device", Type.PCI.toString() );
+ xmlNode.setXmlElementAttributeValue( "type", Type.PCI.toString() );
addedHostdev = HostdevPci.createInstance( xmlNode );
} else if ( hostdev instanceof HostdevUsb ) {
- xmlNode.setXmlElementAttributeValue( "device", Type.USB.toString() );
+ xmlNode.setXmlElementAttributeValue( "type", Type.USB.toString() );
addedHostdev = HostdevUsb.createInstance( xmlNode );
}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/HostdevAddressableSource.java b/src/main/java/org/openslx/libvirt/domain/device/HostdevAddressableSource.java
new file mode 100644
index 0000000..9377421
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/HostdevAddressableSource.java
@@ -0,0 +1,26 @@
+package org.openslx.libvirt.domain.device;
+
+/**
+ * Addressable source operations for a hostdev device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ *
+ * @param true 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.
+ * @param expression XPath expression to select the XML address element.
+ * @return PCI device address from the selected XML address element.
*/
- public boolean isManaged()
+ private HostdevPciDeviceAddress getPciAddress( final String expression )
{
- return this.getXmlElementAttributeValueAsBool( "managed" );
+ String pciDomain = this.getXmlElementAttributeValue( expression, "domain" );
+ String pciBus = this.getXmlElementAttributeValue( expression, "bus" );
+ String pciDevice = this.getXmlElementAttributeValue( expression, "slot" );
+ String pciFunction = this.getXmlElementAttributeValue( expression, "function" );
+
+ pciDomain = HostdevUtils.removeHexPrefix( pciDomain );
+ pciBus = HostdevUtils.removeHexPrefix( pciBus );
+ pciDevice = HostdevUtils.removeHexPrefix( pciDevice );
+ pciFunction = HostdevUtils.removeHexPrefix( pciFunction );
+
+ return HostdevPciDeviceAddress.valueOf( pciDomain + ":" + pciBus + ":" + pciDevice + "." + pciFunction );
}
/**
- * Sets state whether PCI hostdev device is managed.
+ * Sets the PCI device address for an XML address element selected by a XPath expression.
*
- * If the managed parameter is set to true 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.
- *
- * @param managed state whether PCI hostdev device is managed or not.
+ * @param expression XPath expression to select the XML address element.
+ * @param address PCI device address for the selected XML address element.
*/
- public void setManaged( boolean managed )
+ private void setPciAddress( final String expression, final HostdevPciDeviceAddress address )
+ {
+ final String pciDomain = HostdevUtils.appendHexPrefix( address.getPciDomainAsString() );
+ final String pciBus = HostdevUtils.appendHexPrefix( address.getPciBusAsString() );
+ final String pciDevice = HostdevUtils.appendHexPrefix( address.getPciDeviceAsString() );
+ final String pciFunction = HostdevUtils.appendHexPrefix( address.getPciFunctionAsString() );
+
+ this.setXmlElementAttributeValue( expression, "domain", pciDomain );
+ this.setXmlElementAttributeValue( expression, "bus", pciBus );
+ this.setXmlElementAttributeValue( expression, "slot", pciDevice );
+ this.setXmlElementAttributeValue( expression, "function", pciFunction );
+ }
+
+ @Override
+ public HostdevPciDeviceAddress getSource()
+ {
+ return this.getPciAddress( "source/address" );
+ }
+
+ @Override
+ public void setSource( HostdevPciDeviceAddress address )
+ {
+ this.setPciAddress( "source/address", address );
+ }
+
+ @Override
+ public HostdevPciDeviceAddress getTarget()
+ {
+ return this.getPciAddress( "address" );
+ }
+
+ @Override
+ public void setTarget( HostdevPciDeviceAddress address )
{
- this.setXmlElementAttributeValue( "managed", managed );
+ this.setPciAddress( "address", address );
}
/**
diff --git a/src/main/java/org/openslx/libvirt/domain/device/HostdevPciDeviceAddress.java b/src/main/java/org/openslx/libvirt/domain/device/HostdevPciDeviceAddress.java
new file mode 100644
index 0000000..9281500
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/HostdevPciDeviceAddress.java
@@ -0,0 +1,295 @@
+package org.openslx.libvirt.domain.device;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Representation of a slot address from a PCI device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class HostdevPciDeviceAddress
+{
+ /**
+ * Regular expression to parse a PCI device address from a {@link String}.
+ * + * The regular expression matches a PCI device address if its textual PCI device address is + * well-formed according to the following examples: + * + *
+ * 0000:00:02.3 + * 0000:01:00.0 + * 0000:00:1f.3 + *+ */ + private static final String DEVICE_ADDRESS_REGEX = "^([a-f0-9]{4}):([a-f0-9]{2}):([a-f0-9]{2})\\.([0-7]{1})$"; + + /** + * Minimum value for a valid PCI device address component number. + */ + private static final int DEVICE_ADDRESS_MIN_VALUE = 0; + + /** + * Maximum value for a valid PCI device domain number. + */ + private static final int DEVICE_ADDRESS_DOMAIN_MAX_VALUE = 0xffff; + + /** + * Maximum value for a valid PCI device bus number. + */ + private static final int DEVICE_ADDRESS_BUS_MAX_VALUE = 0xff; + + /** + * Maximum value for a valid PCI device device number. + */ + private static final int DEVICE_ADDRESS_DEVICE_MAX_VALUE = 0x1f; + + /** + * Maximum value for a valid PCI device function number. + */ + private static final int DEVICE_ADDRESS_FUNCTION_MAX_VALUE = 0x7; + + /** + * Domain number of the PCI device address. + */ + final int pciDomain; + + /** + * Bus number of the PCI device address. + */ + final int pciBus; + + /** + * Device number of the PCI device address. + */ + final int pciDevice; + + /** + * Function number of the PCI device address. + */ + final int pciFunction; + + /** + * Creates a new PCI device address and sets the address information to the default + * address {@code 0000:00:00.0}. + */ + public HostdevPciDeviceAddress() + { + this( 0, 0, 0, 0 ); + } + + /** + * Creates a new PCI device address consisting of a specified PCI bus, device, and function. + *
+ * The domain of the PCI device address is set to the default number {@code 0000}. + * + * @param pciBus number of the PCI bus. + * @param pciDevice number of the PCI device. + * @param pciFunction number of the PCI function. + * + * @throws IllegalArgumentException failed to validate the PCI bus, device and function. + */ + public HostdevPciDeviceAddress( int pciBus, int pciDevice, int pciFunction ) throws IllegalArgumentException + { + this( 0, pciBus, pciDevice, pciFunction ); + } + + /** + * Creates a new PCI device address consisting of a specified PCI domain, bus, device, and + * function. + * + * @param pciDomain number of the PCI domain. + * @param pciBus number of the PCI bus. + * @param pciDevice number of the PCI device. + * @param pciFunction number of the PCI function. + * + * @throws IllegalArgumentException failed to validate the PCI domain, bus, device and function. + */ + public HostdevPciDeviceAddress( int pciDomain, int pciBus, int pciDevice, int pciFunction ) + throws IllegalArgumentException + { + HostdevPciDeviceAddress.validatePciDeviceAddress( pciDomain, "PCI domain", + HostdevPciDeviceAddress.DEVICE_ADDRESS_DOMAIN_MAX_VALUE ); + HostdevPciDeviceAddress.validatePciDeviceAddress( pciBus, "PCI bus", + HostdevPciDeviceAddress.DEVICE_ADDRESS_BUS_MAX_VALUE ); + HostdevPciDeviceAddress.validatePciDeviceAddress( pciDevice, "PCI device", + HostdevPciDeviceAddress.DEVICE_ADDRESS_DEVICE_MAX_VALUE ); + HostdevPciDeviceAddress.validatePciDeviceAddress( pciFunction, "PCI function", + HostdevPciDeviceAddress.DEVICE_ADDRESS_FUNCTION_MAX_VALUE ); + + this.pciDomain = pciDomain; + this.pciBus = pciBus; + this.pciDevice = pciDevice; + this.pciFunction = pciFunction; + } + + /** + * Validates a specified PCI address component (PCI domain, bus, device or function). + * + * @param address value of the PCI address component. + * @param addressName name of the PCI address component. + * @param upperLimit maximum value for the PCI address component + * + * @throws IllegalArgumentException + */ + private static void validatePciDeviceAddress( final int address, final String addressName, final int upperLimit ) + throws IllegalArgumentException + { + if ( address < HostdevPciDeviceAddress.DEVICE_ADDRESS_MIN_VALUE ) { + throw new IllegalArgumentException( + "The " + addressName + " address must be larger or equal than " + + HostdevPciDeviceAddress.DEVICE_ADDRESS_MIN_VALUE ); + } else if ( address > upperLimit ) { + throw new IllegalArgumentException( + "The " + addressName + " address must be smaller or equal than " + upperLimit ); + } + } + + /** + * Returns the PCI domain. + * + * @return PCI domain. + */ + public int getPciDomain() + { + return this.pciDomain; + } + + /** + * Returns the PCI domain as {@link String}. + * + * @return PCI domain as {@link String}. + */ + public String getPciDomainAsString() + { + return String.format( "%04x", HostdevPciDeviceAddress.DEVICE_ADDRESS_DOMAIN_MAX_VALUE & this.getPciDomain() ); + } + + /** + * Returns the PCI bus. + * + * @return PCI bus. + */ + public int getPciBus() + { + return this.pciBus; + } + + /** + * Returns the PCI bus as {@link String}. + * + * @return PCI bus as {@link String}. + */ + public String getPciBusAsString() + { + return String.format( "%02x", HostdevPciDeviceAddress.DEVICE_ADDRESS_BUS_MAX_VALUE & this.getPciBus() ); + } + + /** + * Returns the PCI device. + * + * @return PCI device. + */ + public int getPciDevice() + { + return this.pciDevice; + } + + /** + * Returns the PCI device as {@link String}. + * + * @return PCI device as {@link String}. + */ + public String getPciDeviceAsString() + { + return String.format( "%02x", HostdevPciDeviceAddress.DEVICE_ADDRESS_DEVICE_MAX_VALUE & this.getPciDevice() ); + } + + /** + * Returns the PCI function. + * + * @return PCI function. + */ + public int getPciFunction() + { + return this.pciFunction; + } + + /** + * Returns the PCI function as {@link String}. + * + * @return PCI function as {@link String}. + */ + public String getPciFunctionAsString() + { + return String.format( "%01x", HostdevPciDeviceAddress.DEVICE_ADDRESS_FUNCTION_MAX_VALUE & this.getPciFunction() ); + } + + /** + * Creates a new PCI device address parsed from a {@link String}. + *
+ * The PCI device address consists of a PCI domain, bus, device and function parsed from the + * specified {@link String}. + * + * @param pciDeviceAddress textual information containing a PCI device address as {@link String}. + * The textual PCI device address should be well-formed according to the defined + * regular expression {@link #DEVICE_ADDRESS_REGEX}. + * + * @return PCI device address instance. + */ + public static HostdevPciDeviceAddress valueOf( String pciDeviceAddress ) + { + HostdevPciDeviceAddress parsedPciDeviceAddress; + + if ( pciDeviceAddress == null || pciDeviceAddress.isEmpty() ) { + parsedPciDeviceAddress = null; + } else { + final Pattern pciDeviceAddressPattern = Pattern.compile( HostdevPciDeviceAddress.DEVICE_ADDRESS_REGEX ); + final Matcher pciDeviceAddressMatcher = pciDeviceAddressPattern.matcher( pciDeviceAddress.toLowerCase() ); + + if ( pciDeviceAddressMatcher.find() ) { + final int pciDomain = Integer.valueOf( pciDeviceAddressMatcher.group( 1 ), 16 ); + final int pciBus = Integer.valueOf( pciDeviceAddressMatcher.group( 2 ), 16 ); + final int pciDevice = Integer.valueOf( pciDeviceAddressMatcher.group( 3 ), 16 ); + final int pciFunction = Integer.valueOf( pciDeviceAddressMatcher.group( 4 ), 16 ); + + try { + parsedPciDeviceAddress = new HostdevPciDeviceAddress( pciDomain, pciBus, pciDevice, pciFunction ); + } catch ( IllegalArgumentException e ) { + parsedPciDeviceAddress = null; + } + } else { + parsedPciDeviceAddress = null; + } + } + + return parsedPciDeviceAddress; + } + + @Override + public boolean equals( Object obj ) + { + if ( obj == null ) { + return false; + } else if ( this.getClass() != obj.getClass() ) { + return false; + } else { + // check if PCI domain, bus, device and function are equal + final HostdevPciDeviceAddress other = HostdevPciDeviceAddress.class.cast( obj ); + if ( this.getPciDomain() == other.getPciDomain() && this.getPciBus() == other.getPciBus() + && this.getPciDevice() == other.getPciDevice() && this.getPciFunction() == other.getPciFunction() ) { + return true; + } else { + return false; + } + } + } + + @Override + public String toString() + { + return this.getPciDomainAsString() + ":" + this.getPciBusAsString() + ":" + this.getPciDeviceAsString() + "." + + this.getPciFunctionAsString(); + } +} diff --git a/src/main/java/org/openslx/libvirt/domain/device/HostdevPciDeviceDescription.java b/src/main/java/org/openslx/libvirt/domain/device/HostdevPciDeviceDescription.java new file mode 100644 index 0000000..25c29f2 --- /dev/null +++ b/src/main/java/org/openslx/libvirt/domain/device/HostdevPciDeviceDescription.java @@ -0,0 +1,186 @@ +package org.openslx.libvirt.domain.device; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Representation of a PCI device description. + * + * @author Manuel Bentele + * @version 1.0 + */ +public class HostdevPciDeviceDescription extends Hostdev +{ + /** + * Regular expression to parse a PCI vendor and device identifier from a {@link String}. + *
+ * The regular expression matches a PCI device description if its textual PCI device description + * is well-formed according to the following examples: + * + *
+ * 8086:a170 + * 10ec:8168 + * 8086:15b7 + *+ */ + private static final String DEVICE_DESCRIPTION_REGEX = "^([a-f0-9]{4}):([a-f0-9]{4})$"; + + /** + * Minimum value of a valid identifier from a PCI device description. + */ + private static final int DEVICE_DESCRIPTION_ID_MIN_VALUE = 0x0000; + + /** + * Maximum value of a valid identifier from a PCI device description. + */ + private static final int DEVICE_DESCRIPTION_ID_MAX_VALUE = 0xffff; + + /** + * Vendor identifier of the PCI device. + */ + final int vendorId; + + /** + * Device identifier of the PCI device. + */ + final int deviceId; + + /** + * Creates a new PCI device description consisting of a PCI vendor and device identifier. + * + * @param vendorId vendor identifier of the PCI device. + * @param deviceId device identifier of the PCI device. + * + * @throws throws IllegalArgumentException failed to validate the PCI device description + * identifiers. + */ + public HostdevPciDeviceDescription( int vendorId, int deviceId ) throws IllegalArgumentException + { + HostdevPciDeviceDescription.validatePciDeviceDescriptionId( "PCI vendor ID", vendorId ); + HostdevPciDeviceDescription.validatePciDeviceDescriptionId( "PCI device ID", deviceId ); + + this.vendorId = vendorId; + this.deviceId = deviceId; + } + + /** + * Validates a PCI device description ID (a PCI vendor or device ID). + * + * @param idName name of the PCI device description identifier. + * @param id value of the PCI device description identifier that should be validated. + * + * @throws IllegalArgumentException failed to validate the PCI device description identifier. + */ + private static void validatePciDeviceDescriptionId( final String idName, final int id ) + throws IllegalArgumentException + { + if ( id < HostdevPciDeviceDescription.DEVICE_DESCRIPTION_ID_MIN_VALUE ) { + throw new IllegalArgumentException( + "The " + idName + "must be larger or equal than " + + HostdevPciDeviceDescription.DEVICE_DESCRIPTION_ID_MIN_VALUE ); + } else if ( id > HostdevPciDeviceDescription.DEVICE_DESCRIPTION_ID_MAX_VALUE ) { + throw new IllegalArgumentException( + "The " + idName + "must be smaller or equal than " + + HostdevPciDeviceDescription.DEVICE_DESCRIPTION_ID_MAX_VALUE ); + } + } + + /** + * Returns the PCI vendor identifier. + * + * @return PCI vendor identifier. + */ + public int getVendorId() + { + return this.vendorId; + } + + /** + * Returns the PCI vendor identifier as {@link String}. + * + * @return PCI vendor identifier as {@link String}. + */ + public String getVendorIdAsString() + { + return String.format( "%04x", HostdevPciDeviceDescription.DEVICE_DESCRIPTION_ID_MAX_VALUE & this.getVendorId() ); + } + + /** + * Returns the PCI device identifier. + * + * @return PCI device identifier. + */ + public int getDeviceId() + { + return this.deviceId; + } + + /** + * Returns the PCI device identifier as {@link String}. + * + * @return PCI device identifier as {@link String}. + */ + public String getDeviceIdAsString() + { + return String.format( "%04x", HostdevPciDeviceDescription.DEVICE_DESCRIPTION_ID_MAX_VALUE & this.getDeviceId() ); + } + + /** + * Creates a new PCI device description parsed from a {@link String}. + *
+ * The PCI device description consists of a PCI vendor and device identifier parsed from the
+ * specified {@link String}.
+ *
+ * @param vendorDeviceId textual information containing a PCI device description as
+ * {@link String}. The textual PCI device description should be well-formed according
+ * to the defined regular expression {@link #DEVICE_DESCRIPTION_REGEX}.
+ *
+ * @return PCI device description instance.
+ */
+ public static HostdevPciDeviceDescription valueOf( String vendorDeviceId )
+ {
+ final HostdevPciDeviceDescription pciDeviceDescription;
+
+ if ( vendorDeviceId == null || vendorDeviceId.isEmpty() ) {
+ pciDeviceDescription = null;
+ } else {
+ final Pattern pciDeviceDescPattern = Pattern.compile( HostdevPciDeviceDescription.DEVICE_DESCRIPTION_REGEX );
+ final Matcher pciDeviceDescMatcher = pciDeviceDescPattern.matcher( vendorDeviceId.toLowerCase() );
+
+ if ( pciDeviceDescMatcher.find() ) {
+ final int vendorId = Integer.valueOf( pciDeviceDescMatcher.group( 1 ), 16 );
+ final int deviceId = Integer.valueOf( pciDeviceDescMatcher.group( 2 ), 16 );
+
+ pciDeviceDescription = new HostdevPciDeviceDescription( vendorId, deviceId );
+ } else {
+ pciDeviceDescription = null;
+ }
+ }
+
+ return pciDeviceDescription;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( obj == null ) {
+ return false;
+ } else if ( this.getClass() != obj.getClass() ) {
+ return false;
+ } else {
+ // check if vendor and device ID are equal
+ final HostdevPciDeviceDescription other = HostdevPciDeviceDescription.class.cast( obj );
+ if ( this.getVendorId() == other.getVendorId() && this.getDeviceId() == other.getDeviceId() ) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.getVendorIdAsString() + ":" + this.getDeviceIdAsString();
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/HostdevUsb.java b/src/main/java/org/openslx/libvirt/domain/device/HostdevUsb.java
index e1fcc0c..a9d7f89 100644
--- a/src/main/java/org/openslx/libvirt/domain/device/HostdevUsb.java
+++ b/src/main/java/org/openslx/libvirt/domain/device/HostdevUsb.java
@@ -8,7 +8,8 @@ import org.openslx.libvirt.xml.LibvirtXmlNode;
* @author Manuel Bentele
* @version 1.0
*/
-public class HostdevUsb extends Hostdev
+public class HostdevUsb extends Hostdev implements HostdevAddressableSource
+ * The regular expression matches an USB device description if its textual USB device description
+ * is well-formed according to the following examples:
+ *
+ *
+ * The USB device description consists of an USB vendor and product identifier parsed from the
+ * specified {@link String}.
+ *
+ * @param vendorProductId textual information containing an USB device description as
+ * {@link String}. The textual USB device description should be well-formed according
+ * to the defined regular expression {@link #DEVICE_DESCRIPTION_REGEX}.
+ *
+ * @return USB device description instance.
+ */
+ public static HostdevUsbDeviceDescription valueOf( String vendorProductId )
+ {
+ HostdevUsbDeviceDescription usbDeviceDescription;
+
+ if ( vendorProductId == null || vendorProductId.isEmpty() ) {
+ usbDeviceDescription = null;
+ } else {
+ final Pattern usbDeviceDescPattern = Pattern.compile( HostdevUsbDeviceDescription.DEVICE_DESCRIPTION_REGEX );
+ final Matcher usbDeviceDescMatcher = usbDeviceDescPattern.matcher( vendorProductId.toLowerCase() );
+
+ if ( usbDeviceDescMatcher.find() ) {
+ final int vendorId = Integer.valueOf( usbDeviceDescMatcher.group( 1 ), 16 );
+ final int productId = Integer.valueOf( usbDeviceDescMatcher.group( 2 ), 16 );
+
+ try {
+ usbDeviceDescription = new HostdevUsbDeviceDescription( vendorId, productId );
+ } catch ( IllegalArgumentException e ) {
+ usbDeviceDescription = null;
+ }
+ } else {
+ usbDeviceDescription = null;
+ }
+ }
+
+ return usbDeviceDescription;
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if ( obj == null ) {
+ return false;
+ } else if ( this.getClass() != obj.getClass() ) {
+ return false;
+ } else {
+ // check if vendor and product ID are equal
+ final HostdevUsbDeviceDescription other = HostdevUsbDeviceDescription.class.cast( obj );
+ if ( this.getVendorId() == other.getVendorId() && this.getProductId() == other.getProductId() ) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.getVendorIdAsString() + ":" + this.getProductIdAsString();
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/HostdevUtils.java b/src/main/java/org/openslx/libvirt/domain/device/HostdevUtils.java
new file mode 100644
index 0000000..204bea9
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/HostdevUtils.java
@@ -0,0 +1,32 @@
+package org.openslx.libvirt.domain.device;
+
+/**
+ * Collection of helper methods to maintain a Libvirt related hostdev XML element.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class HostdevUtils
+{
+ /**
+ * Appends the HEX prefix to a specified hostdev address component without any HEX prefix.
+ *
+ * @param component address component without any HEX prefix.
+ * @return address component with the HEX prefix.
+ */
+ public static String appendHexPrefix( String component )
+ {
+ return "0x" + component;
+ }
+
+ /**
+ * Removes a possible HEX prefix of a specified hostdev address component.
+ *
+ * @param component address component with possible HEX prefix.
+ * @return address component without any HEX prefix.
+ */
+ public static String removeHexPrefix( String component )
+ {
+ return component.replaceFirst( "0x", "" );
+ }
+}
diff --git a/src/main/java/org/openslx/libvirt/domain/device/Shmem.java b/src/main/java/org/openslx/libvirt/domain/device/Shmem.java
new file mode 100644
index 0000000..3c48c95
--- /dev/null
+++ b/src/main/java/org/openslx/libvirt/domain/device/Shmem.java
@@ -0,0 +1,178 @@
+package org.openslx.libvirt.domain.device;
+
+import java.math.BigInteger;
+
+import org.openslx.libvirt.domain.DomainUtils;
+import org.openslx.libvirt.xml.LibvirtXmlNode;
+
+/**
+ * A shared memory device node in a Libvirt domain XML document.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+public class Shmem extends Device
+{
+ /**
+ * Creates an empty sound device.
+ */
+ public Shmem()
+ {
+ super();
+ }
+
+ /**
+ * Creates a shared memory device representing an existing Libvirt XML shared memory device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML shared memory device element.
+ */
+ public Shmem( LibvirtXmlNode xmlNode )
+ {
+ super( xmlNode );
+ }
+
+ /**
+ * Returns the model of the shared memory device.
+ *
+ * @return model of the shared memory device.
+ */
+ public Model getModel()
+ {
+ String model = this.getXmlElementAttributeValue( "model", "type" );
+ return Model.fromString( model );
+ }
+
+ /**
+ * Sets the model for the shared memory device.
+ *
+ * @param model model for the shared memory device.
+ */
+ public void setModel( Model model )
+ {
+ this.setXmlElementAttributeValue( "model", "type", model.toString() );
+ }
+
+ /**
+ * Returns the name of the shared memory device.
+ *
+ * @return name of the shared memory device.
+ */
+ public String getName()
+ {
+ return this.getXmlElementAttributeValue( "name" );
+ }
+
+ /**
+ * Sets the name for the shared memory device.
+ *
+ * @param name name for the shared memory device.
+ */
+ public void setName( String name )
+ {
+ this.setXmlElementAttributeValue( "name", name );
+ }
+
+ /**
+ * Returns the memory size of the shared memory device.
+ *
+ * @return memory size of the shared memory device in bytes.
+ */
+ public BigInteger getSize()
+ {
+ final String unit = this.getXmlElementAttributeValue( "size", "unit" );
+ final String size = this.getXmlElementValue( "size" );
+
+ return DomainUtils.decodeMemory( size, unit );
+ }
+
+ /**
+ * Sets the memory size for the shared memory device.
+ *
+ * @param size memory size for the shared memory device in bytes.
+ */
+ public void setSize( BigInteger memory )
+ {
+ final String unit = "M";
+ final String size = DomainUtils.encodeMemory( memory, unit );
+
+ this.setXmlElementAttributeValue( "size", "unit", unit );
+ this.setXmlElementValue( "size", size );
+ }
+
+ /**
+ * Creates a non-existent shared memory device as Libvirt XML device element.
+ *
+ * @param xmlNode Libvirt XML node of the Libvirt XML device that is created.
+ * @return created shared memory device instance.
+ */
+ public static Shmem createInstance( LibvirtXmlNode xmlNode )
+ {
+ return Shmem.newInstance( xmlNode );
+ }
+
+ /**
+ * Creates a shared memory device representing an existing Libvirt XML shared memory device
+ * element.
+ *
+ * @param xmlNode existing Libvirt XML shared memory device element.
+ * @return shared memory device instance.
+ */
+ public static Shmem newInstance( LibvirtXmlNode xmlNode )
+ {
+ return new Shmem( xmlNode );
+ }
+
+ /**
+ * Model of shared memory device.
+ *
+ * @author Manuel Bentele
+ * @version 1.0
+ */
+ public enum Model
+ {
+ // @formatter:off
+ IVSHMEM ( "ivshmem" ),
+ IVSHMEM_PLAIN ( "ivshmem-plain" ),
+ IVSHMEM_DOORBELL( "ivshmem-doorbell" );
+ // @formatter:on
+
+ /**
+ * Name of the shared memory device model.
+ */
+ private String model;
+
+ /**
+ * Creates shared memory device model.
+ *
+ * @param type valid name of the shared memory device model in a Libvirt domain XML document.
+ */
+ Model( String model )
+ {
+ this.model = model;
+ }
+
+ @Override
+ public String toString()
+ {
+ return this.model;
+ }
+
+ /**
+ * Creates shared memory device model from its name with error check.
+ *
+ * @param model name of the shared memory device model in a Libvirt domain XML document.
+ * @return valid shared memory 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
index 0f8861f..f3ee13f 100644
--- a/src/main/java/org/openslx/libvirt/domain/device/Video.java
+++ b/src/main/java/org/openslx/libvirt/domain/device/Video.java
@@ -71,7 +71,7 @@ public class Video extends Device
if ( model != null ) {
if ( model == Model.VIRTIO ) {
// only set acceleration on supported Virtio GPUs
- this.setXmlElementAttributeValue( "model/acceleration", "accel2d", acceleration );
+ this.setXmlElementAttributeValueYesNo( "model/acceleration", "accel2d", acceleration );
} else {
String errorMsg = new String(
"Video card model '" + model.toString() + "' does not support enabled 2D hardware acceleration." );
@@ -101,7 +101,7 @@ public class Video extends Device
if ( model == Model.VIRTIO ) {
// only set acceleration on supported Virtio GPUs
- this.setXmlElementAttributeValue( "model/acceleration", "accel3d", acceleration );
+ this.setXmlElementAttributeValueYesNo( "model/acceleration", "accel3d", acceleration );
} else {
String errorMsg = new String(
"Video card model '" + model.toString() + "' does not support enabled 3D hardware acceleration." );
@@ -109,6 +109,15 @@ public class Video extends Device
}
}
+ /**
+ * Disables the video device by setting the model to {@link Model#NONE}.
+ */
+ public void disable()
+ {
+ this.removeXmlElementChilds();
+ this.setModel( Model.NONE );
+ }
+
/**
* Creates a non-existent video device as Libvirt XML device element.
*
--
cgit v1.2.3-55-g7522
+ * 1d6b:0002
+ * 0461:4d22
+ * 046d:c312
+ *
+ */
+ private static final String DEVICE_DESCRIPTION_REGEX = "^([a-f0-9]{4}):([a-f0-9]{4})$";
+
+ /**
+ * Minimum value of a valid identifier from an USB device description.
+ */
+ private static final int DEVICE_DESCRIPTION_ID_MIN_VALUE = 0x0000;
+
+ /**
+ * Maximum value of a valid identifier from an USB device description.
+ */
+ private static final int DEVICE_DESCRIPTION_ID_MAX_VALUE = 0xffff;
+
+ /**
+ * Vendor identifier of the USB device.
+ */
+ final int vendorId;
+
+ /**
+ * Product identifier of the USB device.
+ */
+ final int productId;
+
+ /**
+ * Creates a new USB device description consisting of a USB vendor and product identifier.
+ *
+ * @param vendorId vendor identifier of the USB device.
+ * @param productId product identifier of the USB device.
+ *
+ * @throws throws IllegalArgumentException failed to validate the USB device description
+ * identifiers.
+ */
+ public HostdevUsbDeviceDescription( int vendorId, int productId ) throws IllegalArgumentException
+ {
+ HostdevUsbDeviceDescription.validateUsbDeviceDescriptionId( "PCI vendor ID", vendorId );
+ HostdevUsbDeviceDescription.validateUsbDeviceDescriptionId( "PCI device ID", productId );
+
+ this.vendorId = vendorId;
+ this.productId = productId;
+ }
+
+ /**
+ * Validates an USB device description ID (an USB vendor or product ID).
+ *
+ * @param idName name of the USB device description identifier.
+ * @param id value of the USB device description identifier that should be validated.
+ *
+ * @throws IllegalArgumentException failed to validate the USB device description identifier.
+ */
+ private static void validateUsbDeviceDescriptionId( final String idName, final int id )
+ throws IllegalArgumentException
+ {
+ if ( id < HostdevUsbDeviceDescription.DEVICE_DESCRIPTION_ID_MIN_VALUE ) {
+ throw new IllegalArgumentException(
+ "The " + idName + "must be larger or equal than "
+ + HostdevUsbDeviceDescription.DEVICE_DESCRIPTION_ID_MIN_VALUE );
+ } else if ( id > HostdevUsbDeviceDescription.DEVICE_DESCRIPTION_ID_MAX_VALUE ) {
+ throw new IllegalArgumentException(
+ "The " + idName + "must be smaller or equal than "
+ + HostdevUsbDeviceDescription.DEVICE_DESCRIPTION_ID_MAX_VALUE );
+ }
+ }
+
+ /**
+ * Returns the USB device vendor identifier.
+ *
+ * @return USB device vendor identifier.
+ */
+ public int getVendorId()
+ {
+ return this.vendorId;
+ }
+
+ /**
+ * Returns the USB vendor identifier as {@link String}.
+ *
+ * @return USB vendor identifier as {@link String}.
+ */
+ public String getVendorIdAsString()
+ {
+ return String.format( "%04x", HostdevUsbDeviceDescription.DEVICE_DESCRIPTION_ID_MAX_VALUE & this.getVendorId() );
+ }
+
+ /**
+ * Returns the USB device product identifier.
+ *
+ * @return USB device product identifier.
+ */
+ public int getProductId()
+ {
+ return this.productId;
+ }
+
+ /**
+ * Returns the USB device product identifier as {@link String}.
+ *
+ * @return USB device product identifier as {@link String}.
+ */
+ public String getProductIdAsString()
+ {
+ return String.format( "%04x", HostdevUsbDeviceDescription.DEVICE_DESCRIPTION_ID_MAX_VALUE & this.getProductId() );
+ }
+
+ /**
+ * Creates a new USB device description parsed from a {@link String}.
+ *