/**
* 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.
*
*/
package com.abiquo.ovf;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
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.ContentType;
import org.dmtf.schemas.ovf.envelope._1.EnvelopeType;
import org.dmtf.schemas.ovf.envelope._1.ProductSectionType;
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.dmtf.schemas.ovf.environment._1.EntityType;
import org.dmtf.schemas.ovf.environment._1.EnvironmentType;
import org.dmtf.schemas.ovf.environment._1.ObjectFactory;
import org.dmtf.schemas.ovf.environment._1.PlatformSectionType;
import org.dmtf.schemas.ovf.environment._1.PropertySectionType;
import org.dmtf.schemas.ovf.environment._1.SectionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.abiquo.ovf.exceptions.DNSServerNotFoundException;
import com.abiquo.ovf.exceptions.EmptyEnvelopeException;
import com.abiquo.ovf.exceptions.GatewayNotFoundException;
import com.abiquo.ovf.exceptions.IdAlreadyExistsException;
import com.abiquo.ovf.exceptions.NetmaskNotFoundException;
import com.abiquo.ovf.exceptions.IPNotFoundException;
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.SectionNotPresentException;
import com.abiquo.ovf.exceptions.XMLException;
import com.abiquo.ovf.section.OVFProductUtils;
import com.abiquo.ovf.section.OVFPropertyUtils;
import com.abiquo.ovf.xml.OVFEnvironmentSerializer;
import com.telefonica.claudia.ovf.utils.EnvironmentMetaData;
import com.telefonica.claudia.ovf.utils.OVFGeneralUtils;
public class OVFEnvironmentUtils
{
private final static Logger log = LoggerFactory.getLogger(OVFEnvironmentUtils.class);
private final static ObjectFactory envelopeFactory = new ObjectFactory();
public static EnvironmentType createEnvironment(String id) throws RequiredAttributeException
{
EnvironmentType enviro = new EnvironmentType();
if (id == null)
{
throw new RequiredAttributeException("Id on EnvironmentType");
}
enviro.setId(id);
return enviro;
}
public static void addEntity(EnvironmentType environment, EntityType entity)
{
environment.getEntity().add(entity);
}
/**
* platform or product section
*/
public static void setSectionToEnvironment(EnvironmentType environment, SectionType section) throws SectionAlreadyPresentException
{
// TODO check withc sections can appear once ::: getSection(environment, section.getClass());
if (section instanceof PropertySectionType)
{
environment.getSection().add(
envelopeFactory.createPropertySection((PropertySectionType) section));
}
else if (section instanceof PlatformSectionType)
{
environment.getSection().add(
envelopeFactory.createPlatformSection((PlatformSectionType) section));
}
// TODO assert not exist
}
public static <T extends SectionType> T getSection(EnvironmentType environment, Class<T> sectionType) throws SectionNotPresentException
{
SectionType section;
for (JAXBElement< ? extends SectionType> jxbsection : environment.getSection())
{
section = jxbsection.getValue();
if (sectionType.isInstance(section))
{
return (T) section;
}
}
throw new SectionNotPresentException("Section "+sectionType.getCanonicalName());
}
public static void setPropertySectionToEntity(EntityType entity,
PropertySectionType propertySection)
{
// TODO assert not exist
entity.getSection().add(envelopeFactory.createPropertySection(propertySection));
}
public static EntityType createEntity(String id) throws RequiredAttributeException
{
EntityType entity = new EntityType();
if (id == null)
{
throw new RequiredAttributeException("Id for Environment.Entity");
}
entity.setId(id);
return entity;
}
/**
* Generate the OVF Environment for a given VirtualSystem not contained in any given
* VirtualSystemCollection (actually, this is a wrapper for another and more complete
* version of this method).
*
* @param vs the VirtualSystem which Environment is to be generated
* @param instanceNumber used to fill @ macros
* @param domain used to fill @ macros
* @param serviceId used to fill @ macros
* @param monitoringChannel used to fill @ macros
* @param ips used to fill @ macros
* @param netmasks used to fill @ macros
* @param dnsServers used to fill @ macros
* @param gateways used to fill @ macros
* @param entryPoints used to fill @ macros
* @param output the OutputStream to read the serialized Environment file
* @param processSiblings
* @return the id used for the VirtualSystem in the Environment file
* @throws IPNotFoundException
* @throws DNSServerNotFoundException
* @throws NetmaskNotFoundException
* @throws GatewayNotFoundException
* @throws PrecedentTierEntryPointNotFoundException
* @throws NotEnoughIPsInPoolException
* @throws PoolNameNotFoundException
*/
public static String createOVFEnvironment(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,
OutputStream output,
boolean processSiblings)
throws IPNotFoundException,
DNSServerNotFoundException,
NetmaskNotFoundException,
GatewayNotFoundException,
PrecedentTierEntryPointNotFoundException,
NotEnoughIPsInPoolException,
PoolNameNotFoundException {
return createOVFEnvironment(null,
vs,
instanceNumber,
domain,
serviceId,
veeId,
monitoringChannel,
ips,
netmasks,
dnsServers,
gateways,
entryPoints,
output,
processSiblings);
}
/**
*
* Generate the OVF Environment for a given VirtualSystem, contanied in a given
* VirtualSystemCollection
*
* @param parentVsc the VirtualSystemContainer holder for the VirtualSystem. If null,
* it is assumed there is no container VirtualSystemContainer, typically the case of
* a mono-VM OVF in which the Envelope contains directly the VirtualSystem
* @param vs the VirtualSystem which Environment is to be generated
* @param instanceNumber used to fill @ macros
* @param domain used to fill @ macros
* @param serviceId used to fill @ macros
* @param monitoringChannel used to fill @ macros
* @param ips used to fill @ macros
* @param netmasks used to fill @ macros
* @param dnsServers used to fill @ macros
* @param gateways used to fill @ macros
* @param entryPoints used to fill @ macros
* @param output the OutputStream to read the serialized Environment file
* @param processSiblings
* @return the id used for the VirtualSystem in the Environment file
* @throws IPNotFoundException
* @throws DNSServerNotFoundException
* @throws NetmaskNotFoundException
* @throws GatewayNotFoundException
* @throws PrecedentTierEntryPointNotFoundException
* @throws NotEnoughIPsInPoolException
* @throws PoolNameNotFoundException
*/
public static String createOVFEnvironment(VirtualSystemCollectionType parentVsc,
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,
OutputStream output,
boolean processSiblings)
throws IPNotFoundException,
DNSServerNotFoundException,
NetmaskNotFoundException,
GatewayNotFoundException,
PrecedentTierEntryPointNotFoundException,
NotEnoughIPsInPoolException,
PoolNameNotFoundException {
String idEnvironment = "";
try {
idEnvironment = vs.getId();
EnvironmentType env = OVFEnvironmentUtils.createEnvironment(idEnvironment);
/* PropertySection for the VirtualSystem itself */
List<ProductSectionType> listProductSection = new LinkedList<ProductSectionType>();
listProductSection.addAll(OVFEnvelopeUtils.getProductSections(vs));
if (parentVsc != null) {
listProductSection.addAll(OVFEnvelopeUtils.getProductSections(parentVsc));
}
PropertySectionType propertySection = processListForEnvironment(
listProductSection, instanceNumber, domain, serviceId, veeId,
monitoringChannel, ips, netmasks, dnsServers, gateways, entryPoints);
OVFEnvironmentUtils.setSectionToEnvironment(env, propertySection);
if (processSiblings && parentVsc != null) {
/* PropertySection for sibling VirtualSystem, within Entities */
Set<ContentType> childs = OVFEnvelopeUtils.getVirtualSystemsFromCollection(parentVsc);
// FIXME: VirtualSystemCollections children are ignored by the moment, it is not clear
// what to do with them accordingly to DSP0243 v1.0.0 and this is a case that never
// happens in RESERVOIR
for (Iterator<ContentType> iterator = childs.iterator(); iterator.hasNext();) {
ContentType vsSb = (ContentType) iterator.next();
/* Only siblings have to be processed. Note that we don't pass the ips array in this
* case due to the @IP(net) macro is only interpretable when applied to the VS itself,
* but not to sibling <Entity>s */
if (!(vsSb.getId().equals(idEnvironment))) {
listProductSection = new LinkedList<ProductSectionType>();
listProductSection.addAll(OVFEnvelopeUtils.getProductSections(vsSb));
propertySection = processListForEnvironment(
listProductSection, instanceNumber, domain, serviceId,veeId,
monitoringChannel, null, netmasks, dnsServers, gateways, null);
EntityType ent = OVFEnvironmentUtils.createEntity(vsSb.getId());
OVFEnvironmentUtils.setPropertySectionToEntity(ent, propertySection);
OVFEnvironmentUtils.addEntity(env, ent);
}
}
}
OVFEnvironmentSerializer.getInstance().writeXML(env, output);
} catch (SectionAlreadyPresentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XMLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RequiredAttributeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return idEnvironment;
}
public static List<EnvironmentMetaData> createOVFEnvironments(VirtualSystemCollectionType parentVsc,
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,
boolean processSiblings){
List<EnvironmentMetaData> listOutPutStreamEnvironment = new ArrayList<EnvironmentMetaData>();
//List<OutputStream> listOutPutStreamEnvironment = new ArrayList<OutputStream>();
Set<ContentType> setVS_VSC = OVFEnvelopeUtils.getVirtualSystemsFromCollection(parentVsc);
for (Iterator iterator = setVS_VSC.iterator(); iterator.hasNext();) {
ContentType contentType = (ContentType) iterator.next();
if(contentType instanceof VirtualSystemCollectionType){
//List<OutputStream> subListOutputStreamEnvironment = createOVFEnvironments((VirtualSystemCollectionType)contentType, instanceNumber, domain, serviceId, monitoringChannel, ips, netmasks, dnsServers, gateways, entryPoints, processSiblings);
List<EnvironmentMetaData> subListOutputStreamEnvironment = createOVFEnvironments((VirtualSystemCollectionType)contentType, instanceNumber,
domain, serviceId, veeId, monitoringChannel, ips, netmasks, dnsServers, gateways, entryPoints, processSiblings);
listOutPutStreamEnvironment.addAll(subListOutputStreamEnvironment);
}else if(contentType instanceof VirtualSystemType){
try {
OutputStream ou = new ByteArrayOutputStream();
String idEnvironment = createOVFEnvironment(parentVsc, (VirtualSystemType)contentType, instanceNumber, domain, serviceId,veeId, monitoringChannel, ips, netmasks, dnsServers, gateways, entryPoints, ou, processSiblings);
EnvironmentMetaData idEnvironmentAndOutputStreamEnvironment = new EnvironmentMetaData(idEnvironment,ou);
listOutPutStreamEnvironment.add(idEnvironmentAndOutputStreamEnvironment);
} catch (IPNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DNSServerNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NetmaskNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (GatewayNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (PrecedentTierEntryPointNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotEnoughIPsInPoolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (PoolNameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return listOutPutStreamEnvironment;
}
public static PropertySectionType processListForEnvironment(List<ProductSectionType> listProductSection,
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 IPNotFoundException,
DNSServerNotFoundException,
NetmaskNotFoundException,
GatewayNotFoundException,
PrecedentTierEntryPointNotFoundException,
NotEnoughIPsInPoolException,
PoolNameNotFoundException {
/* 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>>();
PropertySectionType propertySection = OVFPropertyUtils.createPropertySection();
try {
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();
// Calculate the actual key string (concatenating ProducSection class and instance)
String effectiveKey = property.getKey();
if (!prodSection.getClazz().isEmpty()) {
effectiveKey = prodSection.getClazz() + "." + effectiveKey;
}
if (!prodSection.getInstance().isEmpty()) {
effectiveKey = effectiveKey + "." + prodSection.getInstance();
}
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);
}
else {
effectiveValue = property.getValue();
}
OVFPropertyUtils.addProperty(propertySection,effectiveKey,effectiveValue);
}
}
} catch (RequiredAttributeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IdAlreadyExistsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return propertySection;
}
}