summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/util/vm/DiskImage.java
blob: 80eec2af07b7f72a8e493882fd593da21dd39037 (plain) (tree)
1
2
3
4
5
6
7
8
9







                                                 
                             




                      
                                                          




                                                         
                                                               







                                                       
                                                                                   


                                            







                                                                                
                                            
                                                            






                                           
                                        
                                        
                                      
                                   
 

                                                                                


                                                                                   
                                                           




                                                                                             






                                                                                           
                                                       





                                                                           











                                                           
                                                                            


                                     

                                                                               

                                                                               







                                                                                   
package org.openslx.util.vm;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

import org.openslx.bwlp.thrift.iface.Virtualizer;
import org.openslx.util.Util;

public class DiskImage
{

	/**
	 * Big endian representation of the 4 bytes 'KDMV'
	 */
	private static final int VMDK_MAGIC = 0x4b444d56;

	public enum ImageFormat
	{
		VMDK( "vmdk" ), QCOW2( "qcow2" ), VDI( "vdi" );

		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( "vmware" ) )
				return VMDK;
			if ( virtId.equals( "virtualbox" ) )
				return VDI;
			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 DiskImage( File disk ) throws FileNotFoundException, IOException,
			UnknownImageFormatException
	{
		// For now we only support VMDK...
		try ( RandomAccessFile file = new RandomAccessFile( disk, "r" ) ) {
			if ( file.readInt() != VMDK_MAGIC )
				throw new UnknownImageFormatException();
			file.seek( 512 );
			byte[] buffer = new byte[ 2048 ];
			file.readFully( buffer );
			VmwareConfig config = new VmwareConfig( buffer, findNull( buffer ) );
			subFormat = config.get( "createType" );
			String parent = config.get( "parentCID" );
			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 );
			}
		}
	}

	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;
	}

}