You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ml...@apache.org on 2013/12/17 20:17:39 UTC

git commit: updated refs/heads/master to 95364a4

Updated Branches:
  refs/heads/master 7e4407d3d -> 95364a402


CLOUDSTACK-5531

Initial support for vhd, raw, vmdk image formats on KVM. Tested all formats with local and CLVM.


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/95364a40
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/95364a40
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/95364a40

Branch: refs/heads/master
Commit: 95364a40225460c03fcec2eed1cbb4bc5e4a3e56
Parents: 7e4407d
Author: Marcus Sorensen <ma...@betterservers.com>
Authored: Mon Dec 16 14:32:38 2013 -0700
Committer: Marcus Sorensen <ma...@betterservers.com>
Committed: Mon Dec 16 14:32:51 2013 -0700

----------------------------------------------------------------------
 api/src/com/cloud/storage/Storage.java          |   2 +
 .../cloud/storage/template/OVAProcessor.java    | 158 +++++++++++++++++++
 .../cloud/storage/template/VmdkProcessor.java   |  95 ++++-------
 .../kvm/storage/KVMStorageProcessor.java        |   1 +
 .../kvm/storage/LibvirtStorageAdaptor.java      |   4 +-
 .../apache/cloudstack/utils/qemu/QemuImg.java   |   7 +-
 .../manager/VmwareStorageManagerImpl.java       |  10 +-
 .../resource/VmwareStorageProcessor.java        |  10 +-
 .../template/HypervisorTemplateAdapter.java     |  57 +++++--
 .../resource/NfsSecondaryStorageResource.java   |  16 +-
 .../storage/template/DownloadManagerImpl.java   |  13 +-
 ui/scripts/templates.js                         |  12 ++
 12 files changed, 289 insertions(+), 96 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/95364a40/api/src/com/cloud/storage/Storage.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/storage/Storage.java b/api/src/com/cloud/storage/Storage.java
