summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/vm/disk
diff options
context:
space:
mode:
authorManuel Bentele2021-05-19 09:48:37 +0200
committerManuel Bentele2021-05-19 09:48:37 +0200
commit2cdee4f4023ec003fe65cfa85ebb654f1446ff59 (patch)
tree39c025839c6fa2b1e58e12cd9dc29df71dec5cc5 /src/main/java/org/openslx/vm/disk
parentMerge branch 'feature/qemu-integration' (diff)
downloadmaster-sync-shared-2cdee4f4023ec003fe65cfa85ebb654f1446ff59.tar.gz
master-sync-shared-2cdee4f4023ec003fe65cfa85ebb654f1446ff59.tar.xz
master-sync-shared-2cdee4f4023ec003fe65cfa85ebb654f1446ff59.zip
Rename 'vm.disk' package to 'virtualization.disk'
Diffstat (limited to 'src/main/java/org/openslx/vm/disk')
-rw-r--r--src/main/java/org/openslx/vm/disk/DiskImage.java253
-rw-r--r--src/main/java/org/openslx/vm/disk/DiskImageException.java25
-rw-r--r--src/main/java/org/openslx/vm/disk/DiskImageQcow2.java232
-rw-r--r--src/main/java/org/openslx/vm/disk/DiskImageUtils.java144
-rw-r--r--src/main/java/org/openslx/vm/disk/DiskImageVdi.java105
-rw-r--r--src/main/java/org/openslx/vm/disk/DiskImageVmdk.java281
6 files changed, 0 insertions, 1040 deletions
diff --git a/src/main/java/org/openslx/vm/disk/DiskImage.java b/src/main/java/org/openslx/vm/disk/DiskImage.java
deleted file mode 100644
index cf7df83..0000000
--- a/src/main/java/org/openslx/vm/disk/DiskImage.java
+++ /dev/null
@@ -1,253 +0,0 @@
-package org.openslx.vm.disk;
-
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.List;
-import java.util.function.Predicate;
-
-import org.openslx.bwlp.thrift.iface.Virtualizer;
-import org.openslx.thrifthelper.TConst;
-import org.openslx.util.Util;
-import org.openslx.virtualization.Version;
-
-/**
- * Disk image for virtual machines.
- *
- * @implNote This class is the abstract base class to implement various specific disk images (like
- * QCOW2 or VMDK).
- *
- * @author Manuel Bentele
- * @version 1.0
- */
-public abstract class DiskImage implements Closeable
-{
- /**
- * Stores the image file of the disk.
- */
- private RandomAccessFile diskImage = null;
-
- /**
- * Creates a new disk image from an existing image file with a known disk image format.
- *
- * @param diskImage file to a disk storing the image content.
- *
- * @implNote Do not use this constructor to create a new disk image from an image file with
- * unknown disk image format. Instead, use the factory method
- * {@link #newInstance(File)} to probe unknown disk image files before creation.
- */
- protected DiskImage( RandomAccessFile diskImage )
- {
- this.diskImage = diskImage;
- }
-
- /**
- * Returns the disk image file.
- *
- * @return the disk image file.
- */
- protected RandomAccessFile getDiskImage()
- {
- return this.diskImage;
- }
-
- /**
- * Checks whether disk image is standalone and do not depend on other files (e.g. snapshot
- * files).
- *
- * @return state whether disk image is standalone or not.
- *
- * @throws DiskImageException unable to check if disk image is standalone.
- */
- public abstract boolean isStandalone() throws DiskImageException;
-
- /**
- * Checks whether disk image is compressed.
- *
- * @return state whether disk image is compressed or not.
- *
- * @throws DiskImageException unable to check whether disk image is compressed.
- */
- public abstract boolean isCompressed() throws DiskImageException;
-
- /**
- * Checks whether disk image is a snapshot.
- *
- * @return state whether disk image is a snapshot or not.
- *
- * @throws DiskImageException unable to check whether disk image is a snapshot.
- */
- public abstract boolean isSnapshot() throws DiskImageException;
-
- /**
- * Returns the version of the disk image format.
- *
- * @return version of the disk image format.
- *
- * @throws DiskImageException unable to obtain version of the disk image format.
- */
- public abstract Version getVersion() throws DiskImageException;
-
- /**
- * Returns the disk image description.
- *
- * @return description of the disk image.
- *
- * @throws DiskImageException unable to obtain description of the disk image.
- */
- public abstract String getDescription() throws DiskImageException;
-
- /**
- * Returns the format of the disk image.
- *
- * @return format of the disk image.
- */
- public abstract ImageFormat getFormat();
-
- /**
- * Creates a new disk image from an existing image file with an unknown disk image format.
- *
- * @param diskImagePath file to a disk storing the image content.
- * @return concrete disk image instance.
- *
- * @throws FileNotFoundException cannot find specified disk image file.
- * @throws IOException cannot access the content of the disk image file.
- * @throws DiskImageException disk image file has an invalid and unknown disk image format.
- */
- public static DiskImage newInstance( File diskImagePath )
- throws FileNotFoundException, IOException, DiskImageException
- {
- // Make sure this doesn't escape the scope, in case instantiation fails - we can't know when the GC
- // would come along and close this file, which is problematic on Windows (blocking rename/delete)
- final RandomAccessFile fileHandle = new RandomAccessFile( diskImagePath, "r" );
-
- try {
- if ( DiskImageQcow2.probe( fileHandle ) ) {
- return new DiskImageQcow2( fileHandle );
- } else if ( DiskImageVdi.probe( fileHandle ) ) {
- return new DiskImageVdi( fileHandle );
- } else if ( DiskImageVmdk.probe( fileHandle ) ) {
- return new DiskImageVmdk( fileHandle );
- }
- } catch ( Exception e ) {
- Util.safeClose( fileHandle );
- throw e;
- }
- Util.safeClose( fileHandle );
- final String errorMsg = new String( "File '" + diskImagePath.getAbsolutePath() + "' is not a valid disk image!" );
- throw new DiskImageException( errorMsg );
- }
-
- @Override
- public void close() throws IOException
- {
- Util.safeClose( diskImage );
- }
-
- @Override
- protected void finalize() throws Throwable
- {
- close();
- }
-
- /**
- * Format of a disk image.
- *
- * @author Manuel Bentele
- * @version 1.0
- */
- public enum ImageFormat
- {
- // @formatter:off
- NONE ( "none" ),
- QCOW2( "qcow2" ),
- VDI ( "vdi" ),
- VMDK ( "vmdk" );
- // @formatter:on
-
- /**
- * Stores filename extension of the disk image format.
- */
- public final String extension;
-
- /**
- * Create new disk image format.
- *
- * @param extension filename extension of the disk image format.
- */
- ImageFormat( String extension )
- {
- this.extension = extension;
- }
-
- /**
- * Returns filename extension of the disk image.
- *
- * @return filename extension of the disk image.
- */
- public String getExtension()
- {
- return this.extension;
- }
-
- /**
- * Checks if the disk image format is supported by a virtualizer.
- *
- * @param supportedImageFormats list of supported disk image formats of a virtualizer.
- * @return <code>true</code> if image type is supported by the virtualizer; otherwise
- * <code>false</code>.
- */
- public boolean isSupportedbyVirtualizer( List<ImageFormat> supportedImageFormats )
- {
- Predicate<ImageFormat> matchDiskFormat = supportedImageFormat -> supportedImageFormat.toString()
- .equalsIgnoreCase( this.toString() );
- return supportedImageFormats.stream().anyMatch( matchDiskFormat );
- }
-
- /**
- * Returns default (preferred) disk image format for the specified virtualizer.
- *
- * @param virt virtualizer for that the default disk image should be determined.
- * @return default (preferred) disk image format.
- */
- public static ImageFormat defaultForVirtualizer( Virtualizer virt )
- {
- if ( virt == null ) {
- return null;
- } else {
- return ImageFormat.defaultForVirtualizer( virt.virtId );
- }
- }
-
- /**
- * Returns default (preferred) disk image format for the specified virtualizer.
- *
- * @param virtId ID of a virtualizer for that the default disk image should be determined.
- * @return default (preferred) disk image format.
- */
- public static ImageFormat defaultForVirtualizer( String virtId )
- {
- ImageFormat imgFormat = null;
-
- if ( TConst.VIRT_DOCKER.equals( virtId ) ) {
- imgFormat = NONE;
- } else if ( TConst.VIRT_QEMU.equals( virtId ) ) {
- imgFormat = QCOW2;
- } else if ( TConst.VIRT_VIRTUALBOX.equals( virtId ) ) {
- imgFormat = VDI;
- } else if ( TConst.VIRT_VMWARE.equals( virtId ) ) {
- imgFormat = VMDK;
- }
-
- return imgFormat;
- }
-
- @Override
- public String toString()
- {
- return this.getExtension();
- }
- }
-}
diff --git a/src/main/java/org/openslx/vm/disk/DiskImageException.java b/src/main/java/org/openslx/vm/disk/DiskImageException.java
deleted file mode 100644
index a98f963..0000000
--- a/src/main/java/org/openslx/vm/disk/DiskImageException.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.openslx.vm.disk;
-
-/**
- * An exception for faulty disk image handling.
- *
- * @author Manuel Bentele
- * @version 1.0
- */
-public class DiskImageException extends Exception
-{
- /**
- * Version number for serialization.
- */
- private static final long serialVersionUID = 5464286488698331909L;
-
- /**
- * Creates a disk image exception including an error message.
- *
- * @param errorMsg message to describe a disk image error.
- */
- public DiskImageException( String errorMsg )
- {
- super( errorMsg );
- }
-}
diff --git a/src/main/java/org/openslx/vm/disk/DiskImageQcow2.java b/src/main/java/org/openslx/vm/disk/DiskImageQcow2.java
deleted file mode 100644
index e569708..0000000
--- a/src/main/java/org/openslx/vm/disk/DiskImageQcow2.java
+++ /dev/null
@@ -1,232 +0,0 @@
-package org.openslx.vm.disk;
-
-import java.io.RandomAccessFile;
-
-import org.openslx.virtualization.Version;
-
-/**
- * QCOW2 disk image for virtual machines.
- *
- * A QCOW2 disk image consists of a header, one L1 table and several L2 tables used for lookup data
- * clusters in the file via a two-level lookup. The QCOW2 header contains the following fields:
- *
- * <pre>
- * 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
- * </pre>
- *
- * @author Manuel Bentele
- * @version 1.0
- */
-public class DiskImageQcow2 extends DiskImage
-{
- /**
- * Big endian representation of the big endian QCOW2 magic bytes <code>QFI\xFB</code>.
- */
- private static final int QCOW2_MAGIC = 0x514649fb;
-
- /**
- * Creates a new QCOW2 disk image from an existing QCOW2 image file.
- *
- * @param diskImage file to a QCOW2 disk storing the image content.
- */
- DiskImageQcow2( RandomAccessFile diskImage )
- {
- super( diskImage );
- }
-
- /**
- * Probe specified file with unknown format to be a QCOW2 disk image file.
- *
- * @param diskImage file with unknown format that should be probed.
- * @return state whether file is a QCOW2 disk image or not.
- *
- * @throws DiskImageException cannot probe specified file with unknown format.
- */
- public static boolean probe( RandomAccessFile diskImage ) throws DiskImageException
- {
- final boolean isQcow2ImageFormat;
-
- // goto the beginning of the disk image to read the disk image
- final int diskImageMagic = DiskImageUtils.readInt( diskImage, 0 );
-
- // check if disk image's magic bytes can be found
- if ( diskImageMagic == DiskImageQcow2.QCOW2_MAGIC ) {
- isQcow2ImageFormat = true;
- } else {
- isQcow2ImageFormat = false;
- }
-
- return isQcow2ImageFormat;
- }
-
- @Override
- public boolean isStandalone() throws DiskImageException
- {
- final RandomAccessFile diskFile = this.getDiskImage();
- final long qcowBackingFileOffset = DiskImageUtils.readLong( diskFile, 8 );
- final boolean qcowStandalone;
-
- // check if QCOW2 image does not refer to any backing file
- if ( qcowBackingFileOffset == 0 ) {
- qcowStandalone = true;
- } else {
- qcowStandalone = false;
- }
-
- return qcowStandalone;
- }
-
- @Override
- public boolean isCompressed() throws DiskImageException
- {
- final RandomAccessFile diskFile = this.getDiskImage();
- final boolean qcowUseExtendedL2;
- boolean qcowCompressed = false;
-
- // check if QCOW2 image uses extended L2 tables
- // extended L2 tables are only possible in QCOW2 version 3 header format
- if ( this.getVersion().getMajor() >= Short.valueOf( "3" ) ) {
- // read incompatible feature bits
- final long qcowIncompatibleFeatures = DiskImageUtils.readLong( diskFile, 72 );
-
- // support for extended L2 tables is enabled if bit 4 is set
- qcowUseExtendedL2 = ( ( ( qcowIncompatibleFeatures & 0x000000000010 ) >>> 4 ) == 1 );
- } else {
- qcowUseExtendedL2 = false;
- }
-
- // get number of entries in L1 table
- final int qcowL1TableSize = DiskImageUtils.readInt( diskFile, 36 );
-
- // 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
- final int qcowClusterBits = DiskImageUtils.readInt( diskFile, 20 );
- 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
- final long qcowL1TableOffset = DiskImageUtils.readLong( diskFile, 40 );
-
- // 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
- final long qcowL1TableEntryOffset = qcowL1TableOffset + ( i * qcowL1TableEntrySize );
- final long qcowL1TableEntry = DiskImageUtils.readLong( diskFile, qcowL1TableEntryOffset );
-
- // extract offset (bits 9 - 55) from L1 table entry
- final 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
- final long qcowL2TableEntryOffset = qcowL2TableOffset + ( j * qcowL2TableEntrySize );
- final long qcowL2TableEntry = DiskImageUtils.readLong( diskFile, qcowL2TableEntryOffset );
-
- // 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;
- }
-
- return qcowCompressed;
- }
-
- @Override
- public boolean isSnapshot() throws DiskImageException
- {
- final RandomAccessFile diskFile = this.getDiskImage();
- final int qcowNumSnapshots = DiskImageUtils.readInt( diskFile, 56 );
- final boolean qcowSnapshot;
-
- // check if QCOW2 image contains at least one snapshot
- if ( qcowNumSnapshots == 0 ) {
- qcowSnapshot = true;
- } else {
- qcowSnapshot = false;
- }
-
- return qcowSnapshot;
- }
-
- @Override
- public Version getVersion() throws DiskImageException
- {
- final RandomAccessFile diskFile = this.getDiskImage();
- final int qcowVersion = DiskImageUtils.readInt( diskFile, 4 );
-
- // check QCOW2 file format version
- if ( qcowVersion < 2 || qcowVersion > 3 ) {
- // QCOW2 disk image does not contain a valid QCOW2 version
- final String errorMsg = new String( "Invalid QCOW2 version in header found!" );
- throw new DiskImageException( errorMsg );
- }
-
- return new Version( Integer.valueOf( qcowVersion ).shortValue() );
- }
-
- @Override
- public String getDescription() throws DiskImageException
- {
- // QCOW2 disk image format does not support any disk description
- return null;
- }
-
- @Override
- public ImageFormat getFormat()
- {
- return ImageFormat.QCOW2;
- }
-}
diff --git a/src/main/java/org/openslx/vm/disk/DiskImageUtils.java b/src/main/java/org/openslx/vm/disk/DiskImageUtils.java
deleted file mode 100644
index ccb053f..0000000
--- a/src/main/java/org/openslx/vm/disk/DiskImageUtils.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.openslx.vm.disk;
-
-import java.io.IOException;
-import java.io.RandomAccessFile;
-
-/**
- * Utilities to parse disk image format elements and control versions of disk images.
- *
- * @author Manuel Bentele
- * @version 1.0
- */
-public class DiskImageUtils
-{
- /**
- * Returns the size of a specified disk image file.
- *
- * @param diskImage file to a disk storing the image content.
- * @return size of the disk image file in bytes.
- *
- * @throws DiskImageException unable to obtain the size of the disk image file.
- */
- public static long getImageSize( RandomAccessFile diskImage ) throws DiskImageException
- {
- final long imageSize;
-
- try {
- imageSize = diskImage.length();
- } catch ( IOException e ) {
- throw new DiskImageException( e.getLocalizedMessage() );
- }
-
- return imageSize;
- }
-
- /**
- * Reads two bytes ({@link Short}) at a given <code>offset</code> from the specified disk image
- * file.
- *
- * @param diskImage file to a disk storing the image content.
- * @param offset offset in bytes for reading the two bytes.
- * @return value of the two bytes from the disk image file as {@link Short}.
- *
- * @throws DiskImageException unable to read two bytes from the disk image file.
- */
- public static short readShort( RandomAccessFile diskImage, long offset ) throws DiskImageException
- {
- final long imageSize = DiskImageUtils.getImageSize( diskImage );
- short value = 0;
-
- if ( imageSize >= ( offset + Short.BYTES ) ) {
- try {
- diskImage.seek( offset );
- value = diskImage.readShort();
- } catch ( IOException e ) {
- throw new DiskImageException( e.getLocalizedMessage() );
- }
- }
-
- return value;
- }
-
- /**
- * Reads four bytes ({@link Integer}) at a given <code>offset</code> from the specified disk
- * image file.
- *
- * @param diskImage file to a disk storing the image content.
- * @param offset offset in bytes for reading the four bytes.
- * @return value of the four bytes from the disk image file as {@link Integer}.
- *
- * @throws DiskImageException unable to read four bytes from the disk image file.
- */
- public static int readInt( RandomAccessFile diskImage, long offset ) throws DiskImageException
- {
- final long imageSize = DiskImageUtils.getImageSize( diskImage );
- int value = 0;
-
- if ( imageSize >= ( offset + Integer.BYTES ) ) {
- try {
- diskImage.seek( offset );
- value = diskImage.readInt();
- } catch ( IOException e ) {
- throw new DiskImageException( e.getLocalizedMessage() );
- }
- }
-
- return value;
- }
-
- /**
- * Reads eight bytes ({@link Long}) at a given <code>offset</code> from the specified disk image
- * file.
- *
- * @param diskImage file to a disk storing the image content.
- * @param offset offset in bytes for reading the eight bytes.
- * @return value of the eight bytes from the disk image file as {@link Long}.
- *
- * @throws DiskImageException unable to read eight bytes from the disk image file.
- */
- public static long readLong( RandomAccessFile diskImage, long offset ) throws DiskImageException
- {
- final long imageSize = DiskImageUtils.getImageSize( diskImage );
- long value = 0;
-
- if ( imageSize >= ( offset + Long.BYTES ) ) {
- try {
- diskImage.seek( offset );
- value = diskImage.readLong();
- } catch ( IOException e ) {
- throw new DiskImageException( e.getLocalizedMessage() );
- }
- }
-
- return value;
- }
-
- /**
- * Reads a variable number of bytes (<code>numBytes</code>) at a given <code>offset</code> from the specified disk image file.
- *
- * @param diskImage file to a disk storing the image content.
- * @param offset offset in bytes for reading <code>numBytes</code> bytes.
- * @param numBytes number of bytes to read at <code>offset</code>.
- * @return read bytes from the disk image file as {@link String}.
- *
- * @throws DiskImageException unable to read two bytes from the disk image file.
- */
- public static String readBytesAsString( RandomAccessFile diskImage, long offset, int numBytes )
- throws DiskImageException
- {
- final long imageSize = DiskImageUtils.getImageSize( diskImage );
- byte values[] = {};
-
- if ( imageSize >= ( offset + numBytes ) ) {
- try {
- diskImage.seek( offset );
- values = new byte[ numBytes ];
- diskImage.readFully( values );
- } catch ( IOException e ) {
- throw new DiskImageException( e.getLocalizedMessage() );
- }
- }
-
- return new String( values );
- }
-}
diff --git a/src/main/java/org/openslx/vm/disk/DiskImageVdi.java b/src/main/java/org/openslx/vm/disk/DiskImageVdi.java
deleted file mode 100644
index 37e45c1..0000000
--- a/src/main/java/org/openslx/vm/disk/DiskImageVdi.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.openslx.vm.disk;
-
-import java.io.RandomAccessFile;
-
-import org.openslx.virtualization.Version;
-
-/**
- * VDI disk image for virtual machines.
- *
- * @author Manuel Bentele
- * @version 1.0
- */
-public class DiskImageVdi extends DiskImage
-{
- /**
- * Big endian representation of the little endian VDI magic bytes (signature).
- */
- private static final int VDI_MAGIC = 0x7f10dabe;
-
- /**
- * Creates a new VDI disk image from an existing VDI image file.
- *
- * @param diskImage file to a VDI disk storing the image content.
- */
- DiskImageVdi( RandomAccessFile diskImage )
- {
- super( diskImage );
- }
-
- /**
- * Probe specified file with unknown format to be a VDI disk image file.
- *
- * @param diskImage file with unknown format that should be probed.
- * @return state whether file is a VDI disk image or not.
- *
- * @throws DiskImageException cannot probe specified file with unknown format.
- */
- public static boolean probe( RandomAccessFile diskImage ) throws DiskImageException
- {
- final boolean isVdiImageFormat;
-
- // goto the beginning of the disk image to read the magic bytes
- // skip first 64 bytes (opening tag)
- final int diskImageMagic = DiskImageUtils.readInt( diskImage, 64 );
-
- // check if disk image's magic bytes can be found
- if ( diskImageMagic == DiskImageVdi.VDI_MAGIC ) {
- isVdiImageFormat = true;
- } else {
- isVdiImageFormat = false;
- }
-
- return isVdiImageFormat;
- }
-
- @Override
- public boolean isStandalone() throws DiskImageException
- {
- // VDI does not seem to support split VDI files, so VDI files are always standalone
- return true;
- }
-
- @Override
- public boolean isCompressed() throws DiskImageException
- {
- // compression is done by sparsifying the disk files, there is no flag for it
- return false;
- }
-
- @Override
- public boolean isSnapshot() throws DiskImageException
- {
- final RandomAccessFile diskFile = this.getDiskImage();
-
- // if parent UUID is set, the VDI file is a snapshot
- final String parentUuid = DiskImageUtils.readBytesAsString( diskFile, 440, 16 );
- final String zeroUuid = new String( new byte[ 16 ] );
-
- return !zeroUuid.equals( parentUuid );
- }
-
- @Override
- public Version getVersion() throws DiskImageException
- {
- final RandomAccessFile diskFile = this.getDiskImage();
-
- final short vdiVersionMajor = Short.reverseBytes( DiskImageUtils.readShort( diskFile, 68 ) );
- final short vdiVersionMinor = Short.reverseBytes( DiskImageUtils.readShort( diskFile, 70 ) );
-
- return new Version( vdiVersionMajor, vdiVersionMinor );
- }
-
- @Override
- public String getDescription() throws DiskImageException
- {
- final RandomAccessFile diskFile = this.getDiskImage();
- return DiskImageUtils.readBytesAsString( diskFile, 84, 256 );
- }
-
- @Override
- public ImageFormat getFormat()
- {
- return ImageFormat.VDI;
- }
-}
diff --git a/src/main/java/org/openslx/vm/disk/DiskImageVmdk.java b/src/main/java/org/openslx/vm/disk/DiskImageVmdk.java
deleted file mode 100644
index 75a2bac..0000000
--- a/src/main/java/org/openslx/vm/disk/DiskImageVmdk.java
+++ /dev/null
@@ -1,281 +0,0 @@
-package org.openslx.vm.disk;
-
-import java.io.RandomAccessFile;
-
-import org.openslx.util.Util;
-import org.openslx.virtualization.configuration.VirtualizationConfigurationVmwareFileFormat;
-import org.openslx.virtualization.Version;
-import org.openslx.virtualization.configuration.VirtualizationConfigurationException;
-
-/**
- * VMDK (sparse extent) disk image for virtual machines.
- *
- * @author Manuel Bentele
- * @version 1.0
- */
-public class DiskImageVmdk extends DiskImage
-{
- /**
- * Big endian representation of the little endian magic bytes <code>KDMV</code>.
- */
- private static final int VMDK_MAGIC = 0x4b444d56;
-
- /**
- * Size of a VMDK disk image data cluster in bytes.
- */
- private static final int VMDK_SECTOR_SIZE = 512;
-
- /**
- * Default hardware version of a VMDK disk image.
- */
- private static final int VMDK_DEFAULT_HW_VERSION = 10;
-
- /**
- * Stores disk configuration if VMDK disk image contains an embedded descriptor file.
- */
- private final VirtualizationConfigurationVmwareFileFormat vmdkConfig;
-
- /**
- * Creates a new VMDK disk image from an existing VMDK image file.
- *
- * @param diskImage file to a VMDK disk storing the image content.
- *
- * @throws DiskImageException parsing of the VMDK's embedded descriptor file failed.
- */
- DiskImageVmdk( RandomAccessFile diskImage ) throws DiskImageException
- {
- super( diskImage );
-
- this.vmdkConfig = this.parseVmdkConfig();
- }
-
- /**
- * Probe specified file with unknown format to be a VMDK disk image file.
- *
- * @param diskImage file with unknown format that should be probed.
- * @return state whether file is a VMDK disk image or not.
- *
- * @throws DiskImageException cannot probe specified file with unknown format.
- */
- public static boolean probe( RandomAccessFile diskImage ) throws DiskImageException
- {
- final boolean isVmdkImageFormat;
-
- // goto the beginning of the disk image to read the magic bytes
- final int diskImageMagic = DiskImageUtils.readInt( diskImage, 0 );
-
- // check if disk image's magic bytes can be found
- if ( diskImageMagic == DiskImageVmdk.VMDK_MAGIC ) {
- isVmdkImageFormat = true;
- } else {
- isVmdkImageFormat = false;
- }
-
- return isVmdkImageFormat;
- }
-
- /**
- * Returns the creation type from the VMDK's embedded descriptor file.
- *
- * @return creation type from the VMDK's embedded descriptor file.
- */
- private String getCreationType()
- {
- final VirtualizationConfigurationVmwareFileFormat vmdkConfig = this.getVmdkConfig();
- final String vmdkCreationType;
-
- if ( vmdkConfig == null ) {
- // VMDK disk image does not contain any descriptor file
- // assume that the file is not stand alone
- vmdkCreationType = null;
- } else {
- // VMDK disk image contains a descriptor file
- // get creation type from the content of the descriptor file
- vmdkCreationType = this.vmdkConfig.get( "createType" );
- }
-
- return vmdkCreationType;
- }
-
- /**
- * Parse the configuration of the VMDK's embedded descriptor file.
- *
- * @return parsed configuration of the VMDK's embedded descriptor file.
- *
- * @throws DiskImageException parsing of the VMDK's embedded descriptor file failed.
- */
- protected VirtualizationConfigurationVmwareFileFormat parseVmdkConfig() throws DiskImageException
- {
- final RandomAccessFile diskFile = this.getDiskImage();
- final VirtualizationConfigurationVmwareFileFormat vmdkConfig;
-
- // get offset and size of descriptor file embedded into the VMDK disk image
- final long vmdkDescriptorSectorOffset = Long.reverseBytes( DiskImageUtils.readLong( diskFile, 28 ) );
- final long vmdkDescriptorSectorSize = Long.reverseBytes( DiskImageUtils.readLong( diskFile, 36 ) );
-
- if ( vmdkDescriptorSectorOffset > 0 ) {
- // get content of descriptor file embedded into the VMDK disk image
- final long vmdkDescriptorOffset = vmdkDescriptorSectorOffset * DiskImageVmdk.VMDK_SECTOR_SIZE;
- final long vmdkDescriptorSizeMax = vmdkDescriptorSectorSize * DiskImageVmdk.VMDK_SECTOR_SIZE;
- final String descriptorStr = DiskImageUtils.readBytesAsString( diskFile, vmdkDescriptorOffset,
- Long.valueOf( vmdkDescriptorSizeMax ).intValue() );
-
- // get final length of the content within the sectors to be able to trim all 'zero' characters
- final int vmdkDescriptorSize = descriptorStr.indexOf( 0 );
-
- // if final length of the content is invalid, throw an exception
- if ( vmdkDescriptorSize > vmdkDescriptorSizeMax || vmdkDescriptorSize < 0 ) {
- final String errorMsg = new String( "Embedded descriptor size in VMDK disk image is invalid!" );
- throw new DiskImageException( errorMsg );
- }
-
- // trim all 'zero' characters at the end of the descriptor content to avoid errors during parsing
- final String configStr = descriptorStr.substring( 0, vmdkDescriptorSize );
-
- // create configuration instance from content of the descriptor file
- try {
- vmdkConfig = new VirtualizationConfigurationVmwareFileFormat( configStr.getBytes(), vmdkDescriptorSize );
- } catch ( VirtualizationConfigurationException e ) {
- throw new DiskImageException( e.getLocalizedMessage() );
- }
- } else {
- // there is no descriptor file embedded into the VMDK disk image
- vmdkConfig = null;
- }
-
- return vmdkConfig;
- }
-
- /**
- * Returns parsed configuration of the VMDK's embedded descriptor file.
- *
- * @return parsed configuration of the VMDK's embedded descriptor file.
- */
- protected VirtualizationConfigurationVmwareFileFormat getVmdkConfig()
- {
- return this.vmdkConfig;
- }
-
- /**
- * Returns the hardware version from the VMDK's embedded descriptor file.
- *
- * If the VMDK's embedded descriptor file does not contain any hardware version configuration
- * entry, the default hardware version (see {@link #VMDK_DEFAULT_HW_VERSION}) is returned.
- *
- * @return hardware version from the VMDK's embedded descriptor file.
- *
- * @throws DiskImageException unable to obtain the VMDK's hardware version of the disk image
- * format.
- */
- public Version getHwVersion() throws DiskImageException
- {
- final VirtualizationConfigurationVmwareFileFormat vmdkConfig = this.getVmdkConfig();
- final Version hwVersion;
-
- if ( vmdkConfig != null ) {
- // VMDK image contains a hardware version, so return parsed hardware version
- // if hardware version cannot be parsed, return default hardware version
- final String hwVersionStr = vmdkConfig.get( "ddb.virtualHWVersion" );
-
- final int hwVersionMajor = Util.parseInt( hwVersionStr, DiskImageVmdk.VMDK_DEFAULT_HW_VERSION );
- hwVersion = new Version( Integer.valueOf( hwVersionMajor ).shortValue() );
- } else {
- // VMDK image does not contain any hardware version, so return default hardware version
- final int hwVersionMajor = DiskImageVmdk.VMDK_DEFAULT_HW_VERSION;
- hwVersion = new Version( Integer.valueOf( hwVersionMajor ).shortValue() );
- }
-
- return hwVersion;
- }
-
- @Override
- public boolean isStandalone() throws DiskImageException
- {
- final String vmdkCreationType = this.getCreationType();
- final boolean vmdkStandalone;
-
- if ( vmdkCreationType != null ) {
- // creation type is defined, so check if VMDK disk image is a snapshot
- if ( this.isSnapshot() ) {
- // VMDK disk image is a snapshot and not stand alone
- vmdkStandalone = false;
- } else {
- // VMDK disk image is not a snapshot
- // determine stand alone disk image property
- vmdkStandalone = vmdkCreationType.equalsIgnoreCase( "streamOptimized" ) ||
- vmdkCreationType.equalsIgnoreCase( "monolithicSparse" );
- }
- } else {
- // creation type is not defined
- // assume that the file is not stand alone
- vmdkStandalone = false;
- }
-
- return vmdkStandalone;
- }
-
- @Override
- public boolean isCompressed() throws DiskImageException
- {
- final String vmdkCreationType = this.getCreationType();
- final boolean vmdkCompressed;
-
- if ( vmdkCreationType != null && vmdkCreationType.equalsIgnoreCase( "streamOptimized" ) ) {
- // creation type is defined, and VMDK disk image is compressed
- vmdkCompressed = true;
- } else {
- // creation type for compression is not defined
- // assume that the file is not compressed
- vmdkCompressed = false;
- }
-
- return vmdkCompressed;
- }
-
- @Override
- public boolean isSnapshot() throws DiskImageException
- {
- final VirtualizationConfigurationVmwareFileFormat vmdkConfig = this.getVmdkConfig();
- final boolean vmdkSnapshot;
-
- if ( vmdkConfig == null ) {
- // VMDK disk image does not contain any descriptor file
- // assume that the file is not a snapshot
- vmdkSnapshot = false;
- } else {
- // get parent CID to determine snapshot disk image property
- final String parentCid = vmdkConfig.get( "parentCID" );
-
- if ( parentCid != null && !parentCid.equalsIgnoreCase( "ffffffff" ) ) {
- // link to parent content identifier is defined, so VMDK disk image is a snapshot
- vmdkSnapshot = true;
- } else {
- // link to parent content identifier is not defined, so VMDK disk image is not a snapshot
- vmdkSnapshot = false;
- }
- }
-
- return vmdkSnapshot;
- }
-
- @Override
- public Version getVersion() throws DiskImageException
- {
- final RandomAccessFile diskFile = this.getDiskImage();
- final int vmdkVersion = Integer.reverseBytes( DiskImageUtils.readInt( diskFile, 4 ) );
-
- return new Version( Integer.valueOf( vmdkVersion ).shortValue() );
- }
-
- @Override
- public String getDescription() throws DiskImageException
- {
- return null;
- }
-
- @Override
- public ImageFormat getFormat()
- {
- return ImageFormat.VMDK;
- }
-}