/*
(c) Copyright 2011 Telefonica, I+D. Printed in Spain (Europe). All Rights
Reserved.
The copyright to the software program(s) is property of Telefonica I+D.
The program(s) may be used and or copied only with the express written
consent of Telefonica I+D or in accordance with the terms and conditions
stipulated in the agreement/contract under which the program(s) have
been supplied.
*/
package com.telefonica.claudia.smi.context.impl;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import javax.xml.bind.JAXBException;
import org.apache.log4j.Logger;
import org.dmtf.schemas.ovf.envelope._1.ContentType;
import org.dmtf.schemas.ovf.envelope._1.Envelope;
import org.dmtf.schemas.ovf.envelope._1.VirtualSystemType;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.abiquo.ovf.OVFEnvelopeUtils;
import com.abiquo.ovf.OVFEnvironmentUtils;
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.NetmaskNotFoundException;
import com.abiquo.ovf.exceptions.NotEnoughIPsInPoolException;
import com.abiquo.ovf.exceptions.PoolNameNotFoundException;
import com.abiquo.ovf.exceptions.PrecedentTierEntryPointNotFoundException;
import com.abiquo.ovf.exceptions.XMLException;
import com.abiquo.ovf.xml.OVFSerializer;
import com.telefonica.claudia.clotho.utils.PropertyManager;
import com.telefonica.claudia.smi.DataTypesUtils;
import com.telefonica.claudia.smi.TCloudConstants;
import com.telefonica.claudia.smi.URICreation;
import com.telefonica.claudia.smi.context.Environment;
import com.telefonica.claudia.smi.context.EnvironmentCreator;
import com.telefonica.claudia.smi.exception.EnvironmentCreationException;
import com.telefonica.claudia.smi.exception.ParserException;
import com.telefonica.claudia.smi.utils.OneProperties;
import com.telefonica.claudia.smi.utils.XMLUtils;
/**
* Creates the virtual machine environment using OVF information
*
* @author luismarcos.ayllon
*
*/
public class EnvironmentCreatorImpl implements EnvironmentCreator {
private static Logger log = Logger.getLogger(EnvironmentCreatorImpl.class);
/**
* {@inheritDoc}
*/
@Override
public Environment create(String ovf) throws EnvironmentCreationException {
EnvironmentImpl env = new EnvironmentImpl();
Document doc = null;
try {
doc = XMLUtils.parse(ovf, true);
} catch (ParserException e) {
throw new EnvironmentCreationException (e);
}
if (!doc.getFirstChild().getNodeName().equals(TCloudConstants.TAG_INSTANTIATE_OVF)) {
log.error("Element <"+TCloudConstants.TAG_INSTANTIATE_OVF+"> not found.");
throw new EnvironmentCreationException ("Element <"+TCloudConstants.TAG_INSTANTIATE_OVF+"> not found.");
}
/* Gets the replica's FQN */
Element root = (Element) doc.getFirstChild();
String name = root.getAttribute("name");
env.setVmFqn(name);
Envelope envelope = null;
ContentType entityInstance = null;
/* Replaces the environment macros in the OVF */
try {
envelope = getEnvelope(doc);
entityInstance = OVFEnvelopeUtils.getTopLevelVirtualSystemContent(envelope);
if (entityInstance instanceof VirtualSystemType) {
envelope = replaceEnvironmentMacros(envelope,
Integer.parseInt(URICreation.getReplica(name)),
URICreation.getOrg(name),
URICreation.getService(name),
PropertyManager.getInstance().getProperty(OneProperties.MONITORING_CHANNEL),
null,
null,
null,
null,
null);
}
} catch (IllegalArgumentException iae) {
log.error("Some data could not be calculated for the OVF environment: " + iae.getMessage());
throw new EnvironmentCreationException(iae);
} catch (EmptyEnvelopeException e) {
log.error("Empty envelope found: " + e);
throw new EnvironmentCreationException("Empty envelope found: " + e.getMessage());
}
/* Creates the environment content */
try {
entityInstance = OVFEnvelopeUtils.getTopLevelVirtualSystemContent(envelope);
VirtualSystemType vs = (VirtualSystemType) entityInstance;
ByteArrayOutputStream output = new ByteArrayOutputStream();
OVFEnvironmentUtils.createOVFEnvironment(vs,
0,
"",
"",
"",
null,
null,
null,
null,
null,
output,
true);
log.debug("OVF Environment file for VM [" + output.toString()+ "]");
env.setContent(output.toString());
return env;
} catch (EmptyEnvelopeException e) {
log.error("Environment could not be created. Empty envelope found: " + e);
throw new IllegalArgumentException("Empty envelope found: " + e.getMessage());
} catch (IPNotFoundException e) {
log.error("Environment could not be created. No IP found: " + e);
throw new IllegalArgumentException("No IP found: " + e.getMessage());
} catch (DNSServerNotFoundException e) {
log.error("Environment could not be created. No DNS found: " + e);
throw new IllegalArgumentException("No DNS found: " + e.getMessage());
} catch (NetmaskNotFoundException e) {
log.error("Environment could not be created. No Netmask found: " + e);
throw new IllegalArgumentException("No Netmask found: " + e.getMessage());
} catch (GatewayNotFoundException e) {
log.error("Environment could not be created. No Gateway found: " + e);
throw new IllegalArgumentException("No Gateway found: " + e.getMessage());
} catch (PrecedentTierEntryPointNotFoundException e) {
log.error("Environment could not be created. No Precedent Tier found: " + e);
throw new IllegalArgumentException("No Precedent Tier found: " + e.getMessage());
} catch (NotEnoughIPsInPoolException e) {
log.error("Environment could not be created. Not enough IPs found: " + e);
throw new IllegalArgumentException("Not enough IPs found: " + e.getMessage());
} catch (PoolNameNotFoundException e) {
log.error("Environment could not be created. No Pool Name found: " + e);
throw new IllegalArgumentException("Pool Name not found: " + e.getMessage());
}
}
/**
* {@inheritDoc}
*/
@Override
public Environment create(String fqn, String text) throws EnvironmentCreationException {
EnvironmentImpl env = new EnvironmentImpl();
env.setVmFqn(fqn);
env.setContent(text);
return env;
}
/**
* Performs a macro replacement in the ProductSections of the Envelope passed as argument
* in the context of the VirtualSystem.
*
* @param ovf
* @param instanceNumber
* @param domain
* @param serviceId
* @param monitoringChannel
* @param ips
* @param netmasks
* @param dnsServers
* @param gateways
* @param entryPoints
* @return
* the envelope element with all macros replaced.
* @throws EnvironmentCreationException
*/
private Envelope replaceEnvironmentMacros (Envelope envelope,
int instanceNumber,
String domain,
String serviceId,
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 EnvironmentCreationException {
try {
ContentType entityInstance = OVFEnvelopeUtils.getTopLevelVirtualSystemContent(envelope);
if (entityInstance instanceof VirtualSystemType) {
OVFEnvelopeUtils.inEnvolopeMacroReplacement(envelope,
(VirtualSystemType) entityInstance,
instanceNumber,
domain,
serviceId,
monitoringChannel,
ips,
netmasks,
dnsServers,
gateways,
entryPoints);
return envelope;
} else {
throw new IllegalArgumentException("Virtual System not found.");
}
} catch (EmptyEnvelopeException e) {
log.error("Macros could not be replaced. Empty envelope found: " + e.getMessage());
throw new IllegalArgumentException("Empty envelope found: " + e.getMessage());
} catch (IPNotFoundException e) {
log.error("Macros with IPs not supported:" + e.getMessage());
throw new IllegalArgumentException("No IP found: " + e.getMessage());
} catch (DNSServerNotFoundException e) {
log.error("Macros with IPs not supported:" + e.getMessage());
throw new IllegalArgumentException("No DNS found: " + e.getMessage());
} catch (NetmaskNotFoundException e) {
log.error("Macros with IPs not supported:" + e.getMessage());
throw new IllegalArgumentException("No Netmask found: " + e.getMessage());
} catch (GatewayNotFoundException e) {
log.error("Macros with IPs not supported:" + e.getMessage());
throw new IllegalArgumentException("No Gateway found: " + e.getMessage());
} catch (PrecedentTierEntryPointNotFoundException e) {
throw new IllegalArgumentException("No Precedent Tier found: " + e.getMessage());
} catch (NotEnoughIPsInPoolException e) {
log.error("Macros with IPs not supported");
throw new IllegalArgumentException("Not enough IPs found: " + e.getMessage());
} catch (PoolNameNotFoundException e) {
throw new IllegalArgumentException("Pool Name not found: " + e.getMessage());
}
}
/**
* Extracts the envelope element from the given document
*
* @param doc
* @return
* @throws EnvironmentCreationException
*/
private Envelope getEnvelope (Document doc) throws EnvironmentCreationException{
NodeList envelopeItems = doc.getElementsByTagNameNS("*", TCloudConstants.TAG_ENVELOPE);
if (envelopeItems.getLength() != 1) {
log.error("Envelope items not found.");
throw new EnvironmentCreationException ("Envelope items not found.");
}
Envelope envelope = null;
try {
Document ovfDoc = XMLUtils.createDocument(true);
ovfDoc.appendChild(ovfDoc.importNode(envelopeItems.item(0), true));
OVFSerializer ovfSerializer = OVFSerializer.getInstance();
ovfSerializer.setValidateXML(false);
envelope = ovfSerializer.readXMLEnvelope(new ByteArrayInputStream(DataTypesUtils.serializeXML(ovfDoc).getBytes()));
return envelope;
} catch (JAXBException e) {
log.error("Envelope can not be extracted");
throw new EnvironmentCreationException (e);
} catch (XMLException e) {
log.error("Envelope can not be extracted");
throw new EnvironmentCreationException (e);
} catch (ParserException e) {
log.error("Envelope can not be extracted");
throw new EnvironmentCreationException (e);
}
}
}