/**
* Licensed to Abiquo Holdings S.L. (Abiquo) 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.abiquo.am.model.ovf;
import java.io.File;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.xml.namespace.QName;
import org.dmtf.schemas.ovf.envelope._1.DiskSectionType;
import org.dmtf.schemas.ovf.envelope._1.EnvelopeType;
import org.dmtf.schemas.ovf.envelope._1.FileType;
import org.dmtf.schemas.ovf.envelope._1.OperatingSystemSectionType;
import org.dmtf.schemas.ovf.envelope._1.ProductSectionType;
import org.dmtf.schemas.ovf.envelope._1.ProductSectionType.Icon;
import org.dmtf.schemas.ovf.envelope._1.RASDType;
import org.dmtf.schemas.ovf.envelope._1.ReferencesType;
import org.dmtf.schemas.ovf.envelope._1.VSSDType;
import org.dmtf.schemas.ovf.envelope._1.VirtualDiskDescType;
import org.dmtf.schemas.ovf.envelope._1.VirtualHardwareSectionType;
import org.dmtf.schemas.ovf.envelope._1.VirtualSystemType;
import org.dmtf.schemas.wbem.wscim._1.cim_schema._2.cim_resourceallocationsettingdata.CIMResourceAllocationSettingDataType;
import com.abiquo.am.model.TemplateDto;
import com.abiquo.am.model.error.AMError;
import com.abiquo.am.model.error.AMException;
import com.abiquo.ovfmanager.cim.CIMResourceAllocationSettingDataUtils;
import com.abiquo.ovfmanager.cim.CIMTypesUtils;
import com.abiquo.ovfmanager.cim.CIMTypesUtils.CIMResourceTypeEnum;
import com.abiquo.ovfmanager.ovf.OVFEnvelopeUtils;
import com.abiquo.ovfmanager.ovf.OVFReferenceUtils;
import com.abiquo.ovfmanager.ovf.exceptions.IdNotFoundException;
import com.abiquo.ovfmanager.ovf.exceptions.RequiredAttributeException;
import com.abiquo.ovfmanager.ovf.section.DiskFormatOVF;
import com.abiquo.ovfmanager.ovf.section.OVFDiskUtils;
import com.abiquo.ovfmanager.ovf.section.OVFDiskUtils.DiskSizeUnit;
import com.abiquo.ovfmanager.ovf.section.OVFProductUtils;
import com.abiquo.ovfmanager.ovf.section.OVFVirtualHadwareSectionUtils;
import com.abiquo.ovfmanager.ovf.section.OperatingSystemOVF;
/**
* Creates an OVF document from a DiskInfo. (Mono disk and Mono virtual system Envelopes)
*/
public class TemplateToOVFEnvelope
{
/** All the virtual system are created using these type. */
private final static String VIRTUAL_SYSTEM_TYPE = "abiquo";
/**
* Use the imageSize
**/
public static EnvelopeType createOVFEnvelopeFromTemplate(final TemplateDto template)
{
EnvelopeType envelope = new EnvelopeType();
ReferencesType references = new ReferencesType();
final String diskPath = template.getDiskFilePath();
// final String packRelPath = getRelativePackagePath(disk.getOvfUrl(),
// String.valueOf(disk.getIdEnterprise()));
final Long diskSize = template.getDiskFileSize();
// final String completPath = packRelPath +'/'+diskPath;
// System.err.println(packRelPath);
try
{
FileType fileRef =
OVFReferenceUtils.createFileType("diskFile", diskPath,
BigInteger.valueOf(diskSize), null, null);
OVFReferenceUtils.addFile(references, fileRef);
DiskSectionType diskSection = createDiskSection(template);
VirtualSystemType vsystem = createVirtualSystem(template);
ProductSectionType product = createProductSection(template);
OperatingSystemSectionType ossection = createOperatingSystemSection(template);
OVFEnvelopeUtils.addSection(vsystem, product);
OVFEnvelopeUtils.addSection(vsystem, ossection);
OVFEnvelopeUtils.addSection(envelope, diskSection);
OVFEnvelopeUtils.addVirtualSystem(envelope, vsystem);
envelope.setReferences(references);
}
catch (Exception e)
{
throw new AMException(AMError.TEMPLATE_INSTALL,
"Can not create the OVF from the DiskInfo",
e);
}
return envelope;
}
/***
* Use ImageType and HD
*/
private static DiskSectionType createDiskSection(final TemplateDto disk) throws Exception
{
DiskFormatOVF format = DiskFormatOVF.fromName(disk.getDiskFileFormat());
final Long diskSize = disk.getRequiredHDInMB();
VirtualDiskDescType diskDesc =
OVFDiskUtils.createDiskDescription("ovfdisk", "diskFile", format, diskSize,
DiskSizeUnit.MegaBytes, null, null);
DiskSectionType diskSection = new DiskSectionType();
OVFDiskUtils.addDisk(diskSection, diskDesc);
return diskSection;
}
/**
* Use Description and name.
*/
private static VirtualSystemType createVirtualSystem(final TemplateDto disk) throws Exception
{
VirtualSystemType vsystem =
OVFEnvelopeUtils.createVirtualSystem(disk.getName(), disk.getName(),
disk.getDescription());
VirtualHardwareSectionType vhs = createVirtualHardwareSection(disk);
OVFEnvelopeUtils.addSection(vsystem, vhs);
return vsystem;
}
/**
* Use Description, Name and IconPath.
*/
private static ProductSectionType createProductSection(final TemplateDto disk) throws Exception
{
ProductSectionType product = new ProductSectionType();
product.setInfo(CIMTypesUtils.createMsg(disk.getDescription(), "0"));
product.setProduct(CIMTypesUtils.createMsg(disk.getName(), "0"));
product.getCategoryOrProperty().add(createProperty("user", disk.getLoginUser()));
product.getCategoryOrProperty().add(createProperty("password", disk.getLoginPassword()));
final String diskIcon = disk.getIconUrl();
if (diskIcon != null)
{
Icon icon = OVFProductUtils.createIcon(50, 50, "jpg", diskIcon); // XXX icon
// details
OVFProductUtils.addProductIcon(product, icon);
}
// warn
product.getOtherAttributes().put(new QName("CategoryName"), disk.getCategoryName());
return product;
}
private static OperatingSystemSectionType createOperatingSystemSection(final TemplateDto disk)
{
final OperatingSystemOVF type =
disk.getOsType() != null ? OperatingSystemOVF.valueOf(disk.getOsType().toUpperCase())
: OperatingSystemOVF.OTHER_64;
final OperatingSystemSectionType ossection = new OperatingSystemSectionType();
ossection.setId(type.getCode());
ossection.setVersion(disk.getOsVersion());
ossection.setDescription(CIMTypesUtils.createMsg(type.getDescription(), null));
return ossection;
}
private static ProductSectionType.Property createProperty(final String key, final String value)
{
if (value == null)
{
return null;
}
ProductSectionType.Property property = new ProductSectionType.Property();
property.setKey(key);
property.setValue(value);
return property;
}
/**
* Use RAM, CPU, HD (and its Units) of the DiskInfo to build a VirtualHadwareSection to be used
* on the OVF Envelope.
*/
private static VirtualHardwareSectionType createVirtualHardwareSection(final TemplateDto disk)
throws RequiredAttributeException
{
VirtualHardwareSectionType vhsection = new VirtualHardwareSectionType();
VSSDType vsystem = new VSSDType();
vsystem.setVirtualSystemType(CIMTypesUtils.createString(VIRTUAL_SYSTEM_TYPE));
vhsection.setSystem(vsystem);
CIMResourceAllocationSettingDataType cpu =
CIMResourceAllocationSettingDataUtils.createResourceAllocationSettingData("Cpu", "1",
CIMResourceTypeEnum.Processor, disk.getRequiredCpu(), null);
CIMResourceAllocationSettingDataType ram =
CIMResourceAllocationSettingDataUtils.createResourceAllocationSettingData("Ram", "1",
CIMResourceTypeEnum.Memory, disk.getRequiredRamInMB(), "MB");
CIMResourceAllocationSettingDataType hd =
CIMResourceAllocationSettingDataUtils.createResourceAllocationSettingData("Hd", "1",
CIMResourceTypeEnum.Disk_Drive, disk.getRequiredHDInMB(), "MB");
RASDType rasdCpu = CIMResourceAllocationSettingDataUtils.createRASDTypeFromCIMRASD(cpu);
RASDType rasdRam = CIMResourceAllocationSettingDataUtils.createRASDTypeFromCIMRASD(ram);
RASDType rasdHd = CIMResourceAllocationSettingDataUtils.createRASDTypeFromCIMRASD(hd);
rasdHd.getHostResource().add(CIMTypesUtils.createString("ovf:/disk/ovfdisk"));
OVFVirtualHadwareSectionUtils.addRASD(vhsection, rasdCpu);
OVFVirtualHadwareSectionUtils.addRASD(vhsection, rasdRam);
OVFVirtualHadwareSectionUtils.addRASD(vhsection, rasdHd);
vhsection = configureCustomEthernetDriver(vhsection, disk);
vhsection = configureCustomDiskController(vhsection, disk);
return vhsection;
}
private static VirtualHardwareSectionType configureCustomEthernetDriver(
final VirtualHardwareSectionType vhsection, final TemplateDto disk)
throws RequiredAttributeException
{
if (disk.getEthernetDriverType() != null)
{
CIMResourceAllocationSettingDataType ethDriver =
CIMResourceAllocationSettingDataUtils.createResourceAllocationSettingData(
"ethernetDriver", "1", CIMResourceTypeEnum.Ethernet_Adapter, 0, null);
ethDriver.setResourceSubType(CIMTypesUtils.createString(disk.getEthernetDriverType()));
final RASDType rasdEthDriver =
CIMResourceAllocationSettingDataUtils.createRASDTypeFromCIMRASD(ethDriver);
OVFVirtualHadwareSectionUtils.addRASD(vhsection, rasdEthDriver);
}
return vhsection;
}
private static VirtualHardwareSectionType configureCustomDiskController(
final VirtualHardwareSectionType vhsection, final TemplateDto disk)
throws RequiredAttributeException
{
if (disk.getDiskControllerType() != null)
{
CIMResourceAllocationSettingDataType diskController = null;
if ("IDE".equalsIgnoreCase(disk.getDiskControllerType()))
{
diskController =
CIMResourceAllocationSettingDataUtils.createResourceAllocationSettingData(
"IDE Controller", "3", CIMResourceTypeEnum.IDE_Controller, 0, null);
}
else if ("SCSI".equalsIgnoreCase(disk.getDiskControllerType()))
{
diskController =
CIMResourceAllocationSettingDataUtils.createResourceAllocationSettingData(
"SCSI Controller", "3", CIMResourceTypeEnum.Parallel_SCSI_HBA, 0, null);
diskController.setResourceSubType(CIMTypesUtils.createString("lsilogic"));
}
OVFVirtualHadwareSectionUtils.addRASD(vhsection,
CIMResourceAllocationSettingDataUtils.createRASDTypeFromCIMRASD(diskController));
}
return vhsection;
}
public static EnvelopeType fixFilePathsAndSize(final EnvelopeType envelope,
final String snapshot, final String packagePath)
{
Set<String> diskFileIds = new HashSet<String>();
DiskSectionType diskSection;
try
{
diskSection = OVFEnvelopeUtils.getSection(envelope, DiskSectionType.class);
}
catch (Exception e)
{
throw new AMException(AMError.TEMPLATE_BOUNDLE, String.format(
"The bundle [%s] can not be created "
+ "because the original envelope do not exist or do not have Disk Section",
snapshot), e);
}
List<VirtualDiskDescType> disks = diskSection.getDisk();
if (disks.isEmpty())
{
throw new AMException(AMError.TEMPLATE_BOUNDLE, String.format(
"The bundle [%s] can not be created because the "
+ "original envelope do not contains any Disk", snapshot));
}
else
{
for (VirtualDiskDescType disk : disks)
{
diskFileIds.add(disk.getFileRef());
}
}
// all the disk files should be marked with "snapshot + OVF_BUNDLE_PATH_IDENTIFIER" + hRef
// (packagePath relative)
for (String diskFileId : diskFileIds)
{
FileType file;
try
{
file = OVFReferenceUtils.getReferencedFile(envelope, diskFileId);
}
catch (IdNotFoundException e)
{
throw new AMException(AMError.TEMPLATE_BOUNDLE, String.format(
"The bundle [%s] can not be created because the "
+ "referenced file Id [%s] is not found on the Envelope", snapshot,
diskFileId), e);
}
// TODO check hRef is 'packagePath' relative
final String relativeBundleFileRef = snapshot + file.getHref();
final String absoluteBundleFileRef = packagePath + relativeBundleFileRef;
File bundleFile = new File(absoluteBundleFileRef);
Long bundleFileSize;
if (!bundleFile.exists() || bundleFile.isDirectory())
{
throw new AMException(AMError.TEMPLATE_BOUNDLE, String.format(
"The bundle [%s] can not be created because the "
+ "referenced file on [%s] is not found", snapshot, absoluteBundleFileRef));
}
else
{
// actually exist
bundleFileSize = bundleFile.length(); // Bytes
file.setSize(BigInteger.valueOf(bundleFileSize));
file.setHref(relativeBundleFileRef);
}
for (VirtualDiskDescType vDiskDesc : disks)
{
if (diskFileId.equalsIgnoreCase(vDiskDesc.getFileRef()))
{
// TODO Capacity == Disk file
vDiskDesc.setCapacity(String.valueOf(bundleFileSize));
}
}
}// each disk file
return envelope;
}
public static EnvelopeType fixFilePathsAndSize(final EnvelopeType envelope,
final String relativeDiskPath, final BigInteger diskSizeInBytes)
{
Set<String> diskFileIds = new HashSet<String>();
DiskSectionType diskSection;
try
{
diskSection = OVFEnvelopeUtils.getSection(envelope, DiskSectionType.class);
}
catch (Exception e)
{
throw new AMException(AMError.PROMOTE_MASTER_OVF, String.format(
"The promote [%s] can not be created "
+ "because the original envelope do not exist or do not have Disk Section",
relativeDiskPath), e);
}
List<VirtualDiskDescType> disks = diskSection.getDisk();
if (disks.isEmpty())
{
throw new AMException(AMError.PROMOTE_MASTER_OVF, String.format(
"The promote [%s] can not be created because the "
+ "original envelope do not contains any Disk", relativeDiskPath));
}
else
{
for (VirtualDiskDescType disk : disks)
{
diskFileIds.add(disk.getFileRef());
}
}
// all the disk files should be marked with "snapshot + OVF_BUNDLE_PATH_IDENTIFIER" + hRef
// (packagePath relative)
for (String diskFileId : diskFileIds)
{
FileType file;
try
{
file = OVFReferenceUtils.getReferencedFile(envelope, diskFileId);
}
catch (IdNotFoundException e)
{
throw new AMException(AMError.PROMOTE_MASTER_OVF, String.format(
"The promote [%s] can not be created because the "
+ "referenced file Id [%s] is not found on the Envelope", relativeDiskPath,
diskFileId), e);
}
file.setSize(diskSizeInBytes);
file.setHref(relativeDiskPath);
}
return envelope;
}
}