/**
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is available at https://abicloud.svn.sourceforge.net/svnroot/abicloud
*
* The Initial Developer of the Original Code is Soluciones Grid, S.L. (www.abiquo.com),
* Consell de Cent 296 principal 2ยบ, 08007 Barcelona, Spain.
* No portions of the Code have been created by third parties.
* All Rights Reserved.
*
* Contributor(s):
* Telefonica Investigacion y Desarrollo S.A.U. (http://www.tid.es)
* Emilio Vargas 6, 28043 Madrid, Spain.
*
*/
/**
* This project aims to be OVF1.0.0 DSP8023(Envelope) and DSP8027(Environment) complaint @see DMTF
* page for details {@link http://schemas.dmtf.org/ovf/}, but for now VMWare only can deploy OVF
* packages form the 0.9, so compatibility is take into order.
* <p>
* Manipulate objects on the OVF-envelope name space. Hide from other classes the use of JAXB.
* <p>
* It intends to be an utility similar to ''open-ovf'', see the complete feature list for this
* project on:
* <li>{@link http://open-ovf.wiki.sourceforge.net/open-ovf+command+line+interface}</li><br>
* also the virtualBox OVF code is checked<br>
* <li>{@link http ://www.virtualbox.org/browser/trunk/src/VBox/Main/ApplianceImpl.cpp?rev=16306}</li>
* <p>
* References to check:
* <li>{@link http://server.dzone.com/news/a-review-ovf-a-systems-managem}</li>
* <li>{@link http ://stage.vambenepe.com/archives/382}</li>
* <li>{@http://grantmcwilliams.com/index.php/virtualization/blog/}</li>
* <p>
*/
package com.abiquo.ovf;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import org.dmtf.schemas.ovf.envelope._1.AnnotationSectionType;
import org.dmtf.schemas.ovf.envelope._1.ContentType;
import org.dmtf.schemas.ovf.envelope._1.DeploymentOptionSectionType;
import org.dmtf.schemas.ovf.envelope._1.DiskSectionType;
import org.dmtf.schemas.ovf.envelope._1.EnvelopeType;
import org.dmtf.schemas.ovf.envelope._1.EulaSectionType;
import org.dmtf.schemas.ovf.envelope._1.FileType;
import org.dmtf.schemas.ovf.envelope._1.InstallSectionType;
import org.dmtf.schemas.ovf.envelope._1.MsgType;
import org.dmtf.schemas.ovf.envelope._1.NetworkSectionType;
import org.dmtf.schemas.ovf.envelope._1.ObjectFactory;
import org.dmtf.schemas.ovf.envelope._1.OperatingSystemSectionType;
import org.dmtf.schemas.ovf.envelope._1.ProductSectionType;
import org.dmtf.schemas.ovf.envelope._1.RASDType;
import org.dmtf.schemas.ovf.envelope._1.ReferencesType;
import org.dmtf.schemas.ovf.envelope._1.ResourceAllocationSectionType;
import org.dmtf.schemas.ovf.envelope._1.SectionType;
import org.dmtf.schemas.ovf.envelope._1.StartupSectionType;
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.ovf.envelope._1.ProductSectionType.Property;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.abiquo.cim.CIMTypesUtils;
import com.abiquo.ovf.exceptions.DNSServerNotFoundException;
import com.abiquo.ovf.exceptions.EmptyEnvelopeException;
import com.abiquo.ovf.exceptions.GatewayNotFoundException;
import com.abiquo.ovf.exceptions.IPNotFoundException;
import com.abiquo.ovf.exceptions.IdAlreadyExistsException;
import com.abiquo.ovf.exceptions.IdNotFoundException;
import com.abiquo.ovf.exceptions.InvalidSectionException;
import com.abiquo.ovf.exceptions.NetmaskNotFoundException;
import com.abiquo.ovf.exceptions.NotEnoughIPsInPoolException;
import com.abiquo.ovf.exceptions.PoolNameNotFoundException;
import com.abiquo.ovf.exceptions.PrecedentTierEntryPointNotFoundException;
import com.abiquo.ovf.exceptions.RequiredAttributeException;
import com.abiquo.ovf.exceptions.SectionAlreadyPresentException;
import com.abiquo.ovf.exceptions.SectionException;
import com.abiquo.ovf.exceptions.SectionNotPresentException;
import com.abiquo.ovf.section.OVFDiskUtils;
import com.abiquo.ovf.section.OVFNetworkUtils;
import com.abiquo.ovf.section.OVFProductUtils;
import com.abiquo.ovf.section.OVFVirtualHadwareSectionUtils;
import com.abiquo.ovf.section.OVFVirtualSystemUtils;
import com.telefonica.claudia.ovf.AffinitySectionType;
import com.telefonica.claudia.ovf.AntiAffinityType;
import com.telefonica.claudia.ovf.AspectsSectionType;
import com.telefonica.claudia.ovf.AvailabilitySectionType;
import com.telefonica.claudia.ovf.DeploymentSectionType;
import com.telefonica.claudia.ovf.DiskMappingSectionType;
import com.telefonica.claudia.ovf.ElasticArraySectionType;
import com.telefonica.claudia.ovf.FirewallSectionType;
import com.telefonica.claudia.ovf.KPISectionType;
import com.telefonica.claudia.ovf.LoadBalancerSectionType;
import com.telefonica.claudia.ovf.PerformanceObjectiveSectionType;
import com.telefonica.claudia.ovf.utils.OVFGeneralUtils;
/**
* This utility provide basic operation on the highest level OVF envelope
* entities, providing methods to get/create Section on the Envelope or Content
* (VirtualSystem and VirtualSystemCollection). <br>
* <li>Creates Envelope, VirtualSystem an VirtualSystemCollection</li><br>
* <li>Attach sections into Envelope, VirtualSystem or VirtualSystemCollection</li>
* <br>
* TODO add ''final'' modifier on all the input parameters
*/
public class OVFEnvelopeUtils {
private final static Logger log = LoggerFactory.getLogger(OVFEnvelopeUtils.class);
/** Generated factory to create XML OVF-elements in OVF name space . */
private final static org.dmtf.schemas.ovf.envelope._1.ObjectFactory envelopFactory = new org.dmtf.schemas.ovf.envelope._1.ObjectFactory();
/** Utility methods for the Reference element. */
public final static OVFReferenceUtils fileReference = new OVFReferenceUtils();
/** Utility methods for the Disk section element. */
public final static OVFDiskUtils diskSection = new OVFDiskUtils();
/** Utility methods for the Network section element. */
public final static OVFNetworkUtils networkSection = new OVFNetworkUtils();
/** Utility methods for the Product section element. */
public final static OVFProductUtils productSection = new OVFProductUtils();
/** Utility methods for the Virtual Hardware section element. */
public final static OVFVirtualHadwareSectionUtils hardwareSection = new OVFVirtualHadwareSectionUtils();
/*
* Values (from CIM_ResourceAllocationSettingData ResourceType property
* value map)
*/
public final static int ResourceTypeCPU = 3;
public final static int ResourceTypeMEMORY = 4;
public final static int ResourceTypeNIC = 10;
public final static int ResourceTypeDISK = 17;
/**
* Using the Core Metadata Section table from the OVF specification
* determine when a specific section is allowed on the OVF envelope element.
*
* @param sectionType
* , a section class to be checked if is complain to appear on
* the envelope.
* @throws InvalidSectionException
* , if the section type is not allowed on the envelope.
*/
public static <T extends SectionType> void checkEnvelopeSection(Class<T> sectionType) throws InvalidSectionException {
if (!DiskSectionType.class.equals(sectionType)
& !NetworkSectionType.class.equals(sectionType)
& !AnnotationSectionType.class.equals(sectionType)
& !DeploymentOptionSectionType.class.equals(sectionType)
& !VirtualHardwareSectionType.class.equals(sectionType)
& !ProductSectionType.class.equals(sectionType)
& !KPISectionType.class.equals(sectionType)
& !DeploymentSectionType.class.equals(sectionType)
& !AffinitySectionType.class.equals(sectionType)
& !AspectsSectionType.class.equals(sectionType)
& !DiskMappingSectionType.class.equals(sectionType)
& !AvailabilitySectionType.class.equals(sectionType)
& !PerformanceObjectiveSectionType.class.equals(sectionType)
)
{
throw new InvalidSectionException("Envelope", sectionType);
}
}
/**
* Using the Core Metadata Section table from the OVF specification
* determine when a specific section is allowed on the content element
* (could be VirtualSystem or VirtualSystemCollection).
*
* @param vsystem
* , a VirtualSystem or a VirtualSystemCollection class.
* @param sectionType
* , a section class to be checked if is complain to appear on
* the given Content (virtual system or collection).
* @throws InvalidSectionException
* , if the section type is not allowed on the content element.
*/
public static <T extends SectionType> void checkContentSection(Class<? extends ContentType> vsystem, Class<T> sectionType) throws InvalidSectionException {
// is an VirtualSystemCollectionType
if (VirtualSystemCollectionType.class.equals(vsystem)) {
if (!StartupSectionType.class.equals(sectionType)
& !EulaSectionType.class.equals(sectionType)
& !ProductSectionType.class.equals(sectionType)
& !AnnotationSectionType.class.equals(sectionType)
& !ResourceAllocationSectionType.class.equals(sectionType)
& !VirtualHardwareSectionType.class.equals(sectionType)) {
throw new InvalidSectionException("VirtualSystemCollection", sectionType);
}
} else
// is an VirtualSystemType
{
if (!VirtualHardwareSectionType.class.equals(sectionType)
& !InstallSectionType.class.equals(sectionType)
& !OperatingSystemSectionType.class.equals(sectionType)
& !EulaSectionType.class.equals(sectionType)
& !ProductSectionType.class.equals(sectionType)
& !AnnotationSectionType.class.equals(sectionType)
& !VirtualHardwareSectionType.class.equals(sectionType)
& !ElasticArraySectionType.class.equals(sectionType)
& !AvailabilitySectionType.class.equals(sectionType)
& !PerformanceObjectiveSectionType.class.equals(sectionType)
& !DeploymentSectionType.class.equals(sectionType)
& !AntiAffinityType.class.equals(sectionType)
& !FirewallSectionType.class.equals(sectionType)
& !LoadBalancerSectionType.class.equals(sectionType)
) {
throw new InvalidSectionException("VirtualSystem", sectionType);
}
}
}
/**
* Instantiate the desired implementation of a section type.
*
* @param sectionType
* , the section class to be instantiated.
* @param msg
* , a message content to be attached on the instantiated section
* @return the required section object.
*/
public static <T extends SectionType> T createSection(Class<T> sectionType, String msg) throws SectionException {
T section;
try {
section = sectionType.newInstance();
section.setInfo(CIMTypesUtils.createMsg(msg, null));
// section.setRequired(---) TODO set Required (but it change if the
// secction if for envelope/vs or vsc ...)
} catch (Exception e) {
throw new SectionException("Section " + sectionType.getName() + " can not be instantiated ");
}
return section;
}
/**
* Gets the specified section form the provided OVFEnvelope.
*
* @param envelope
* , the OVF envelope to be inspected
* @param sectionType
* , the desired section to be extracted form the envelope.
* @return the section if present on the highest level envelope content.
* @throws SectionNotPresentException
* , when there is not the desired section defined.
*/
@SuppressWarnings("unchecked")
public static <T extends SectionType> T getSection(EnvelopeType envelope, Class<T> sectionType) throws SectionNotPresentException, InvalidSectionException {
SectionType section;
checkEnvelopeSection(sectionType);
for (JAXBElement<? extends SectionType> jxbsection : envelope.getSection()) {
section = jxbsection.getValue();
if (sectionType.isInstance(section)) {
return (T) section;
}
}
throw new SectionNotPresentException(sectionType);
}
/**
* Gets the specified section form provided VirtualSystem.
*
* @param vsystem
* , the virtual system or virtual system collection to be
* inspected
* @param sectionType
* , the desired section to be extracted form the virtual system
* or virtual system collection.
* @return the section if present on the virtual system or virtual system
* collection.
* @throws SectionNotPresentException
* , when there is not the desired section defined.
*/
@SuppressWarnings("unchecked")
public static <T extends SectionType> T getSection(ContentType vsystem, Class<T> sectionType) throws SectionNotPresentException, InvalidSectionException {
SectionType section;
checkContentSection(vsystem.getClass(), sectionType);
for (JAXBElement<? extends SectionType> jxbsection : vsystem.getSection()) {
section = jxbsection.getValue();
if (sectionType.isInstance(section)) {
return (T) section;
}
}
throw new SectionNotPresentException(sectionType);
}
/**
* Adds the specified section on the provided OVFEnvelope.
*
* @param envelope
* , the OVF envelope to be modified.
* @param sectionType
* , the desired section to be added on the envelope.
* @throws SectionAlreadyPresentException
* , when a sectionType is already defined on the envelope
* level.
*/
public static <T extends SectionType> void addSection(EnvelopeType envelope, T section) throws SectionAlreadyPresentException, InvalidSectionException {
try {
getSection(envelope, section.getClass());
throw new SectionAlreadyPresentException(section.getClass());
} catch (SectionNotPresentException e1) {
// so lets add it
}
//TODO ElasticArraySection???? add to VSC not to Envelope???
try {
if (section instanceof DiskSectionType)
envelope.getSection().add(envelopFactory.createDiskSection((DiskSectionType) section));
else if (section instanceof NetworkSectionType)
envelope.getSection().add(envelopFactory.createNetworkSection((NetworkSectionType) section));
else if (section instanceof DeploymentOptionSectionType)
envelope.getSection().add(envelopFactory.createDeploymentOptionSection((DeploymentOptionSectionType) section));
else if (section instanceof AffinitySectionType)
envelope.getSection().add(envelopFactory.createAffinitySection((AffinitySectionType) section));
else if (section instanceof AspectsSectionType)
envelope.getSection().add(envelopFactory.createAspectsSection((AspectsSectionType) section));
else if (section instanceof DeploymentSectionType)
envelope.getSection().add(envelopFactory.createDeploymentSection((DeploymentSectionType) section));
else if (section instanceof DiskMappingSectionType)
envelope.getSection().add(envelopFactory.createDiskMappingSection((DiskMappingSectionType) section));
else if (section instanceof KPISectionType)
envelope.getSection().add(envelopFactory.createKPISection((KPISectionType) section));
else if (section instanceof AvailabilitySectionType)
envelope.getSection().add(envelopFactory.createAvailabilitySection((AvailabilitySectionType) section));
else if (section instanceof PerformanceObjectiveSectionType)
envelope.getSection().add(envelopFactory.createPerformanceObjectiveSection((PerformanceObjectiveSectionType) section));
else if (section instanceof AnnotationSectionType)
envelope.getSection().add(envelopFactory.createAnnotationSection((AnnotationSectionType) section));
else
envelope.getSection().add(envelopFactory.createSection(section));
} catch (Exception e) // InstantiationException or
// IllegalAccessException
{
log.error("The class " + section.getClass().getCanonicalName() + " can not be instantiated");
}
}
/**
* Add the specified section form the provided virtual system.
*
* @param vsystem
* , the virtual system or virtual system collection to be
* modified
* @param sectionType
* , the desired section to be added on the virtual system or
* virtual system collection.
* @throws SectionAlreadyPresentException
* , when a sectionType is already defined on the virtual system
* or collection (note: only VirtualHardware, Product and Eula
* sections can appear more than once).
*/
public static void addSection(ContentType vsystem, SectionType section) throws SectionAlreadyPresentException, InvalidSectionException {
try {
getSection(vsystem, section.getClass());
// note: only VirtualHardware, Product and Eula sections can appear
// more than once
if (!FirewallSectionType.class.equals(section.getClass()) & !LoadBalancerSectionType.class.equals(section.getClass()) & !ProductSectionType.class.equals(section.getClass()) & !EulaSectionType.class.equals(section.getClass()) & !VirtualHardwareSectionType.class.equals(section.getClass())
) {
throw new SectionAlreadyPresentException(section.getClass());
}
} catch (SectionNotPresentException e1) {
// so lets create it
}
try {
if (section instanceof OperatingSystemSectionType)
vsystem.getSection().add(envelopFactory.createOperatingSystemSection((OperatingSystemSectionType) section));
else if (section instanceof ProductSectionType)
vsystem.getSection().add(envelopFactory.createProductSection((ProductSectionType) section));
else if (section instanceof VirtualHardwareSectionType)
vsystem.getSection().add(envelopFactory.createVirtualHardwareSection((VirtualHardwareSectionType) section));
else if (section instanceof ElasticArraySectionType)
vsystem.getSection().add(envelopFactory.createElasticArraySection((ElasticArraySectionType) section));
else if (section instanceof FirewallSectionType)
vsystem.getSection().add(envelopFactory.createFirewallSection((FirewallSectionType) section));
else if (section instanceof LoadBalancerSectionType)
vsystem.getSection().add(envelopFactory.createLoadBalancerSection((LoadBalancerSectionType) section));
else
vsystem.getSection().add(envelopFactory.createSection(section));
} catch (Exception e) // InstantiationException or
// IllegalAccessException
{
log.error("The class " + section.getClass().getCanonicalName() + " can not be instantiated");
}
}
/*******************************************************************************
* VITTUAL SYSTEM / COLLECTION CONTENT
*******************************************************************************/
/**
* Creates an empty virtual system with tcloud params.
*
* @param vsId
* , the required virtual system identifier.
* @param name
* , the optional name for the virtual system.
* @param info
* , the optional attached information.
* @param min
* , to specify the minimum number of instances in the array.
* @param max
* , to specify the maximum number of instances in the array.
* @param initial
* , to specify the initial number of instances in the array.
* @return an empty (any section on it) virtual system with the provided Id,
* name and information message.
*/
public static VirtualSystemType createVirtualSystem(String vsId, String name, String info, Integer min, Integer max, Integer initial) throws RequiredAttributeException {
if (vsId == null) {
throw new RequiredAttributeException("VirtualSystem attribute ID");
}
VirtualSystemType vs = new VirtualSystemType();
vs.setId(vsId);
vs.setInfo(CIMTypesUtils.createMsg(info, null));
vs.setName(CIMTypesUtils.createMsg(name, null));
try {
QName minAtt = new QName("http://schemas.telefonica.com/claudia/ovf", "min");
OVFVirtualSystemUtils.addOtherAttributes(vs, minAtt, Integer.toString(min.intValue()));
} catch (IdAlreadyExistsException e) {
log.error("Attribute min already defined");
}
catch (RequiredAttributeException e) {
log.error(e.getLocalizedMessage());
}
try {
QName maxAtt = new QName("http://schemas.telefonica.com/claudia/ovf", "max");
OVFVirtualSystemUtils.addOtherAttributes(vs, maxAtt, Integer.toString(max.intValue()));
} catch (IdAlreadyExistsException e) {
log.error("Attribute max already defined");
}
catch (RequiredAttributeException e) {
log.error(e.getLocalizedMessage());
}
try {
QName initialAtt = new QName("http://schemas.telefonica.com/claudia/ovf", "initial");
OVFVirtualSystemUtils.addOtherAttributes(vs, initialAtt, Integer.toString(initial.intValue()));
} catch (IdAlreadyExistsException e) {
log.error("Attribute initial already defined");
}
catch (RequiredAttributeException e) {
log.error(e.getLocalizedMessage());
}
return vs;
}
/**
* Creates an empty virtual system collection.
*
* @param vsId
* , the required virtual system identifier.
* @param name
* , the optional name for the virtual system collection.
* @param info
* , the optional attached information
* @return an empty (any section on it) virtual system with the provided Id,
* name and information message.
*/
public static VirtualSystemCollectionType createVirtualSystemCollection(String vsId, String name, String info) throws RequiredAttributeException {
if (vsId == null) {
throw new RequiredAttributeException("VirutalSystem attribute ID");
}
VirtualSystemCollectionType vsc = new VirtualSystemCollectionType();
vsc.setId(vsId);
vsc.setInfo(CIMTypesUtils.createMsg(info, null));
vsc.setName(CIMTypesUtils.createMsg(name, null));
return vsc;
}
/**
* Check if the given envelope contains more than one virtual system. (if
* there is a virtual system collection)
*
* @return true if there is only one virtual system on the provided OVF
* envelope content.
* @throws EmptyEnvelopeException
* it the envelope do not contain any virtual system or virtual
* system collection
*/
public static boolean isOneVirtualSystem(EnvelopeType envelope) throws EmptyEnvelopeException {
boolean isVirtualSystem;
ContentType entity = envelope.getContent().getValue();
if (entity == null) {
throw new EmptyEnvelopeException();
}
if (entity instanceof VirtualSystemType) {
isVirtualSystem = true;
} else if (entity instanceof VirtualSystemCollectionType) {
isVirtualSystem = false;
} else {
throw new EmptyEnvelopeException("Invalid envelope, it do not contains virtualsytem or virtualsystemcollections its a " + entity.getClass().getCanonicalName());
}
return isVirtualSystem;
}
/**
* Gets the virtual system collection presents on the OVF envelope.
*
* @return the highest level virtual system collection or virtual system
* collection
* @throws EmptyEnvelopeException
* if the provided OVF envelope do not contain any content
*/
public static ContentType getTopLevelVirtualSystemContent(EnvelopeType envelope) throws EmptyEnvelopeException {
ContentType vs;
JAXBElement<? extends ContentType> content = envelope.getContent();
if (content != null) {
vs = content.getValue();
if (vs == null) {
throw new EmptyEnvelopeException();
}
} else {
throw new EmptyEnvelopeException();
}
return vs;
}
/**
* Extract all the virtual systems (and virtual system collections) form a
* collection.
*
* @return all the virtual system and collections contained on the provided
* virtual system collection.
*/
public static Set<ContentType> getVirtualSystemsFromCollection(VirtualSystemCollectionType vsCollection) {
Set<ContentType> systems = new HashSet<ContentType>();
List<JAXBElement<? extends ContentType>> vsCollectContent = vsCollection.getContent();
for (JAXBElement<? extends ContentType> elem : vsCollectContent) {
ContentType entity = elem.getValue();
systems.add(entity);
}
return systems;
}
/**
* Extract all the virtual systems (and virtual system collections) form a
* collection.
*
* @return all the virtual system and collections contained on the provided
* virtual system collection.
*/
public static List<VirtualSystemType> getVirtualSystems(VirtualSystemCollectionType vsCollection) {
List<VirtualSystemType> systems = new LinkedList<VirtualSystemType>();
List<JAXBElement<? extends ContentType>> vsCollectContent = vsCollection.getContent();
for (JAXBElement<? extends ContentType> elem : vsCollectContent) {
ContentType entity = elem.getValue();
if (entity instanceof VirtualSystemType) {
systems.add((VirtualSystemType) entity);
} else // collection
{
systems.addAll(getVirtualSystems((VirtualSystemCollectionType) entity));
}
}
return systems;
}
/**
* Adds a new virtual system on the virtual system collection.
*
* @param collection
* , the virtual system collection to be changed.
* @param system
* , the virtual system or virtual system collection to add.
*/
public static <T extends ContentType> void addVirtualSystem(VirtualSystemCollectionType collection, T system) throws IdAlreadyExistsException {
log.debug("Adding virutal system id:" + system.getId() + " to collection " + collection.getId());
checkVirtualSystemId(collection, system.getId());
if (system instanceof VirtualSystemType) {
collection.getContent().add(envelopFactory.createVirtualSystem((VirtualSystemType) system));
} else if (system instanceof VirtualSystemCollectionType) {
collection.getContent().add(envelopFactory.createVirtualSystem((VirtualSystemType) system));
} else {
log.error("The provided content type is not a virtual system or vs collection, its a {}", system.getClass().getCanonicalName());
}
}
/**
* Check if there is some other Content (virtual system or system
* collection) with the same if on the given virtual system collection.
*
* @param vscollection
* , a virtual system collection to be check.
* @param vsId
* , the identifier to be assert it is unique.
* @throws IdAlreadyExists
* it there is some other virtual system with the same id.
*/
public static void checkVirtualSystemId(VirtualSystemCollectionType vscollection, final String vsId) throws IdAlreadyExistsException {
ContentType content;
for (JAXBElement<? extends ContentType> jxbcontent : vscollection.getContent()) {
content = jxbcontent.getValue();
if (vsId.equals(content.getId())) {
throw new IdAlreadyExistsException("Virtual system id " + vsId + " on collectino " + vscollection.getId());
}
}
}
/***
* TODO doc : call with vs and vsc
*
* @throws IdAlreadyExistsException
* */
public static <T extends ContentType> void addVirtualSystem(EnvelopeType envelope, T contentType) throws IdAlreadyExistsException {
if (VirtualSystemType.class.isInstance(contentType)) {
addVirtualSystem(envelope, (VirtualSystemType) contentType);
} else if (VirtualSystemCollectionType.class.isInstance(contentType)) {
addVirtualSystemCollection(envelope, (VirtualSystemCollectionType) contentType);
} else {
// TODO throw invalid content exception
}
}
/**
* Adds a new virtual system on the OVF envelope. If there is a virtual
* system collection is added there (highest level collection), if there is
* a previous virtual system a new virtual system collection is created to
* wrap both, if there is any virtual system/collection simply added.
*
* @param envelope
* , the OVFenvelope to be changed.
* @param system
* , the virtual system to add.
* @throws IdAlreadyExists
*/
public static void addVirtualSystem(EnvelopeType envelope, VirtualSystemType system) throws IdAlreadyExistsException {
log.debug("Adding virutal system id:" + system.getId());
JAXBElement<VirtualSystemType> elementSystem = envelopFactory.createVirtualSystem(system);
if (envelope.getContent() == null) // the envelope do not contain any
// previous VirtualSystem
{
envelope.setContent(elementSystem);
} else
// envelope already contains some virtual systems (or collection)
{
ContentType entity = envelope.getContent().getValue();
if (entity instanceof VirtualSystemType) {
final String msg = "Adding virutal system on an envelope witch already habe a virtual system," + " a new VirtualSystemCollection will be created to wrap both";
log.warn(msg);
VirtualSystemType entityPrevRoot = (VirtualSystemType) entity;
VirtualSystemCollectionType collection = new VirtualSystemCollectionType();
// TODO require some Section to be moved ??? (think on
// product/eula ....)
collection.setInfo(CIMTypesUtils.createMsg(msg, null));
collection.setId("wrap_" + entityPrevRoot.getId() + "_" + system.getId());
collection.getContent().add(envelopFactory.createVirtualSystem(entityPrevRoot));// previous
collection.getContent().add(envelopFactory.createVirtualSystem(system));// actual
envelope.setContent(envelopFactory.createVirtualSystemCollection(collection));
} else if (entity instanceof VirtualSystemCollectionType) {
final String msg = "There is a virtual system collection already";
log.debug(msg);
checkVirtualSystemId((VirtualSystemCollectionType) entity, system.getId());
VirtualSystemCollectionType collection = (VirtualSystemCollectionType) entity;
collection.getContent().add(elementSystem);
} else {
log.error("Invalid envelope, it do not contains virtualsytem or virtualsystemcollections its a " + entity.getClass().getCanonicalName());
}
}// some previous content
}
/**
* Check if the provided virtual system collection is or contains the given
* collection Id.
*
* @param collection
* , the virtual system collection to be check and inspected its
* elements.
* @param collecitonId
* , the desired collection Id.
* @return the virtual system collection (provided or nested on) with Id
* equals to provided.
* @throws IdNotFoundException
* if the collection and any of its nested elements have the
* desired Id.
*/
private static VirtualSystemCollectionType getVirtualSystemCollection(VirtualSystemCollectionType collection, final String collectionId) throws IdNotFoundException {
for (JAXBElement<? extends ContentType> system : collection.getContent()) {
ContentType entitySystem = system.getValue();
if (entitySystem instanceof VirtualSystemCollectionType) {
try {
return getVirtualSystemCollection((VirtualSystemCollectionType) entitySystem, collectionId);
} catch (IdNotFoundException e) {
// check if there is more virtual systems collections nested
// the given
// collection.
}
}
}// subcollections
throw new IdNotFoundException("Virtual system collection " + collectionId + " not found");
}
/**
* Adds a new virtual system collection on the OVF envelope. If there is a
* virtual system collection is added there (highest level collection), if
* there is a previous virtual system this is added on the collection, if
* there is any virtual system/collection simply added.
*
* @param envelope
* , the OVFenvelope to be changed.
* @param collection
* , the virtual system collection to add. TODO throw except if
* id already on the present collection
* @throws IdAlreadyExists
*/
public static void addVirtualSystemCollection(EnvelopeType envelope, VirtualSystemCollectionType collection) throws IdAlreadyExistsException {
log.debug("Adding virutal system collection id:" + collection.getId());
JAXBElement<VirtualSystemCollectionType> elementCollection = envelopFactory.createVirtualSystemCollection(collection);
if (envelope.getContent() == null) // the envelope do not contain any
// previous VirtualSystem
{
envelope.setContent(elementCollection);
} else
// envelope already contains some virtual systems (or collection)
{
ContentType entity = envelope.getContent().getValue();
if (entity instanceof VirtualSystemType) {
final String msg = "Adding virutal system collection on an envelope witch already habe a virtual system," + " previous virtual system added to collection";
// TODO perhaps better to have collection{vs, vsc}
log.warn(msg);
// TODO performance: use prev pointer
collection.getContent().add(envelopFactory.createVirtualSystem((VirtualSystemType) entity));
envelope.setContent(envelopFactory.createVirtualSystemCollection(collection));
// TODO perfomance : can i use elementCollection ?
} else if (entity instanceof VirtualSystemCollectionType) {
final String msg = "There is a virtual system collection already";
log.debug(msg);
VirtualSystemCollectionType prevCollection = (VirtualSystemCollectionType) entity;
checkVirtualSystemId(prevCollection, elementCollection.getValue().getId());
prevCollection.getContent().add(elementCollection);
} else {
log.error("Invalid envelope, it do not contains virtualsytem or virtualsystemcollections its a " + entity.getClass().getCanonicalName());
// TODO throw or remove
}
}// some previous content
}
/**
* Adds a virtual system collection on the given virtual system collection.
*
* @param envelope
* , the OVFenvelope to be changed.
* @param collection
* , the virtual system collection to add.
* @param collectionID
* , the virtual system collection identifier on the envelope.
* @throws IdNotFoundException
* if the provided envelope do not contain a virtual system
* collection with provided ID.
*/
public static void addVirtualSystemCollection(EnvelopeType envelope, VirtualSystemCollectionType collection, String collectionId) throws IdNotFoundException {
log.debug("Adding virutal system collection id:" + collection.getId() + " to collection: " + collectionId);
JAXBElement<VirtualSystemCollectionType> elementCollection = envelopFactory.createVirtualSystemCollection(collection);
if (envelope.getContent() == null) // the envelope do not contain any
// previous VirtualSystem
{
final String msg = "The provided envelope do not conatain any virutal system or collection";
throw new IdNotFoundException(msg);
} else
// envelope already contains some virtual systems (or collection)
{
ContentType entity = envelope.getContent().getValue();
if (entity instanceof VirtualSystemType) {
final String msg = "The provided envelope only contains a virutal system";
throw new IdNotFoundException(msg);
} else if (entity instanceof VirtualSystemCollectionType) {
VirtualSystemCollectionType targetCollection = getVirtualSystemCollection((VirtualSystemCollectionType) entity, collectionId);
targetCollection.getContent().add(elementCollection);
// TODO check id not exist
} else {
log.error("Invalid envelope, it do not contains virtualsytem or virtualsystemcollections its a " + entity.getClass().getCanonicalName());
// TODO throw or remove
}
}// some previous content
}
/**
* Gets all the virtual disk descriptions on the disk section for the
* provided OVF envelope.
*
* @param envelope
* , the OVFenvelope to be inspected.
* @return all the defined disk descriptions on the OVF envelope.
*/
public static Set<VirtualDiskDescType> getAllVirtualDiskDescription(EnvelopeType envelope) throws SectionNotPresentException {
DiskSectionType sectionDisk = null;
Set<VirtualDiskDescType> disks = new HashSet<VirtualDiskDescType>();
try {
sectionDisk = getSection(envelope, DiskSectionType.class);
} catch (InvalidSectionException e) {
// network is allowed on the envelope
}
disks.addAll(sectionDisk.getDisk());
return disks;
}
/**
* Extract *all* the product sections for a collection.
*
* @return all the product sections on the provided virtual system collection.
*/
/*
* FIXME: Accordingly to the OVF Environment document production rules in DSP0243 1.0.0 lines 1322-1325,
* all the VirtualSystems in a given VirtualSystemCollection get the Properties defined in
* ProductSections placed at VirtualSystemCollection level: "The PropertySection contains the
* key/value pairs defined for all the properties specified in the OVF descriptor for the
* current virtual machine, as well as properties specified for the *immediate parent*
* VirtualSystemCollection, if one exists". Currently, we are considering *all* the containment
* tree, which although is ok for RESERVOIR (we only have one VirtualSystemCollection conatiement
* layer) is not following the standard in strict sense.
*/
public static List<ProductSectionType> getAllProductSections(VirtualSystemCollectionType vsCollection) {
List<ProductSectionType> ps = new LinkedList<ProductSectionType>();
// Add product sections at VirtualSystemCollection level
ps.addAll(getProductSections(vsCollection));
// Explore contained VirtualSystems and VirtualSystemCollections
List<JAXBElement<? extends ContentType>> vsCollectContent = vsCollection.getContent();
for (JAXBElement<? extends ContentType> elemContent : vsCollectContent) {
ContentType entity = elemContent.getValue();
if (entity instanceof VirtualSystemType) {
// Add product sections at VirtualSystemType level
ps.addAll(getProductSections(entity));
}
else if (entity instanceof VirtualSystemCollectionType) {
// Continue adding child elements
ps.addAll(getAllProductSections((VirtualSystemCollectionType) entity));
}
}
return ps;
}
/**
* Extract the product sections for a VirtualSystem or VirtualSystemCollection. In
* the latter case it refers to *local* ProductSections, i.e. without going into
* containing VirtualSystems or VirtualSystemCollections (for that, use getAllProductSections
* instead)
*
* @return all the product sections on the provided virtual system or virtual system collection.
*/
public static List<ProductSectionType> getProductSections(ContentType entity) {
List<ProductSectionType> ps = new LinkedList<ProductSectionType>();
List<JAXBElement<? extends SectionType>> sections = entity.getSection();
for (JAXBElement<? extends SectionType> elemSection : sections) {
SectionType section = elemSection.getValue();
if (section instanceof ProductSectionType) {
System.out.println (section);
ps.add((ProductSectionType) section);
}
}
return ps;
}
/**
* Get the parent VirtualSystemCollection that contains a given VirtualSystem and a top
* VirtualSystemCollection
*
* @return all the product sections on the provided virtual system collection.
*
* FIXME: add exceptions properly when the vs is not in the vsc or the
* (replace the 'return null')
*/
public static VirtualSystemCollectionType getContainingVirtualSystemCollection(VirtualSystemCollectionType vsc, VirtualSystemType vs) {
/* FIXME: Maybe not too efficient, but I don't see any other way... Using
* the envelop as part of the invocation parameters is a bit unsmart, I would
* like to get rid of it (Fermin) */
List<JAXBElement<? extends ContentType>> vsCollectContent = vsc.getContent();
for (JAXBElement<? extends ContentType> elemContent : vsCollectContent) {
ContentType entity = elemContent.getValue();
if (entity instanceof VirtualSystemType) {
if (vs.getId().equals(entity.getId())) {
return vsc;
}
}
else if (entity instanceof VirtualSystemCollectionType) {
/* Search recursively inside the VirtualSystemCollection */
return getContainingVirtualSystemCollection(vsc, vs);
}
}
/* If this point is reached, then the VirtualSystem has no parent */
return null;
}
/**
* Get a given content (VirtualSystem or VirtualSystemCollection) by String
* @param vsc
* @param id
* @return
* FIXME: null equals to not found. Return exception instead?
*/
public static ContentType getContentTypeByString(VirtualSystemCollectionType vsc, String id) {
List<JAXBElement<? extends ContentType>> vsCollectContent = vsc.getContent();
for (JAXBElement<? extends ContentType> elemContent : vsCollectContent) {
ContentType entity = elemContent.getValue();
if (entity.getId().equals(id)) {
return entity;
}
else if (entity instanceof VirtualSystemCollectionType) {
/* Search recursively inside the VirtualSystemCollection */
return getContentTypeByString(vsc, id);
}
}
/* If this point is reached, then the VirtualSystem has not been found */
return null;
}
/**
* Analyzes the ProductSection for the given vs and returns a HashMap with the
* numer of required IPs for each network, based on the analysis of @IP(net) and
* @IP(net,alias) macros
*
* @return
*/
public static HashMap<String,Integer> getRequiredIPByNetwork(EnvelopeType envel, VirtualSystemType vs) {
// FIXME: put the MACROS in OVFEnvironemenUtils in a place that they can be reach
// by both classes, so we don't need to do the following line explictly
String IP_MACRO = "IP";
HashMap<String, ArrayList<String>> aliasMap = new HashMap<String,ArrayList<String>>();
try {
/* Get the ProductSections for that VM */
VirtualSystemCollectionType topVsc;
topVsc = (VirtualSystemCollectionType) OVFEnvelopeUtils.getTopLevelVirtualSystemContent(envel);
VirtualSystemCollectionType parentVsc = OVFEnvelopeUtils.getContainingVirtualSystemCollection(topVsc, vs);
List<ProductSectionType> listProductSection = new LinkedList<ProductSectionType>();
listProductSection.addAll(OVFEnvelopeUtils.getProductSections(vs));
listProductSection.addAll(OVFEnvelopeUtils.getProductSections(parentVsc));
/* Search in the ProductSections */
for (Iterator<ProductSectionType> iteratorPs = listProductSection.iterator(); iteratorPs.hasNext();) {
ProductSectionType prodSection = (ProductSectionType) iteratorPs.next();
List<Property> propertyList = OVFProductUtils.getAllProperties(prodSection);
for (Iterator<Property> iterator = propertyList.iterator(); iterator.hasNext();) {
Property property = (Property) iterator.next();
Map<QName, String> attributes = property.getOtherAttributes();
QName cloudConfigurable = new QName("http://schemas.telefonica.com/claudia/ovf","cloudConfigurable");
if ( Boolean.valueOf(attributes.get(cloudConfigurable)))
{
String value = property.getValue();
if (value.contains("@"+IP_MACRO))
{
String prefix = "@" + IP_MACRO + "(";
String macroValue = value.substring(value.indexOf(prefix)+prefix.length(),value.indexOf(")"));
/* Two possibilities to take into account: @IP(net) or @IP(net,alias). Note that
* alias = "" in the case @IP(net) is used */
String network;
String alias = "";
StringTokenizer macroValueTokenizer = new StringTokenizer(macroValue,",");
network = macroValueTokenizer.nextToken();
if (macroValueTokenizer.hasMoreElements()) {
alias = macroValueTokenizer.nextToken();
}
/* In the network already exist in the aliasMap? */
if (aliasMap.get(network)!= null) {
/* Is the alias in the list associated to the network? */
if (!aliasMap.get(network).contains(alias)) {
/* If not, add it to the list */
ArrayList<String> l = aliasMap.get(network);
l.add(alias);
aliasMap.put(network, l);
}
}
else {
/* If not, create the network and add the first alias */
ArrayList<String> l = new ArrayList<String>();
l.add(alias);
aliasMap.put(network,l);
}
}
}
}
}
} catch (EmptyEnvelopeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/* Analize the number of alias in each network */
HashMap<String,Integer> ips = new HashMap<String,Integer>();
for ( Iterator<String> i = aliasMap.keySet().iterator(); i.hasNext() ; ) {
String net = i.next();
ips.put(net, new Integer(aliasMap.get(net).size()));
}
return ips;
}
/**
* Performs a macro replacement in the ProductSections of the Envelope passed as argument
* in the context of the VirtualSystem passed as argument (i.e. the VirtualSystem itself
* and possibly the containing VirtualSystemCollection). The other ProductSections are not
* touched. Note that if the Envelope contains just one VirtualSystem all the ProductSections
* are processed
*
* @param env
* @param vs
* @param instanceNumber
* @param domain
* @param serviceId
* @param monitoringChannel
* @param ips
* @param netmasks
* @param dnsServers
* @param gateways
* @param entryPoints
* @return
* @throws EmptyEnvelopeException
*/
public static void inEnvolopeMacroReplacement(EnvelopeType env,
VirtualSystemType vs,
int instanceNumber,
String domain,
String serviceId,
String veeId,
String monitoringChannel,
HashMap<String,ArrayList<String>> ips,
HashMap<String, String> netmasks,
HashMap<String, String> dnsServers,
HashMap<String, String> gateways,
HashMap<String, HashMap<String, String> > entryPoints)
throws
EmptyEnvelopeException,
IPNotFoundException,
DNSServerNotFoundException,
NetmaskNotFoundException,
GatewayNotFoundException,
PrecedentTierEntryPointNotFoundException,
NotEnoughIPsInPoolException,
PoolNameNotFoundException {
VirtualSystemCollectionType parentVsc = null;
if (!OVFEnvelopeUtils.isOneVirtualSystem(env)) {
parentVsc = OVFEnvelopeUtils.getContainingVirtualSystemCollection((VirtualSystemCollectionType) OVFEnvelopeUtils.getTopLevelVirtualSystemContent(env), vs);
}
/* Accumulating ProducSections in the scope of the VirtualSystem*/
List<ProductSectionType> listProductSection = new LinkedList<ProductSectionType>();
listProductSection.addAll(OVFEnvelopeUtils.getProductSections(vs));
if (parentVsc != null) {
listProductSection.addAll(OVFEnvelopeUtils.getProductSections(parentVsc));
}
/* Create a tag to register IPs for alias, dual key: (network, alias) -> ip */
HashMap<String, HashMap<String,String>> registeredAliasIPs = new HashMap<String, HashMap<String,String>>();
for (Iterator<ProductSectionType> iteratorPs = listProductSection.iterator(); iteratorPs.hasNext();) {
ProductSectionType prodSection = (ProductSectionType) iteratorPs.next();
/* Processing properties one by one */
List<Property> propertyList = OVFProductUtils.getAllProperties(prodSection);
for (Iterator<Property> iterator = propertyList.iterator(); iterator.hasNext();) {
Property property = (Property) iterator.next();
Map<QName, String> attributes = property.getOtherAttributes();
QName cloudConfigurable = new QName("http://schemas.telefonica.com/claudia/ovf","cloudConfigurable");
String effectiveValue;
if ( Boolean.valueOf(attributes.get(cloudConfigurable)))
{
effectiveValue = OVFGeneralUtils.macroReplacement(property.getValue(),
instanceNumber,
domain,
serviceId,
veeId,
monitoringChannel,
ips,
netmasks,
dnsServers,
gateways,
entryPoints,
registeredAliasIPs);
property.setValue(effectiveValue);
}
}
}
}
/**
* Split the given Service OVF file into as many files as VirtualSystems are found in it.
*
* @param env
* A service OVF file. It has to contain a VirtualSystemCollection item.
*
* @return
* A list of OVF Envelopes, each one representing the information of a Virtual System.
* @throws Exception
*/
public static HashMap<String, EnvelopeType> splitOvf(EnvelopeType env) throws Exception {
HashMap<String, EnvelopeType> results = new HashMap<String, EnvelopeType>();
ContentType entityInstance = null;
try {
entityInstance = OVFEnvelopeUtils.getTopLevelVirtualSystemContent(env);
} catch (EmptyEnvelopeException e) {
log.error("Empty envelope found: " + e);
}
if (entityInstance instanceof VirtualSystemType) {
// If the entity is already a VirtualSystem, return a list with the virtual system itself.
results.put(entityInstance.getId(), env);
} else if (entityInstance instanceof VirtualSystemCollectionType) {
VirtualSystemCollectionType virtualSystemCollectionType = (VirtualSystemCollectionType) entityInstance;
List<ProductSectionType> productSections=null;
productSections = OVFEnvelopeUtils.getProductSections(virtualSystemCollectionType);
for (VirtualSystemType vs : OVFEnvelopeUtils.getVirtualSystems(virtualSystemCollectionType)) {
// Create the envelope
ObjectFactory ovfFactory = new ObjectFactory();
EnvelopeType vsEnv = ovfFactory.createEnvelopeType();
// Add the VirtualSystem to the envelope
try {
ReferencesType references = ovfFactory.createReferencesType();
vsEnv.setReferences(references);
DiskSectionType diskSection = ovfFactory.createDiskSectionType();
diskSection.setInfo(new MsgType());
NetworkSectionType networkSection = ovfFactory.createNetworkSectionType();
networkSection.setInfo(new MsgType());
if (productSections!=null)
for (ProductSectionType ps: productSections) {
try {
OVFEnvelopeUtils.addSection(vs, ps);
} catch (Exception snpe) {
log.warn("Product section not found: " + snpe.getMessage());
}
}
OVFEnvelopeUtils.addSection(vsEnv, diskSection);
OVFEnvelopeUtils.addSection(vsEnv, networkSection);
// Search for the disks and add them to the DiskSection and ReferenceSection
// of the child VirtualSystem
VirtualHardwareSectionType vh = null;
try {
vh = OVFEnvelopeUtils.getSection(vs, VirtualHardwareSectionType.class);
List<RASDType> items = vh.getItem();
for (Iterator<RASDType> iteratorRASD = items.iterator(); iteratorRASD.hasNext();) {
RASDType item = (RASDType) iteratorRASD.next();
/* Get the resource type and process it accordingly */
int rsType = new Integer(item.getResourceType().getValue());
log.debug("hw type: " + rsType);
switch (rsType) {
case ResourceTypeDISK:
String hostRes = item.getHostResource().get(0).getValue();
log.debug("hostresource: " + hostRes);
StringTokenizer st = new StringTokenizer(hostRes, "/");
if (st.countTokens() != 3) {
throw new Exception("malformed HostResource value (" + hostRes + ")");
}
if (!(st.nextToken().equals("ovf:"))) {
throw new Exception("HostResource must start with ovf: (" + hostRes + ")");
}
String hostResType = st.nextToken();
if (!(hostResType.equals("disk") || hostResType.equals("file"))) {
throw new Exception("HostResource type must be either disk or file: (" + hostRes + ")");
}
String hostResId = st.nextToken();
if (hostResType.equals("disk")) {
/* This type involves an indirection level */
DiskSectionType ds = null;
String fileRef = null;
try {
ds = OVFEnvelopeUtils.getSection(env, DiskSectionType.class);
} catch (SectionNotPresentException e) {
log.error(e.getMessage());
} catch (InvalidSectionException e) {
log.error(e.getMessage());
}
// Fill the disk section
List<VirtualDiskDescType> disks = ds.getDisk();
for (Iterator<VirtualDiskDescType> iteratorDk = disks.iterator(); iteratorDk.hasNext();) {
VirtualDiskDescType disk = iteratorDk.next();
fileRef = disk.getFileRef();
String diskId = disk.getDiskId();
if (diskId.equals(hostResId)) {
OVFDiskUtils.addDisk(diskSection, disk);
break;
}
}
// Fill the Reference section
if (fileRef == null) {
throw new SectionException("File reference can not be found for disk: " + hostRes);
}
ReferencesType ref = env.getReferences();
List<FileType> files = ref.getFile();
for (Iterator<FileType> iteratorFl = files.iterator(); iteratorFl.hasNext();) {
FileType fl = iteratorFl.next();
if (fl.getId().equals(fileRef)) {
OVFReferenceUtils.addFile(references, fl);
}
}
}
break;
case ResourceTypeNIC:
String netName = item.getConnection().get(0).getValue();
NetworkSectionType ns = OVFEnvelopeUtils.getSection(env, NetworkSectionType.class);
List<NetworkSectionType.Network> networks = ns.getNetwork();
for (Iterator<NetworkSectionType.Network> iteratorN = networks.iterator(); iteratorN.hasNext();) {
org.dmtf.schemas.ovf.envelope._1.NetworkSectionType.Network netInSection = iteratorN.next();
if (netInSection.getName().equals(netName))
OVFNetworkUtils.addNetwork(networkSection, netInSection);
}
break;
}
}
} catch (SectionNotPresentException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InvalidSectionException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
OVFEnvelopeUtils.addVirtualSystem(vsEnv, vs);
} catch (IdAlreadyExistsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Add the new Envelope to the results list
results.put(vs.getId(), vsEnv);
}
}
return results;
}
}