diff options
Diffstat (limited to 'src/main/java/org/openslx/util/vm/DiskImage.java')
-rw-r--r-- | src/main/java/org/openslx/util/vm/DiskImage.java | 208 |
1 files changed, 0 insertions, 208 deletions
diff --git a/src/main/java/org/openslx/util/vm/DiskImage.java b/src/main/java/org/openslx/util/vm/DiskImage.java deleted file mode 100644 index 15b3800..0000000 --- a/src/main/java/org/openslx/util/vm/DiskImage.java +++ /dev/null @@ -1,208 +0,0 @@ -package org.openslx.util.vm; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.Arrays; - -import org.apache.log4j.Logger; -import org.openslx.bwlp.thrift.iface.Virtualizer; -import org.openslx.thrifthelper.TConst; -import org.openslx.util.Util; - -public class DiskImage -{ - private static final Logger LOGGER = Logger.getLogger( DiskImage.class ); - /** - * Big endian representation of the 4 bytes 'KDMV' - */ - private static final int VMDK_MAGIC = 0x4b444d56; - private static final int VDI_MAGIC = 0x7f10dabe; - /** - * Big endian representation of the 4 bytes 'QFI\xFB' - */ - private static final int QEMU_MAGIC = 0x514649fb; - - public enum ImageFormat - { - VMDK( "vmdk" ), QCOW2( "qcow2" ), VDI( "vdi" ), - DOCKER("dockerfile"); - - public final String extension; - - private ImageFormat( String extension ) - { - this.extension = extension; - } - - public static ImageFormat defaultForVirtualizer( Virtualizer virt ) - { - if ( virt == null ) - return null; - return defaultForVirtualizer( virt.virtId ); - } - - public static ImageFormat defaultForVirtualizer( String virtId ) - { - if ( virtId == null ) - return null; - if ( virtId.equals( TConst.VIRT_VMWARE ) ) - return VMDK; - if ( virtId.equals( TConst.VIRT_VIRTUALBOX ) ) - return VDI; - if ( virtId.equals( TConst.VIRT_QEMU ) ) - return QCOW2; - if ( virtId.equals( TConst.VIRT_DOCKER) ) - return DOCKER; - return null; - } - } - - public final boolean isStandalone; - public final boolean isCompressed; - public final boolean isSnapshot; - public final ImageFormat format; - public final String subFormat; - public final int hwVersion; - public final String diskDescription; - - public ImageFormat getImageFormat() - { - return format; - } - - public DiskImage( File disk ) throws FileNotFoundException, IOException, UnknownImageFormatException - { - LOGGER.debug( "Validating disk file: " + disk.getAbsolutePath() ); - try ( RandomAccessFile file = new RandomAccessFile( disk, "r" ) ) { - // vmdk - boolean isVmdkMagic = ( file.readInt() == VMDK_MAGIC ); - if ( isVmdkMagic || file.length() < 4096 ) { - if ( isVmdkMagic ) { - file.seek( 512 ); - } else { - file.seek( 0 ); - } - byte[] buffer = new byte[ (int)Math.min( 2048, file.length() ) ]; - file.readFully( buffer ); - VmwareConfig config; - try { - config = new VmwareConfig( buffer, findNull( buffer ) ); - } catch ( UnsupportedVirtualizerFormatException e ) { - config = null; - } - if ( config != null ) { - String sf = config.get( "createType" ); - String parent = config.get( "parentCID" ); - if ( sf != null || parent != null ) { - subFormat = sf; - this.isStandalone = isStandaloneCreateType( subFormat, parent ); - this.isCompressed = subFormat != null && subFormat.equalsIgnoreCase( "streamOptimized" ); - this.isSnapshot = parent != null && !parent.equalsIgnoreCase( "ffffffff" ); - this.format = ImageFormat.VMDK; - String hwv = config.get( "ddb.virtualHWVersion" ); - if ( hwv == null ) { - this.hwVersion = 10; - } else { - this.hwVersion = Util.parseInt( hwv, 10 ); - } - this.diskDescription = null; - return; - } - } - } - // Format spec from: https://forums.virtualbox.org/viewtopic.php?t=8046 - // First 64 bytes are the opening tag: <<< .... >>> - // which we don't care about, then comes the VDI signature - file.seek( 64 ); - if ( file.readInt() == VDI_MAGIC ) { - // skip the next 4 ints as they don't interest us: - // - VDI version - // - size of header, strangely irrelevant? - // - image type, 1 for dynamic allocated storage, 2 for fixed size - // - image flags, seem to be always 00 00 00 00 - file.skipBytes( 4 * 4 ); - - // next 256 bytes are image description - byte[] imageDesc = new byte[ 256 ]; - file.readFully( imageDesc ); - // next sections are irrelevant (int if not specified): - // - offset blocks - // - offset data - // - cylinders - // - heads - // - sectors - // - sector size - // - <unused> - // - disk size (long = 8 bytes) - // - block size - // - block extra data - // - blocks in hdd - // - blocks allocated - file.skipBytes( 4 * 13 ); - - // now it gets interesting, UUID of VDI - byte[] diskUuid = new byte[ 16 ]; - file.readFully( diskUuid ); - // last snapshot uuid, mostly uninteresting since we don't support snapshots -> skip 16 bytes - // TODO: meaning of "uuid link"? for now, skip 16 - file.skipBytes( 32 ); - - // parent uuid, indicator if this VDI is a snapshot or not - byte[] parentUuid = new byte[ 16 ]; - file.readFully( parentUuid ); - byte[] zeroUuid = new byte[ 16 ]; - Arrays.fill( zeroUuid, (byte)0 ); - this.isSnapshot = !Arrays.equals( parentUuid, zeroUuid ); - // VDI does not seem to support split VDI files so always standalone - this.isStandalone = true; - // compression is done by sparsifying the disk files, there is no flag for it - this.isCompressed = false; - this.format = ImageFormat.VDI; - this.subFormat = null; - this.diskDescription = new String( imageDesc ); - this.hwVersion = 0; - return; - } - - // TODO: qcow - file.seek( 0 ); - if ( file.readInt() == QEMU_MAGIC ) { - // dummy values - this.isStandalone = true; - this.isCompressed = false; - this.isSnapshot = false; - this.format = ImageFormat.QCOW2; - this.subFormat = null; - this.diskDescription = null; - this.hwVersion = 0; - return; - } - } - throw new UnknownImageFormatException(); - } - - private int findNull( byte[] buffer ) - { - for ( int i = 0; i < buffer.length; ++i ) { - if ( buffer[i] == 0 ) - return i; - } - return buffer.length; - } - - private boolean isStandaloneCreateType( String type, String parent ) - { - if ( type == null ) - return false; - if ( parent != null && !parent.equalsIgnoreCase( "ffffffff" ) ) - return false; - return type.equalsIgnoreCase( "streamOptimized" ) || type.equalsIgnoreCase( "monolithicSparse" ); - } - - public static class UnknownImageFormatException extends Exception - { - private static final long serialVersionUID = -6647935235475007171L; - } -} |