/** * Abiquo community edition * cloud management application for hybrid clouds * Copyright (C) 2008-2010 - Abiquo Holdings S.L. * * This application is free software; you can redistribute it and/or * modify it under the terms of the GNU LESSER GENERAL PUBLIC * LICENSE as published by the Free Software Foundation under * version 3 of the License * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * LESSER GENERAL PUBLIC LICENSE v.3 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.abiquo.am.services.ovfformat; import java.math.BigInteger; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import org.apache.commons.io.FilenameUtils; import org.dmtf.schemas.ovf.envelope._1.ContentType; 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.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.VirtualDiskDescType; import org.dmtf.schemas.ovf.envelope._1.VirtualHardwareSectionType; import org.dmtf.schemas.ovf.envelope._1.VirtualSystemCollectionType; import org.dmtf.schemas.ovf.envelope._1.VirtualSystemType; import org.dmtf.schemas.wbem.wscim._1.cim_schema._2.cim_resourceallocationsettingdata.ResourceType; import org.dmtf.schemas.wbem.wscim._1.common.CimString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.abiquo.am.exceptions.AMError; import com.abiquo.appliancemanager.exceptions.AMException; import com.abiquo.appliancemanager.transport.MemorySizeUnit; import com.abiquo.appliancemanager.transport.TemplateDto; import com.abiquo.model.enumerator.DiskFormatType; import com.abiquo.model.enumerator.EthernetDriverType; import com.abiquo.ovfmanager.cim.CIMTypesUtils.CIMResourceTypeEnum; import com.abiquo.ovfmanager.ovf.OVFEnvelopeUtils; import com.abiquo.ovfmanager.ovf.exceptions.EmptyEnvelopeException; import com.abiquo.ovfmanager.ovf.exceptions.IdAlreadyExistsException; import com.abiquo.ovfmanager.ovf.exceptions.IdNotFoundException; import com.abiquo.ovfmanager.ovf.exceptions.InvalidSectionException; import com.abiquo.ovfmanager.ovf.exceptions.RequiredAttributeException; import com.abiquo.ovfmanager.ovf.exceptions.SectionNotPresentException; import com.abiquo.ovfmanager.ovf.section.DiskFormat; public class TemplateFromOVFEnvelope { private final static Logger LOG = LoggerFactory.getLogger(TemplateFromOVFEnvelope.class); public static VirtualDiskDescType getDisk(final EnvelopeType envelope) { DiskSectionType diskSection = null; try { diskSection = OVFEnvelopeUtils.getSection(envelope, DiskSectionType.class); } catch (Exception e)// SectionNotPresentException InvalidSectionException { throw new AMException(AMError.TEMPLATE_INVALID, "missing DiskSection"); } List<VirtualDiskDescType> disks = diskSection.getDisk(); if (disks == null || disks.isEmpty() || disks.size() != 1) { throw new AMException(AMError.TEMPLATE_INVALID, "multiple Disk not supported"); } return disks.get(0); } /** * TODO re-DOC <br> * REQUIRE THE OVFID IS PLACED ON A REMOTE LOCATION (WARINING on generation)<BR> * Creates a list of VirtualInfo relative to the VirtualDisk (from the disk section) and * requirements (from the VirtualHardwareSection) contained on the provided OVF envelope. Used * to add VirtualImage on database once an OVFPackage completes its download. No duplicated Disk * are returned. * * @param ovfDescription, the OVF description of the required OVF package. * @return an array containing all the DiskInfo properties and requirements. * @throws RepositoryException, if the envelope do not contain the required info to get * VirtualDisk information. **/ public static TemplateDto createTemplateDto(final String ovfId, final EnvelopeType envelope) // TODO String userID, String category throws AMException { TemplateDto diskInfo = null; Map<String, VirtualDiskDescType> diskIdToDiskFormat = new HashMap<String, VirtualDiskDescType>(); Map<String, FileType> fileIdToFileType = new HashMap<String, FileType>(); Map<String, List<String>> diskIdToVSs = new HashMap<String, List<String>>(); Map<String, TemplateDto> requiredByVSs = new HashMap<String, TemplateDto>(); DiskSectionType diskSectionType; try { ContentType contentType = OVFEnvelopeUtils.getTopLevelVirtualSystemContent(envelope); ProductSectionType product = OVFEnvelopeUtils.getSection(contentType, ProductSectionType.class); String description = null; if (product.getInfo() != null && product.getInfo().getValue() != null) { description = product.getInfo().getValue(); } String categoryName = null; if (product.getOtherAttributes().containsKey(new QName("CategoryName"))) { categoryName = product.getOtherAttributes().get(new QName("CategoryName")); } String iconPath = getIconPath(product, fileIdToFileType, ovfId); diskSectionType = OVFEnvelopeUtils.getSection(envelope, DiskSectionType.class); for (FileType fileType : envelope.getReferences().getFile()) { fileIdToFileType.put(fileType.getId(), fileType); } // Create a hash for (VirtualDiskDescType virtualDiskDescType : diskSectionType.getDisk()) { diskIdToDiskFormat.put(virtualDiskDescType.getDiskId(), virtualDiskDescType); } if (contentType instanceof VirtualSystemType) { VirtualSystemType vs = (VirtualSystemType) contentType; TemplateDto req = getDiskInfo(vs, diskIdToDiskFormat, diskIdToVSs); requiredByVSs.put(vs.getId(), req); } else if (contentType instanceof VirtualSystemCollectionType) { List<VirtualSystemType> virtualSystems = OVFEnvelopeUtils.getVirtualSystems((VirtualSystemCollectionType) contentType); for (VirtualSystemType virtualSystemType : virtualSystems) { TemplateDto req = getDiskInfo(virtualSystemType, diskIdToDiskFormat, diskIdToVSs); requiredByVSs.put(virtualSystemType.getId(), req); } } for (VirtualDiskDescType diskDescType : diskIdToDiskFormat.values()) { String diskId = diskDescType.getDiskId(); String fileId = diskDescType.getFileRef(); if (!fileIdToFileType.containsKey(fileId)) { String msg = "File Id [" + fileId + "] not found on the ReferencesSection"; throw new IdNotFoundException(msg); } FileType file = fileIdToFileType.get(fileId); final String filePath = file.getHref(); final Long fileSize = file.getSize().longValue(); String format = diskDescType.getFormat(); // XXX using the same format on the OVF // disk if (!diskIdToVSs.containsKey(diskId)) { throw new IdNotFoundException("Any virtualSystem is using diskId[" + diskId + "]"); // XXX warning ?? } if (diskIdToVSs.size() != 1) { throw new AMException(AMError.TEMPLATE_INVALID, String.format( "There are more than one virtual system on the OVF Envelope [%s]", ovfId)); } for (String vssName : diskIdToVSs.get(diskId)) { diskInfo = new TemplateDto(); diskInfo.setName(vssName); diskInfo.setUrl(ovfId); DiskFormat diskFormat = DiskFormat.fromValue(format); DiskFormatType ovfDiskFormat = DiskFormatType.valueOf(diskFormat.name()); diskInfo.setDiskFileFormat(ovfDiskFormat); diskInfo.setDiskFileSize(fileSize); // Note that getHRef() will now return the relative path // of the file at the downloaded repository space if (filePath.startsWith("http:")) { diskInfo.setDiskFilePath(FilenameUtils.getName(filePath)); } else { diskInfo.setDiskFilePath(filePath); } diskInfo.setIconPath(iconPath); diskInfo.setDescription(description); diskInfo.setCategoryName(categoryName); // XXX diskInfo.setSO(value); if (!requiredByVSs.containsKey(vssName)) { throw new IdNotFoundException("VirtualSystem id not found [" + vssName + "]"); } TemplateDto requirement = requiredByVSs.get(vssName); // XXX disk format ::: diskInfo.setImageType(requirement.getImageType()); diskInfo.setCpu(requirement.getCpu()); diskInfo.setRam(requirement.getRam()); diskInfo.setHd(requirement.getHd()); diskInfo.setRamSizeUnit(requirement.getRamSizeUnit()); diskInfo.setHdSizeUnit(requirement.getHdSizeUnit()); diskInfo.setEthernetDriverType(requirement.getEthernetDriverType()); // TODO diskInfo.setEnterpriseId(enterpriseId); // diskInfo.setUserId(userId); TODO user ID // diskInfo.getCategories().add(category); TODO category }// all vss }// all disks } catch (EmptyEnvelopeException e) { String msg = "No VirtualSystem or VirtualSystemCollection exists for this OVF package"; throw new AMException(AMError.TEMPLATE_INVALID, msg, e); } catch (Exception e) { throw new AMException(AMError.TEMPLATE_INVALID, e); } if (diskInfo == null) { String msg = "No VirtualSystem or VirtualSystemCollection exists for this OVF package"; throw new AMException(AMError.TEMPLATE_INVALID, msg); } return diskInfo; } /** * Only the first icon on product section is used */ private static String getIconPath(final ProductSectionType product, final Map<String, FileType> fileIdToFileType, final String ovfId) { List<Icon> icons = product.getIcon(); if (icons == null || icons.size() == 0) { return null; } final Icon icon = icons.get(0); final String iconRef = icon.getFileRef(); if (iconRef.startsWith("http")) { return iconRef; } if (!fileIdToFileType.containsKey(iconRef)) { return null; // XXX log cause } final String iconPathRelative = fileIdToFileType.get(iconRef).getHref(); if (iconPathRelative.startsWith("http")) { return iconPathRelative; } final String ovfAbs = ovfId.substring(0, ovfId.lastIndexOf('/')); return ovfAbs + '/' + iconPathRelative; } /** * TODO TBD **/ private static TemplateDto getDiskInfo(final VirtualSystemType vsystem, final Map<String, VirtualDiskDescType> diskDescByName, final Map<String, List<String>> diskIdToVSs) throws IdAlreadyExistsException, RequiredAttributeException, SectionNotPresentException { TemplateDto dReq = new TemplateDto(); VirtualHardwareSectionType hardwareSectionType; try { hardwareSectionType = OVFEnvelopeUtils.getSection(vsystem, VirtualHardwareSectionType.class); } catch (InvalidSectionException e) { throw new SectionNotPresentException("VirtualHardware on a virtualSystem", e); } dReq.setCpu(-1); dReq.setHd(Long.valueOf(-1)); dReq.setRam(Long.valueOf(-1)); // XXX now we are using ONLY the Disk format // XXX String vsType = hardwareSectionType.getSystem().getVirtualSystemType().getValue(); // XXX dReq.setImageType(vsType); // XXX log.debug("Using ''virtualSystemType'' [{}]", vsType); for (RASDType rasdType : hardwareSectionType.getItem()) { ResourceType resourceType = rasdType.getResourceType(); int resTnumeric = Integer.parseInt(resourceType.getValue()); // TODO use CIMResourceTypeEnum from value and then a SWITCH // Get the information on the ram if (CIMResourceTypeEnum.Processor.getNumericResourceType() == resTnumeric) { String cpuVal = rasdType.getVirtualQuantity().getValue().toString(); dReq.setCpu(Integer.parseInt(cpuVal)); // TODO if(rasdType.getAllocationUnits()!= null) } else if (CIMResourceTypeEnum.Memory.getNumericResourceType() == resTnumeric) { BigInteger ramVal = rasdType.getVirtualQuantity().getValue(); dReq.setRam(ramVal.longValue()); if (rasdType.getAllocationUnits() != null & rasdType.getAllocationUnits().getValue() != null) { final String allocationUnits = rasdType.getAllocationUnits().getValue(); final MemorySizeUnit ramSizeUnit = getMemoryUnitsFromOVF(allocationUnits); dReq.setRamSizeUnit(ramSizeUnit); } } else if (CIMResourceTypeEnum.Disk_Drive.getNumericResourceType() == resTnumeric) { // HD requirements are extracted from the associated Disk on ''hostResource'' String diskId = getVirtualSystemDiskId(rasdType.getHostResource()); if (!diskDescByName.containsKey(diskId)) { String msg = "DiskId [" + diskId + "] not found on disk section"; throw new IdAlreadyExistsException(msg); } if (!diskIdToVSs.containsKey(diskId)) { List<String> vss = new LinkedList<String>(); vss.add(vsystem.getId()); // XXX diskIdToVSs.put(diskId, vss); } else { diskIdToVSs.get(diskId).add(vsystem.getId()); } VirtualDiskDescType diskDescType = diskDescByName.get(diskId); String capacity = diskDescType.getCapacity(); dReq.setHd(Long.parseLong(capacity)); final String allocationUnits = diskDescType.getCapacityAllocationUnits(); final MemorySizeUnit hdSizeUnit = getMemoryUnitsFromOVF(allocationUnits); dReq.setHdSizeUnit(hdSizeUnit); // dReq.setImageSize(diskDescType.get); } else if (CIMResourceTypeEnum.Ethernet_Adapter.getNumericResourceType() == resTnumeric) { String ethDriver = null; EthernetDriverType ethDriverType = null; try { ethDriver = rasdType.getResourceSubType().getValue(); ethDriverType = EthernetDriverType.valueOf(ethDriver); } catch (Exception e) { LOG.error("Invalid ethernet adapter type {}", ethDriver != null ? ethDriver : "-ResourceSubType- not found"); } if (dReq.getEthernetDriverType() != null && ethDriverType != null) { LOG.warn("Overwrite ethernet adapter type form {} to {}", dReq .getEthernetDriverType().name(), ethDriverType.name()); } else if (ethDriverType != null) { dReq.setEthernetDriverType(ethDriverType); } } }// rasd if (dReq.getCpu() == -1) { throw new RequiredAttributeException("Not CPU RASD element found on the envelope"); } if (dReq.getRam() == -1) { throw new RequiredAttributeException("Not RAM RASD element found on the envelope"); } if (dReq.getHd() == -1) { throw new RequiredAttributeException("Not HD RASD element found on the envelope"); } return dReq; } /** * default is byte * * @throws RequiredAttributeException */ private static MemorySizeUnit getMemoryUnitsFromOVF(final String allocationUnits) throws RequiredAttributeException { if (allocationUnits == null || "byte".equalsIgnoreCase(allocationUnits) || "bytes".equalsIgnoreCase(allocationUnits)) { return MemorySizeUnit.BYTE; } else if ("byte * 2^10".equals(allocationUnits) || "KB".equalsIgnoreCase(allocationUnits) || "KILOBYTE".equalsIgnoreCase(allocationUnits) || "KILOBYTES".equalsIgnoreCase(allocationUnits)) // kb { return MemorySizeUnit.KILOBYTE; } else if ("byte * 2^20".equals(allocationUnits) || "MB".equalsIgnoreCase(allocationUnits) || "MEGABYTE".equalsIgnoreCase(allocationUnits) || "MEGABYTES".equalsIgnoreCase(allocationUnits)) // mb { return MemorySizeUnit.MEGABYTE; } else if ("byte * 2^30".equals(allocationUnits) || "GB".equalsIgnoreCase(allocationUnits) || "GIGABYTE".equalsIgnoreCase(allocationUnits) || "GIGABYTES".equalsIgnoreCase(allocationUnits)) // gb { return MemorySizeUnit.GIGABYTE; } else if ("byte * 2^40".equals(allocationUnits) || "TB".equalsIgnoreCase(allocationUnits) || "TERABYTE".equalsIgnoreCase(allocationUnits) || "TERABYTES".equalsIgnoreCase(allocationUnits)) // tb { return MemorySizeUnit.TERABYTE; } else { final String msg = "Unknow disk capacityAllocationUnits factor [" + allocationUnits + "]"; throw new RequiredAttributeException(msg); } } /** * Decode CimStrings (on the OVF namespce) on the Disk RASD's HostResource attribute to delete * the ''ovf://disk/'' prefix **/ private static String getVirtualSystemDiskId(final List<CimString> cimStrs) { String cimStringVal = ""; for (CimString cimString : cimStrs) { cimStringVal = cimString.getValue(); if (cimStringVal.startsWith("ovf:/disk/")) { cimStringVal = cimStringVal.replace("ovf:/disk/", ""); break; } else if (cimStringVal.startsWith("/disk/")) { cimStringVal = cimStringVal.replace("/disk/", ""); break; } } return cimStringVal; } /** * Gets the disk capacity on bytes. * * @param capacity, numeric value * @param alloctionUnit, bytes by default but can be Kb, Mb, Gb or Tb. * @return capacity on bytes private static BigInteger getBytes(String capacity, String * allocationUnits) { BigInteger capa = new BigInteger(capacity); if(allocationUnits == * null) { return capa; } if("byte".equals(allocationUnits)) { return capa; } BigInteger * factor = new BigInteger("2"); if("byte * 2^10".equals(allocationUnits)) // kb { * factor.pow(10); } else if("byte * 2^20".equals(allocationUnits)) // mb { * factor.pow(20); } else if("byte * 2^30".equals(allocationUnits)) // gb { * factor.pow(30); } else if("byte * 2^40".equals(allocationUnits)) // tb { * factor.pow(40); } else { * System.err.println("Unknow capacityAllocationUnits factor ["+allocationUnits+"]"); * return capa; } return capa.multiply(factor); } */ /** * Decode CimStrings (on the OVF namespce) on the Disk RASD's HostResource attribute to delete * the ''ovf://disk/'' prefix private static String getVirtualSystemDiskId(List<CimString> * cimStrs) { String cimStringVal = ""; for (CimString cimString : cimStrs) { cimStringVal = * cimString.getValue(); if (cimStringVal.startsWith("ovf:/disk/")) { cimStringVal = * cimStringVal.replace("ovf:/disk/", ""); break; } } return cimStringVal; } */ }