/*
* Claudia Project
* http://claudia.morfeo-project.org
*
* (C) Copyright 2010 Telefonica Investigacion y Desarrollo
* S.A.Unipersonal (Telefonica I+D)
*
* See CREDITS file for info about members and contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the Affero GNU General Public License (AGPL) as
* published by the Free Software Foundation; either version 3 of the License,
* or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the Affero GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* If you want to use this software an plan to distribute a
* proprietary application in any way, and you are not licensing and
* distributing your source code under AGPL, you probably need to
* purchase a commercial license of the product. Please contact
* claudia-support@lists.morfeo-project.org for more information.
*/
package com.telefonica.claudia.slm.deployment;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.hibernate.annotations.CollectionOfElements;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.telefonica.claudia.slm.common.SMConfiguration;
import com.telefonica.claudia.slm.deployment.hwItems.CPUConf;
import com.telefonica.claudia.slm.deployment.hwItems.DiskConf;
import com.telefonica.claudia.slm.deployment.hwItems.MemoryConf;
import com.telefonica.claudia.slm.deployment.hwItems.NICConf;
import com.telefonica.claudia.slm.deployment.paas.Product;
import com.telefonica.claudia.slm.deployment.paas.Property;
import com.telefonica.claudia.slm.maniParser.GetOperationsUtils;
import com.telefonica.claudia.slm.naming.DirectoryEntry;
import com.telefonica.claudia.slm.naming.FQN;
import com.telefonica.claudia.slm.naming.ReservoirDirectory;
@Entity
@SuppressWarnings("unchecked")
public class VEE implements Comparable, DirectoryEntry {
public static enum VirtualizationTechnologyType {XEN, VMWARE, KVM};
@Id
@GeneratedValue
public long internalId;
private String veeName = null;
@ManyToOne
private ServiceApplication serviceApplication = null;
@OneToOne(cascade={CascadeType.REFRESH, CascadeType.MERGE, CascadeType.PERSIST})
private FQN veeFQN = null;
@Enumerated(EnumType.STRING)
private VirtualizationTechnologyType virtType = null;
@OneToMany(cascade=CascadeType.ALL)
private List<DiskConf> disksConf = new ArrayList<DiskConf>();
@OneToMany(cascade=CascadeType.ALL)
private List<Product> products = new ArrayList<Product>();
@OneToMany(cascade=CascadeType.ALL)
private List<CPUConf> cpusConf = new ArrayList<CPUConf>();
@OneToMany(cascade=CascadeType.ALL)
private List<NICConf> nicsConf = new ArrayList<NICConf>();
@OneToOne(cascade=CascadeType.ALL)
private MemoryConf memoryConf = null;
@OneToOne(cascade = CascadeType.ALL)
private VEE balancedBy = null;
private int lastReplicaId = 0;
private int maxReplicas = 1;
private int minReplicas = 1;
private int initReplicas = minReplicas;
private int currentReplicas= 0;
private boolean hotMigrationAllowed = true;
private boolean coldMigrationAllowed = true;
private int deploymentOrder = -1;
private int lbManagementPort = 0;
private boolean isBalancer = false;
@OneToMany(cascade=CascadeType.ALL)
@JoinTable(name="ALLOWED_DOMAINS")
private Set<GeographicDomain> allowedDomains = new HashSet<GeographicDomain>();
@OneToMany(cascade=CascadeType.ALL)
@JoinTable(name="FORBIDDEN_DOMAINS")
private Set<GeographicDomain> forbiddenDomains = new HashSet<GeographicDomain>();
@OneToMany(cascade=CascadeType.ALL)
private Set<ISOImage> isoImages = new HashSet<ISOImage>();
@OneToMany(mappedBy="vee", cascade=CascadeType.ALL)
private Set<VEEReplica> activeReplicas = new HashSet<VEEReplica>();
@Transient
private AvailabilityWindow availabilityWindow;
// RESERVOIR attributes
private String UUID=null;
private boolean migratable;
private double availabilityValue;
@CollectionOfElements
private List<String> recipes = new ArrayList ();
/**
* OVF document that describe the VEE template that will be used to generate virtual machine templates.
* The OVF document contains a collection of identifiers that will be replaced with current values when
* the VEE is being instantiated.
*/
@Column(columnDefinition = "VARCHAR(32672)")
private String ovfRepresentation=null;
@Column(columnDefinition = "VARCHAR(32672)")
private String password=null;
@Column(columnDefinition = "VARCHAR(32672)")
private String username=null;
public VEE() {}
public String getUUID() {
return UUID;
}
public void setUUID(String uuid) {
this.UUID = uuid;
}
public boolean getMigratable() {
return migratable;
}
public void setMigratable(boolean migrat) {
this.migratable = migrat;
}
public double getAvailabilityValue() {
return availabilityValue;
}
public void setAvailabilityValue(double availabilityValue) {
this.availabilityValue = availabilityValue;
}
public static class AvailabilityWindow {
public String unit;
public long value;
}
public VEE(String veeName, ServiceApplication serviceApplication) {
if(veeName == null)
throw new IllegalArgumentException("VEE name cannot be null");
if(serviceApplication == null)
throw new IllegalArgumentException("Service application name cannot be null");
this.veeName = veeName;
this.serviceApplication = serviceApplication;
}
public void addDiskConf(DiskConf diskConf) {
System.out.println(" +++++ DiskConf " + diskConf.getImageURL() + " added to VEE " + getFQN().toString() + " configuration");
disksConf.add(diskConf);
}
public List<DiskConf> getDisksConf() {
return disksConf;
}
public void addProduct(Product product) {
System.out.println(" +++++ Product " + product.getName());
products.add(product);
}
@OneToMany
public List<Product> getProducts() {
return products;
}
public Product getProductByName(String productin) {
for (Iterator<Product> it = products.iterator(); it.hasNext(); ) {
Product product = it.next();
if (product.getName().equals(productin)) {
return product;
}
}
return null;
}
public void removeDiskConf(DiskConf diskConf){
if (disksConf.remove(diskConf))
System.out.println(" +++++ DiskConf " + diskConf.getImageURL() + " removed from VEE " + getFQN().toString() + " configuration");
System.out.println(" +++++ There are " + disksConf.size() + " disk configurations left in VEE");
for(DiskConf diskConfT : disksConf)
System.out.println(" +++++ DiskConf " + diskConf.getImageURL() + " has disk configuration " + diskConfT.getImageURL());
}
public void addCPUConf(CPUConf cpuConf) {
cpusConf.add(cpuConf);
}
public List<CPUConf> getCPUsConf() {
return cpusConf;
}
public VEE getBalancedBy() {
return balancedBy;
}
public void setBalancedBy(VEE balancedBy) {
this.balancedBy = balancedBy;
}
public void addNICConf(NICConf nicConf) {
nicsConf.add(nicConf);
}
public List<NICConf> getNICsConf() {
return nicsConf;
}
public void setMemoryConf(MemoryConf memoryConf) {
this.memoryConf = memoryConf;
}
public MemoryConf getMemoryConf() {
return memoryConf;
}
public String getVEEName() {
return veeName;
}
public void setVEEName(String veeName) {
this.veeName = veeName;
}
public int nextVEEReplicaId() {
return ++lastReplicaId;
}
public int VEELastReplicaId() {
return lastReplicaId;
}
public Set<VEEReplica> getVEEReplicas() {
return activeReplicas;
}
public void registerVEEReplica(VEEReplica veeReplica) {
if(veeReplica == null)
throw new IllegalArgumentException("Cannot register null VEE replica");
if(!veeReplica.getVEE().equals(this))
throw new IllegalArgumentException("Trying to register VEE Replica " + veeReplica + " in a different VEE " + this);
activeReplicas.add(veeReplica);
}
public boolean isVEEReplicaRegistered(VEEReplica veeReplica) {
return activeReplicas.contains(veeReplica);
}
public void unregisterVEEReplica(VEEReplica veeReplica) {
activeReplicas.remove(veeReplica);
}
public ServiceApplication getServiceApplication() {
return serviceApplication;
}
public void addIsoImage(ISOImage isoImage){
isoImages.add(isoImage);
}
public Set<ISOImage> getIsoImages() {
return isoImages;
}
public void addAllowedDomain(GeographicDomain domain) {
allowedDomains.add(domain);
}
public Set<GeographicDomain> getAllowedDomains() {
return allowedDomains;
}
public void addForbiddenDomain(GeographicDomain domain) {
forbiddenDomains.add(domain);
}
public Set<GeographicDomain> getForbiddenDomains() {
return forbiddenDomains;
}
public boolean isColdMigrationAllowed() {
return coldMigrationAllowed;
}
public void setColdMigrationAllowed(boolean coldMigrationAllowed) {
this.coldMigrationAllowed = coldMigrationAllowed;
}
public boolean isHotMigrationAllowed() {
return hotMigrationAllowed;
}
public void setHotMigrationAllowed(boolean hotMigrationAllowed) {
this.hotMigrationAllowed = hotMigrationAllowed;
}
public int getCurrentReplicas(){
return currentReplicas;
}
public void addCurrentReplicas(){
currentReplicas++;
}
public void removeCurrentReplicas(){
currentReplicas--;
}
public int getMaxReplicas() {
return maxReplicas;
}
public void setMaxReplicas(int maxReplicas) {
this.maxReplicas = maxReplicas;
}
public int getMinReplicas() {
return minReplicas;
}
public void setMinReplicas(int minReplicas) {
this.minReplicas = minReplicas;
}
public void setInitReplicas(int initReplicas) {
this.initReplicas = initReplicas;
}
public int getInitReplicas() {
return initReplicas;
}
public VirtualizationTechnologyType getVirtType() {
return virtType;
}
public void setVirtType(VirtualizationTechnologyType virtType) {
this.virtType = virtType;
}
public FQN getFQN(){
if(veeFQN == null)
veeFQN = ReservoirDirectory.getInstance().buildFQN(this);
return veeFQN;
}
@Override
public String toString() {
return getFQN().toString();
}
@Override
public int hashCode(){
return getFQN().hashCode();
}
@Override
public boolean equals(Object object) {
if(object == null)
return false;
if(!(object instanceof VEE))
return false;
return ((VEE)object).getFQN().equals(getFQN());
}
public int getDeploymentOrder() {
return deploymentOrder;
}
public void setDeploymentOrder(int deploymentOrder) {
this.deploymentOrder = deploymentOrder;
}
public int compareTo(Object arg0) {
if(arg0 instanceof VEE){ //if the object is-a VEE
VEE temp = (VEE)arg0; //Edit
if(temp.deploymentOrder == deploymentOrder)
return 0;
else if(temp.deploymentOrder < deploymentOrder)
return 1;
else return -1;
}
return 99;
}
public void setAvailabilityWindow(String units, long value) {
this.availabilityWindow = new AvailabilityWindow();
this.availabilityWindow.unit = units;
this.availabilityWindow.value = value;
}
public AvailabilityWindow getAvailabilityWindow() {
return availabilityWindow;
}
public void setOvfRepresentation(String ovfRepresentation) {
this.ovfRepresentation = ovfRepresentation;
}
public String getOvfRepresentation() {
return ovfRepresentation;
}
public Document toXML() {
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
Document doc;
String organizationId = SMConfiguration.getInstance().getSiteRoot().replace(".", "_");
try {
docBuilder = dbfac.newDocumentBuilder();
doc = docBuilder.newDocument();
Element veeElement = doc.createElement("VApp");
doc.appendChild(veeElement);
veeElement.setAttribute("name", getFQN().toString());
veeElement.setAttributeNS("http://schemas.telefonica.com/claudia/ovf", "rsrvr:min", ""+this.getMinReplicas());
veeElement.setAttributeNS("http://schemas.telefonica.com/claudia/ovf", "rsrvr:max", ""+this.getMaxReplicas());
veeElement.setAttributeNS("http://schemas.telefonica.com/claudia/ovf", "rsrvr:initial", ""+this.getInitReplicas());
veeElement.setAttribute("href", "@HOSTNAME/api/org/" + organizationId + "/vdc/" + this.getServiceApplication().getCustomer().getCustomerName() + "/vapp/" + this.getServiceApplication().getSerAppName() + "/" + getVEEName());
Element monitorLink = doc.createElement("Link");
veeElement.appendChild(monitorLink);
monitorLink.setAttribute("rel", "monitor:measures");
monitorLink.setAttribute("type", "application/vnc.telefonica.tcloud. measureDescriptorList+xml");
monitorLink.setAttribute("href", "@HOSTNAME/api/org/" + organizationId + "/vdc/" +
this.getServiceApplication().getCustomer().getCustomerName() + "/vapp/" + this.getServiceApplication().getSerAppName() + "/" + this.getVEEName() + "/monitor");
Element veeChildren = doc.createElement("Children");
veeElement.appendChild(veeChildren);
SortedSet<VEEReplica> orderedVEEReplicas = new TreeSet<VEEReplica>(new VEEReplicasComparator());
orderedVEEReplicas.addAll(getVEEReplicas());
for(VEEReplica veeReplica : orderedVEEReplicas) {
Element veeReplicaElement = doc.createElement("VApp");
veeChildren.appendChild(veeReplicaElement);
veeReplicaElement.setAttribute("name", veeReplica.getFQN().toString());
veeReplicaElement.setAttribute("href", "@HOSTNAME/api/org/" + organizationId + "/vdc/" + this.getServiceApplication().getCustomer().getCustomerName() + "/vapp/" + this.getServiceApplication().getSerAppName() +
"/" + getVEEName() + "/" + veeReplica.getId());
Element linkVeeReplica = doc.createElement("Link");
veeReplicaElement.appendChild(linkVeeReplica);
linkVeeReplica.setAttribute("rel", "monitor:measures");
linkVeeReplica.setAttribute("type", "application/vnc.telefonica.tcloud. measureDescriptorList+xml");
linkVeeReplica.setAttribute("href", "@HOSTNAME/api/org/" + organizationId + "/vdc/" +
this.getServiceApplication().getCustomer().getCustomerName() + "/vapp/" + this.getServiceApplication().getSerAppName() + "/" + getVEEName() + "/" + veeReplica.getId() + "/monitor");
Element virtuahardware = GetOperationsUtils.getVirtualHardwareSystem(doc, "@HOSTNAME/api/org/" + organizationId + "/vdc/" + this.getServiceApplication().getCustomer().getCustomerName() + "/vapp/" + this.getServiceApplication().getSerAppName() +
"/" + getVEEName() + "/" + veeReplica.getId(), veeReplica);
veeReplicaElement.appendChild(virtuahardware);
}
return doc;
} catch (ParserConfigurationException e) {
}
return null;
}
public void setLbManagementPort(int lbManagementPort)
{
this.lbManagementPort = lbManagementPort;
}
public int getLbManagementPort()
{
return this.lbManagementPort;
}
public void setBalancer(boolean isBalancer)
{
this.isBalancer= isBalancer;
}
public boolean getBalancer()
{
return this.isBalancer;
}
public void setUserName(String username)
{
this.username= username;
}
public String getUserName()
{
return this.username;
}
public void setPassword(String password)
{
this.password= password;
}
public String getPassword()
{
return this.password;
}
public List<String> getRecipes (){
return recipes;
}
public void setRecipe(List<String> recipes){
this.recipes = recipes;
}
public void addRecipe(String recipe){
this.recipes.add(recipe);
}
}