index f1868a7..2175c9b 100755
--- a/api/src/com/cloud/storage/Storage.java
+++ b/api/src/com/cloud/storage/Storage.java
@@ -28,6 +28,8 @@ public class Storage {
         OVA(true, true, true, "ova"),
         VHDX(true, true, true, "vhdx"),
         BAREMETAL(false, false, false, "BAREMETAL"),
+        VMDK(true, true, false, "vmdk"),
+        VDI(true, true, false, "vdi"),
         TAR(false, false, false, "tar");
 
         private final boolean thinProvisioned;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/95364a40/core/src/com/cloud/storage/template/OVAProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/template/OVAProcessor.java b/core/src/com/cloud/storage/template/OVAProcessor.java
new file mode 100644
index 0000000..0db3bb0
--- /dev/null
+++ b/core/src/com/cloud/storage/template/OVAProcessor.java
@@ -0,0 +1,158 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.storage.template;
+
+import java.io.File;
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.cloud.exception.InternalErrorException;
+import com.cloud.storage.Storage.ImageFormat;
+import com.cloud.storage.StorageLayer;
+import com.cloud.utils.component.AdapterBase;
+import com.cloud.utils.script.Script;
+
+@Local(value = Processor.class)
+public class OVAProcessor extends AdapterBase implements Processor {
+    private static final Logger s_logger = Logger.getLogger(OVAProcessor.class);
+
+    StorageLayer _storage;
+
+    @Override
+    public FormatInfo process(String templatePath, ImageFormat format, String templateName) throws InternalErrorException {
+        if (format != null) {
+            if (s_logger.isInfoEnabled()) {
+                s_logger.info("We currently don't handle conversion from " + format + " to OVA.");
+            }
+            return null;
+        }
+
+        s_logger.info("Template processing. templatePath: " + templatePath + ", templateName: " + templateName);
+        String templateFilePath = templatePath + File.separator + templateName + "." + ImageFormat.OVA.getFileExtension();
+        if (!_storage.exists(templateFilePath)) {
+            if (s_logger.isInfoEnabled()) {
+                s_logger.info("Unable to find the vmware template file: " + templateFilePath);
+            }
+            return null;
+        }
+
+        s_logger.info("Template processing - untar OVA package. templatePath: " + templatePath + ", templateName: " + templateName);
+        String templateFileFullPath = templatePath + File.separator + templateName + "." + ImageFormat.OVA.getFileExtension();
+        File templateFile = new File(templateFileFullPath);
+
+        Script command = new Script("tar", 0, s_logger);
+        command.add("--no-same-owner");
+        command.add("-xf", templateFileFullPath);
+        command.setWorkDir(templateFile.getParent());
+        String result = command.execute();
+        if (result != null) {
+            s_logger.info("failed to untar OVA package due to " + result + ". templatePath: " + templatePath + ", templateName: " + templateName);
+            return null;
+        }
+
+        FormatInfo info = new FormatInfo();
+        info.format = ImageFormat.OVA;
+        info.filename = templateName + "." + ImageFormat.OVA.getFileExtension();
+        info.size = _storage.getSize(templateFilePath);
+        info.virtualSize = getTemplateVirtualSize(templatePath, info.filename);
+
+        // delete original OVA file
+        // templateFile.delete();
+        return info;
+    }
+
+    @Override
+    public Long getVirtualSize(File file) {
+        try {
+            long size = getTemplateVirtualSize(file.getParent(), file.getName());
+            return size;
+        } catch (Exception e) {
+
+        }
+        return file.length();
+    }
+
+    public long getTemplateVirtualSize(String templatePath, String templateName) throws InternalErrorException {
+        // get the virtual size from the OVF file meta data
+        long virtualSize = 0;
+        String templateFileFullPath = templatePath.endsWith(File.separator) ? templatePath : templatePath + File.separator;
+        templateFileFullPath += templateName.endsWith(ImageFormat.OVA.getFileExtension()) ? templateName : templateName + "." + ImageFormat.OVA.getFileExtension();
+        String ovfFileName = getOVFFilePath(templateFileFullPath);
+        if (ovfFileName == null) {
+            String msg = "Unable to locate OVF file in template package directory: " + templatePath;
+            s_logger.error(msg);
+            throw new InternalErrorException(msg);
+        }
+        try {
+            Document ovfDoc = null;
+            ovfDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(ovfFileName));
+            Element disk = (Element)ovfDoc.getElementsByTagName("Disk").item(0);
+            virtualSize = Long.parseLong(disk.getAttribute("ovf:capacity"));
+            String allocationUnits = disk.getAttribute("ovf:capacityAllocationUnits");
+            if ((virtualSize != 0) && (allocationUnits != null)) {
+                long units = 1;
+                if (allocationUnits.equalsIgnoreCase("KB") || allocationUnits.equalsIgnoreCase("KiloBytes") || allocationUnits.equalsIgnoreCase("byte * 2^10")) {
+                    units = 1024;
+                } else if (allocationUnits.equalsIgnoreCase("MB") || allocationUnits.equalsIgnoreCase("MegaBytes") || allocationUnits.equalsIgnoreCase("byte * 2^20")) {
+                    units = 1024 * 1024;
+                } else if (allocationUnits.equalsIgnoreCase("GB") || allocationUnits.equalsIgnoreCase("GigaBytes") || allocationUnits.equalsIgnoreCase("byte * 2^30")) {
+                    units = 1024 * 1024 * 1024;
+                }
+                virtualSize = virtualSize * units;
+            } else {
+                throw new InternalErrorException("Failed to read capacity and capacityAllocationUnits from the OVF file: " + ovfFileName);
+            }
+            return virtualSize;
+        } catch (Exception e) {
+            String msg = "Unable to parse OVF XML document to get the virtual disk size due to" + e;
+            s_logger.error(msg);
+            throw new InternalErrorException(msg);
+        }
+    }
+
+    private String getOVFFilePath(String srcOVAFileName) {
+        File file = new File(srcOVAFileName);
+        assert (_storage != null);
+        String[] files = _storage.listFiles(file.getParent());
+        if (files != null) {
+            for (String fileName : files) {
+                if (fileName.toLowerCase().endsWith(".ovf")) {
+                    File ovfFile = new File(fileName);
+                    return file.getParent() + File.separator + ovfFile.getName();
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        _storage = (StorageLayer)params.get(StorageLayer.InstanceConfigKey);
+        if (_storage == null) {
+            throw new ConfigurationException("Unable to get storage implementation");
+        }
+
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/95364a40/core/src/com/cloud/storage/template/VmdkProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/template/VmdkProcessor.java b/core/src/com/cloud/storage/template/VmdkProcessor.java
index be20143..2c08447 100644
--- a/core/src/com/cloud/storage/template/VmdkProcessor.java
+++ b/core/src/com/cloud/storage/template/VmdkProcessor.java
@@ -16,22 +16,24 @@
 // under the License.
 package com.cloud.storage.template;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
 
 import javax.ejb.Local;
 import javax.naming.ConfigurationException;
-import javax.xml.parsers.DocumentBuilderFactory;
 
 import org.apache.log4j.Logger;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
 
 import com.cloud.exception.InternalErrorException;
 import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.StorageLayer;
 import com.cloud.utils.component.AdapterBase;
-import com.cloud.utils.script.Script;
 
 @Local(value = Processor.class)
 public class VmdkProcessor extends AdapterBase implements Processor {
@@ -49,7 +51,7 @@ public class VmdkProcessor extends AdapterBase implements Processor {
         }
 
         s_logger.info("Template processing. templatePath: " + templatePath + ", templateName: " + templateName);
-        String templateFilePath = templatePath + File.separator + templateName + "." + ImageFormat.OVA.getFileExtension();
+        String templateFilePath = templatePath + File.separator + templateName + "." + ImageFormat.VMDK.getFileExtension();
         if (!_storage.exists(templateFilePath)) {
             if (s_logger.isInfoEnabled()) {
                 s_logger.info("Unable to find the vmware template file: " + templateFilePath);
@@ -57,28 +59,12 @@ public class VmdkProcessor extends AdapterBase implements Processor {
             return null;
         }
 
-        s_logger.info("Template processing - untar OVA package. templatePath: " + templatePath + ", templateName: " + templateName);
-        String templateFileFullPath = templatePath + File.separator + templateName + "." + ImageFormat.OVA.getFileExtension();
-        File templateFile = new File(templateFileFullPath);
-
-        Script command = new Script("tar", 0, s_logger);
-        command.add("--no-same-owner");
-        command.add("-xf", templateFileFullPath);
-        command.setWorkDir(templateFile.getParent());
-        String result = command.execute();
-        if (result != null) {
-            s_logger.info("failed to untar OVA package due to " + result + ". templatePath: " + templatePath + ", templateName: " + templateName);
-            return null;
-        }
-
         FormatInfo info = new FormatInfo();
-        info.format = ImageFormat.OVA;
-        info.filename = templateName + "." + ImageFormat.OVA.getFileExtension();
+        info.format = ImageFormat.VMDK;
+        info.filename = templateName + "." + ImageFormat.VMDK.getFileExtension();
         info.size = _storage.getSize(templateFilePath);
         info.virtualSize = getTemplateVirtualSize(templatePath, info.filename);
 
-        // delete original OVA file
-        // templateFile.delete();
         return info;
     }
 
@@ -94,56 +80,37 @@ public class VmdkProcessor extends AdapterBase implements Processor {
     }
 
     public long getTemplateVirtualSize(String templatePath, String templateName) throws InternalErrorException {
-        // get the virtual size from the OVF file meta data
         long virtualSize = 0;
         String templateFileFullPath = templatePath.endsWith(File.separator) ? templatePath : templatePath + File.separator;
-        templateFileFullPath += templateName.endsWith(ImageFormat.OVA.getFileExtension()) ? templateName : templateName + "." + ImageFormat.OVA.getFileExtension();
-        String ovfFileName = getOVFFilePath(templateFileFullPath);
-        if (ovfFileName == null) {
-            String msg = "Unable to locate OVF file in template package directory: " + templatePath;
-            s_logger.error(msg);
-            throw new InternalErrorException(msg);
-        }
+        templateFileFullPath += templateName.endsWith(ImageFormat.VMDK.getFileExtension()) ? templateName : templateName + "." + ImageFormat.VMDK.getFileExtension();
+        String vmdkHeader = "";
+
         try {
-            Document ovfDoc = null;
-            ovfDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(ovfFileName));
-            Element disk = (Element)ovfDoc.getElementsByTagName("Disk").item(0);
-            virtualSize = Long.parseLong(disk.getAttribute("ovf:capacity"));
-            String allocationUnits = disk.getAttribute("ovf:capacityAllocationUnits");
-            if ((virtualSize != 0) && (allocationUnits != null)) {
-                long units = 1;
-                if (allocationUnits.equalsIgnoreCase("KB") || allocationUnits.equalsIgnoreCase("KiloBytes") || allocationUnits.equalsIgnoreCase("byte * 2^10")) {
-                    units = 1024;
-                } else if (allocationUnits.equalsIgnoreCase("MB") || allocationUnits.equalsIgnoreCase("MegaBytes") || allocationUnits.equalsIgnoreCase("byte * 2^20")) {
-                    units = 1024 * 1024;
-                } else if (allocationUnits.equalsIgnoreCase("GB") || allocationUnits.equalsIgnoreCase("GigaBytes") || allocationUnits.equalsIgnoreCase("byte * 2^30")) {
-                    units = 1024 * 1024 * 1024;
+            FileReader fileReader = new FileReader(templateFileFullPath);
+            BufferedReader bufferedReader = new BufferedReader(fileReader);
+            Pattern regex = Pattern.compile("(RW|RDONLY|NOACCESS) (\\d+) (FLAT|SPARSE|ZERO|VMFS|VMFSSPARSE|VMFSDRM|VMFSRAW)");
+            String line = null;
+            while((line = bufferedReader.readLine()) != null) {
+                Matcher m = regex.matcher(line);
+                if (m.find( )) {
+                    long sectors = Long.parseLong(m.group(2));
+                    virtualSize = sectors * 512;
+                    break;
                 }
-                virtualSize = virtualSize * units;
-            } else {
-                throw new InternalErrorException("Failed to read capacity and capacityAllocationUnits from the OVF file: " + ovfFileName);
             }
-            return virtualSize;
-        } catch (Exception e) {
-            String msg = "Unable to parse OVF XML document to get the virtual disk size due to" + e;
+            bufferedReader.close();
+        } catch(FileNotFoundException ex) {
+            String msg = "Unable to open file '" + templateFileFullPath + "' " + ex.toString();
+            s_logger.error(msg);
+            throw new InternalErrorException(msg);
+        } catch(IOException ex) {
+            String msg = "Unable read open file '" + templateFileFullPath + "' " + ex.toString();
             s_logger.error(msg);
             throw new InternalErrorException(msg);
         }
-    }
 
-    private String getOVFFilePath(String srcOVAFileName) {
-        File file = new File(srcOVAFileName);
-        assert (_storage != null);
-        String[] files = _storage.listFiles(file.getParent());
-        if (files != null) {
-            for (String fileName : files) {
-                if (fileName.toLowerCase().endsWith(".ovf")) {
-                    File ovfFile = new File(fileName);
-                    return file.getParent() + File.separator + ovfFile.getName();
-                }
-            }
-        }
-        return null;
+        s_logger.debug("vmdk file had size="+virtualSize);
+        return virtualSize;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/95364a40/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
index d854ca5..7d5d335 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
@@ -189,6 +189,7 @@ public class KVMStorageProcessor implements StorageProcessor {
             }
 
             /* Copy volume to primary storage */
+            s_logger.debug("Copying template to primary storage, template format is " + tmplVol.getFormat() );
             KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
 
             KVMPhysicalDisk primaryVol = null;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/95364a40/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
index 82d0f8d..f910813 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java
@@ -978,6 +978,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
         String sourcePath = disk.getPath();
 
         KVMPhysicalDisk newDisk;
+        s_logger.debug("copyPhysicalDisk: disk size:" + disk.getSize() + ", virtualsize:" + disk.getVirtualSize()+" format:"+disk.getFormat());
         if (destPool.getType() != StoragePoolType.RBD) {
             if (disk.getFormat() == PhysicalDiskFormat.TAR) {
                 newDisk = destPool.createPhysicalDisk(name, PhysicalDiskFormat.DIR, disk.getVirtualSize());
@@ -1015,7 +1016,8 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
                 try {
                     Map<String, String> info = qemu.info(srcFile);
                     String backingFile = info.get(new String("backing_file"));
-                    if (sourceFormat.equals(destFormat) && backingFile == null) {
+                    // qcow2 templates can just be copied into place
+                    if (sourceFormat.equals(destFormat) && backingFile == null && sourcePath.endsWith(".qcow2")) {
                         String result = Script.runSimpleBashScript("cp -f " + sourcePath + " " + destPath, timeout);
                         if (result != null) {
                             throw new CloudRuntimeException("Failed to create disk: " + result);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/95364a40/plugins/hypervisors/kvm/src/org/apache/cloudstack/utils/qemu/QemuImg.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/org/apache/cloudstack/utils/qemu/QemuImg.java b/plugins/hypervisors/kvm/src/org/apache/cloudstack/utils/qemu/QemuImg.java
index 8c23f1e..a948ca1 100644
--- a/plugins/hypervisors/kvm/src/org/apache/cloudstack/utils/qemu/QemuImg.java
+++ b/plugins/hypervisors/kvm/src/org/apache/cloudstack/utils/qemu/QemuImg.java
@@ -184,8 +184,9 @@ public class QemuImg {
     public void convert(QemuImgFile srcFile, QemuImgFile destFile, Map<String, String> options) throws QemuImgException {
         Script s = new Script(_qemuImgPath, timeout);
         s.add("convert");
-        s.add("-f");
-        s.add(srcFile.getFormat().toString());
+        // autodetect source format. Sometime int he future we may teach KVMPhysicalDisk about more formats, then we can explicitly pass them if necessary
+        //s.add("-f");
+        //s.add(srcFile.getFormat().toString());
         s.add("-O");
         s.add(destFile.getFormat().toString());
 
@@ -350,4 +351,4 @@ public class QemuImg {
     public void resize(QemuImgFile file, long size) throws QemuImgException {
         this.resize(file, size, false);
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/95364a40/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
index 040a4cf..cd3fe73 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
@@ -80,7 +80,7 @@ import com.cloud.storage.JavaStorageLayer;
 import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.StorageLayer;
 import com.cloud.storage.Volume;
-import com.cloud.storage.template.VmdkProcessor;
+import com.cloud.storage.template.OVAProcessor;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.Pair;
 import com.cloud.utils.StringUtils;
@@ -649,10 +649,10 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
             clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateUniqueName, true, false);
 
             long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
-            VmdkProcessor processor = new VmdkProcessor();
+            OVAProcessor processor = new OVAProcessor();
             Map<String, Object> params = new HashMap<String, Object>();
             params.put(StorageLayer.InstanceConfigKey, _storage);
-            processor.configure("VMDK Processor", params);
+            processor.configure("OVA Processor", params);
             long virtualSize = processor.getTemplateVirtualSize(installFullPath, templateUniqueName);
 
             postCreatePrivateTemplate(installFullPath, templateId, templateUniqueName, physicalSize, virtualSize);
@@ -771,11 +771,11 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
             }
 
             long physicalSize = new File(installFullPath + "/" + templateVMDKName).length();
-            VmdkProcessor processor = new VmdkProcessor();
+            OVAProcessor processor = new OVAProcessor();
             // long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
             Map<String, Object> params = new HashMap<String, Object>();
             params.put(StorageLayer.InstanceConfigKey, _storage);
-            processor.configure("VMDK Processor", params);
+            processor.configure("OVA Processor", params);
             long virtualSize = processor.getTemplateVirtualSize(installFullPath, templateUniqueName);
 
             postCreatePrivateTemplate(installFullPath, templateId, templateUniqueName, physicalSize, virtualSize);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/95364a40/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
index b55dbec..abb6733 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
@@ -78,7 +78,7 @@ import com.cloud.storage.JavaStorageLayer;
 import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.StorageLayer;
 import com.cloud.storage.Volume;
-import com.cloud.storage.template.VmdkProcessor;
+import com.cloud.storage.template.OVAProcessor;
 import com.cloud.utils.Pair;
 import com.cloud.utils.Ternary;
 import com.cloud.utils.script.Script;
@@ -617,10 +617,10 @@ public class VmwareStorageProcessor implements StorageProcessor {
             clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateUniqueName, true, false);
 
             long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
-            VmdkProcessor processor = new VmdkProcessor();
+            OVAProcessor processor = new OVAProcessor();
             Map<String, Object> params = new HashMap<String, Object>();
             params.put(StorageLayer.InstanceConfigKey, _storage);
-            processor.configure("VMDK Processor", params);
+            processor.configure("OVA Processor", params);
             long virtualSize = processor.getTemplateVirtualSize(installFullPath, templateUniqueName);
 
             postCreatePrivateTemplate(installFullPath, templateId, templateUniqueName, physicalSize, virtualSize);
@@ -841,11 +841,11 @@ public class VmwareStorageProcessor implements StorageProcessor {
             }
 
             long physicalSize = new File(installFullPath + "/" + templateVMDKName).length();
-            VmdkProcessor processor = new VmdkProcessor();
+            OVAProcessor processor = new OVAProcessor();
             // long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
             Map<String, Object> params = new HashMap<String, Object>();
             params.put(StorageLayer.InstanceConfigKey, _storage);
-            processor.configure("VMDK Processor", params);
+            processor.configure("OVA Processor", params);
             long virtualSize = processor.getTemplateVirtualSize(installFullPath, templateUniqueName);
 
             postCreatePrivateTemplate(installFullPath, templateId, templateUniqueName, physicalSize, virtualSize);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/95364a40/server/src/com/cloud/template/HypervisorTemplateAdapter.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java
index 74d1ac8..25e79db 100755
--- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java
+++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java
@@ -151,21 +151,54 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
             (!url.toLowerCase().endsWith("qcow2.bz2")) && (!url.toLowerCase().endsWith("qcow2.gz")) && (!url.toLowerCase().endsWith("ova")) &&
             (!url.toLowerCase().endsWith("ova.zip")) && (!url.toLowerCase().endsWith("ova.bz2")) && (!url.toLowerCase().endsWith("ova.gz")) &&
             (!url.toLowerCase().endsWith("tar")) && (!url.toLowerCase().endsWith("tar.zip")) && (!url.toLowerCase().endsWith("tar.bz2")) &&
-            (!url.toLowerCase().endsWith("tar.gz")) && (!url.toLowerCase().endsWith("img")) && (!url.toLowerCase().endsWith("raw"))) {
+            (!url.toLowerCase().endsWith("tar.gz")) && (!url.toLowerCase().endsWith("vmdk")) && (!url.toLowerCase().endsWith("vmdk.gz")) &&
+            (!url.toLowerCase().endsWith("vmdk.zip")) && (!url.toLowerCase().endsWith("vmdk.bz2")) && (!url.toLowerCase().endsWith("img")) &&
+            (!url.toLowerCase().endsWith("img.gz")) && (!url.toLowerCase().endsWith("img.zip")) && (!url.toLowerCase().endsWith("img.bz2")) &&
+            (!url.toLowerCase().endsWith("raw")) && (!url.toLowerCase().endsWith("raw.gz")) && (!url.toLowerCase().endsWith("raw.bz2")) &&
+            (!url.toLowerCase().endsWith("raw.zip"))) {
             throw new InvalidParameterValueException("Please specify a valid " + format.toLowerCase());
         }
 
-        if ((format.equalsIgnoreCase("vhd") && (!url.toLowerCase().endsWith("vhd") && !url.toLowerCase().endsWith("vhd.zip") && !url.toLowerCase().endsWith("vhd.bz2") && !url.toLowerCase()
-            .endsWith("vhd.gz"))) ||
-            (format.equalsIgnoreCase("vhdx") && (!url.toLowerCase().endsWith("vhdx") && !url.toLowerCase().endsWith("vhdx.zip") &&
-                !url.toLowerCase().endsWith("vhdx.bz2") && !url.toLowerCase()
-                .endsWith("vhdx.gz"))) ||
-            (format.equalsIgnoreCase("qcow2") && (!url.toLowerCase().endsWith("qcow2") && !url.toLowerCase().endsWith("qcow2.zip") &&
-                !url.toLowerCase().endsWith("qcow2.bz2") && !url.toLowerCase().endsWith("qcow2.gz"))) ||
-            (format.equalsIgnoreCase("ova") && (!url.toLowerCase().endsWith("ova") && !url.toLowerCase().endsWith("ova.zip") && !url.toLowerCase().endsWith("ova.bz2") && !url.toLowerCase()
-                .endsWith("ova.gz"))) ||
-            (format.equalsIgnoreCase("tar") && (!url.toLowerCase().endsWith("tar") && !url.toLowerCase().endsWith("tar.zip") && !url.toLowerCase().endsWith("tar.bz2") && !url.toLowerCase()
-                .endsWith("tar.gz"))) || (format.equalsIgnoreCase("raw") && (!url.toLowerCase().endsWith("img") && !url.toLowerCase().endsWith("raw")))) {
+        if ((format.equalsIgnoreCase("vhd")
+                 && (!url.toLowerCase().endsWith("vhd")
+                         && !url.toLowerCase().endsWith("vhd.zip")
+                         && !url.toLowerCase().endsWith("vhd.bz2")
+                         && !url.toLowerCase().endsWith("vhd.gz")))
+            || (format.equalsIgnoreCase("vhdx")
+                 && (!url.toLowerCase().endsWith("vhdx")
+                         && !url.toLowerCase().endsWith("vhdx.zip")
+                         && !url.toLowerCase().endsWith("vhdx.bz2")
+                         && !url.toLowerCase().endsWith("vhdx.gz")))
+            || (format.equalsIgnoreCase("qcow2")
+                 && (!url.toLowerCase().endsWith("qcow2")
+                         && !url.toLowerCase().endsWith("qcow2.zip")
+                         && !url.toLowerCase().endsWith("qcow2.bz2")
+                         && !url.toLowerCase().endsWith("qcow2.gz")))
+            || (format.equalsIgnoreCase("ova")
+                 && (!url.toLowerCase().endsWith("ova")
+                         && !url.toLowerCase().endsWith("ova.zip")
+                         && !url.toLowerCase().endsWith("ova.bz2")
+                         && !url.toLowerCase().endsWith("ova.gz")))
+            || (format.equalsIgnoreCase("tar")
+                 && (!url.toLowerCase().endsWith("tar")
+                         && !url.toLowerCase().endsWith("tar.zip")
+                         && !url.toLowerCase().endsWith("tar.bz2")
+                         && !url.toLowerCase().endsWith("tar.gz")))
+            || (format.equalsIgnoreCase("raw")
+                 && (!url.toLowerCase().endsWith("img")
+                         && !url.toLowerCase().endsWith("img.zip")
+                         && !url.toLowerCase().endsWith("img.bz2")
+                         && !url.toLowerCase().endsWith("img.gz")
+                         && !url.toLowerCase().endsWith("raw")
+                         && !url.toLowerCase().endsWith("raw.bz2")
+                         && !url.toLowerCase().endsWith("raw.zip")
+                         && !url.toLowerCase().endsWith("raw.gz")))
+            || (format.equalsIgnoreCase("vmdk")
+                 && (!url.toLowerCase().endsWith("vmdk")
+                         && !url.toLowerCase().endsWith("vmdk.zip")
+                         && !url.toLowerCase().endsWith("vmdk.bz2")
+                         && !url.toLowerCase().endsWith("vmdk.gz")))
+           ) {
             throw new InvalidParameterValueException("Please specify a valid URL. URL:" + url + " is an invalid for the format " + format.toLowerCase());
         }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/95364a40/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
----------------------------------------------------------------------
diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
index 7c1b9c8..00c1aac 100755
--- a/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
+++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
@@ -125,6 +125,7 @@ import com.cloud.storage.template.RawImageProcessor;
 import com.cloud.storage.template.TemplateLocation;
 import com.cloud.storage.template.TemplateProp;
 import com.cloud.storage.template.VhdProcessor;
+import com.cloud.storage.template.OVAProcessor;
 import com.cloud.storage.template.VmdkProcessor;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.S3Utils;
@@ -771,6 +772,8 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
         if (ext != null) {
             if (ext.equalsIgnoreCase("vhd")) {
                 return ImageFormat.VHD;
+            } else if (ext.equalsIgnoreCase("vhdx")) {
+                return ImageFormat.VHDX;
             } else if (ext.equalsIgnoreCase("qcow2")) {
                 return ImageFormat.QCOW2;
             } else if (ext.equalsIgnoreCase("ova")) {
@@ -779,6 +782,10 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
                 return ImageFormat.TAR;
             } else if (ext.equalsIgnoreCase("img") || ext.equalsIgnoreCase("raw")) {
                 return ImageFormat.RAW;
+            } else if (ext.equalsIgnoreCase("vmdk")) {
+                return ImageFormat.VMDK;
+            } else if (ext.equalsIgnoreCase("vdi")) {
+                return ImageFormat.VDI;
             }
         }
 
@@ -794,11 +801,13 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
             } else if (format == ImageFormat.QCOW2) {
                 processor = new QCOW2Processor();
             } else if (format == ImageFormat.OVA) {
-                processor = new VmdkProcessor();
+                processor = new OVAProcessor();
             } else if (format == ImageFormat.VHD) {
                 processor = new VhdProcessor();
             } else if (format == ImageFormat.RAW) {
                 processor = new RawImageProcessor();
+            } else if (format == ImageFormat.VMDK) {
+                processor = new VmdkProcessor();
             }
 
             if (processor == null) {
@@ -840,7 +849,10 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
                     if (!srcFile.exists()) {
                         srcFile = _storage.getFile(templatePath + ".ova");
                         if (!srcFile.exists()) {
-                            return new CopyCmdAnswer("Can't find src file:" + templatePath);
+                            srcFile = _storage.getFile(templatePath + ".vmdk");
+                            if (!srcFile.exists()) {
+                                return new CopyCmdAnswer("Can't find src file:" + templatePath);
+                            }
                         }
                     }
                 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/95364a40/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java
----------------------------------------------------------------------
diff --git a/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java b/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java
index c01537c..84daf27 100755
--- a/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java
+++ b/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java
@@ -75,6 +75,7 @@ import com.cloud.storage.template.TemplateDownloader.Status;
 import com.cloud.storage.template.TemplateLocation;
 import com.cloud.storage.template.TemplateProp;
 import com.cloud.storage.template.VhdProcessor;
+import com.cloud.storage.template.OVAProcessor;
 import com.cloud.storage.template.VmdkProcessor;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.component.ManagerBase;
@@ -840,8 +841,8 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager
 
             if ((tInfo.getSize() == tInfo.getPhysicalSize()) && (tInfo.getInstallPath().endsWith(ImageFormat.OVA.getFileExtension()))) {
                 try {
-                    Processor processor = _processors.get("VMDK Processor");
-                    VmdkProcessor vmdkProcessor = (VmdkProcessor)processor;
+                    Processor processor = _processors.get("OVA Processor");
+                    OVAProcessor vmdkProcessor = (OVAProcessor)processor;
                     long vSize = vmdkProcessor.getTemplateVirtualSize(path, tInfo.getInstallPath().substring(tInfo.getInstallPath().lastIndexOf(File.separator) + 1));
                     tInfo.setSize(vSize);
                     loc.updateVirtualSize(vSize);
@@ -897,8 +898,8 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager
 
             if ((vInfo.getSize() == vInfo.getPhysicalSize()) && (vInfo.getInstallPath().endsWith(ImageFormat.OVA.getFileExtension()))) {
                 try {
-                    Processor processor = _processors.get("VMDK Processor");
-                    VmdkProcessor vmdkProcessor = (VmdkProcessor)processor;
+                    Processor processor = _processors.get("OVA Processor");
+                    OVAProcessor vmdkProcessor = (OVAProcessor)processor;
                     long vSize = vmdkProcessor.getTemplateVirtualSize(path, vInfo.getInstallPath().substring(vInfo.getInstallPath().lastIndexOf(File.separator) + 1));
                     vInfo.setSize(vSize);
                     loc.updateVirtualSize(vSize);
@@ -1052,6 +1053,10 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager
         processor.configure("QCOW2 Processor", params);
         _processors.put("QCOW2 Processor", processor);
 
+        processor = new OVAProcessor();
+        processor.configure("OVA Processor", params);
+        _processors.put("OVA Processor", processor);
+
         processor = new VmdkProcessor();
         processor.configure("VMDK Processor", params);
         _processors.put("VMDK Processor", processor);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/95364a40/ui/scripts/templates.js
----------------------------------------------------------------------
diff --git a/ui/scripts/templates.js b/ui/scripts/templates.js
index bcceb89..3854db7 100644
--- a/ui/scripts/templates.js
+++ b/ui/scripts/templates.js
@@ -361,6 +361,18 @@
                                                     id: 'QCOW2',
                                                     description: 'QCOW2'
                                                 });
+                                                items.push({
+                                                    id: 'RAW',
+                                                    description: 'RAW'
+                                                });
+                                                items.push({
+                                                    id: 'VHD',
+                                                    description: 'VHD'
+                                                });
+                                                items.push({
+                                                    id: 'VMDK',
+                                                    description: 'VMDK'
+                                                });
                                             } else if (args.hypervisor == "BareMetal") {
                                                 //formatSelect.append("<option value='BareMetal'>BareMetal</option>");
                                                 items.push({