summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/util/vm/DiskImage.java
blob: 80eec2af07b7f72a8e493882fd593da21dd39037 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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;
	}

}