CLOUDSTACK-5531

Initial support for vhd, raw, vmdk image formats on KVM. Tested all formats with local and CLVM.
This commit is contained in:
Marcus Sorensen 2013-12-16 14:32:38 -07:00
parent 7e4407d3dd
commit 95364a4022
12 changed files with 292 additions and 99 deletions

View File

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

View File

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

View File

@ -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);
}
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);
}
}
templateFileFullPath += templateName.endsWith(ImageFormat.VMDK.getFileExtension()) ? templateName : templateName + "." + ImageFormat.VMDK.getFileExtension();
String vmdkHeader = "";
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();
try {
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;
}
}
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);
}
return null;
s_logger.debug("vmdk file had size="+virtualSize);
return virtualSize;
}
@Override

View File

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

View File

@ -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);

View File

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

View File

@ -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);

View File

@ -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);

View File

@ -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());
}

View File

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

View File

@ -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);

View File

@ -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({