/* (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.slm.deployment; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.persistence.Basic; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; 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.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.telefonica.claudia.slm.common.PersistentObject; import com.telefonica.claudia.slm.deployment.HWComponent.HWType; import com.telefonica.claudia.slm.deployment.Network.NetworkModeType; import com.telefonica.claudia.slm.deployment.Zone.ZoneType; import com.telefonica.claudia.slm.monitoring.MeasurableElement; import com.telefonica.claudia.slm.naming.DirectoryEntry; import com.telefonica.claudia.slm.naming.FQN; import com.telefonica.claudia.slm.naming.ReservoirDirectory; import com.telefonica.claudia.smi.DataTypesUtils; @Entity public class VDC extends DirectoryEntry implements PersistentObject, MeasurableElement { private static final double DEFAULT_MEMORY_ALLOCATION = -1; private static final String DEFAULT_CPU_UNITS = "# CPUs"; private static final double DEFAULT_CPU_ALLOCATION = -1; private static final double DEFAULT_DISK_ALLOCATION = -1; private static Logger logger = Logger.getLogger("VDC"); @Id @GeneratedValue public long internalId; private long tcloudId; @Basic private String vdcName = null; private String description = null; //@OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @Transient private FQN vdcFQN = null; @OneToMany(mappedBy="vdc", cascade=CascadeType.ALL) private Set<ServiceApplication> services = new HashSet<ServiceApplication>(); @OneToMany(mappedBy="vdc", cascade=CascadeType.ALL, fetch=FetchType.EAGER) private Set<Zone> zones = new HashSet<Zone>(); @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER) private Capacity cpuCapacity; @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER) private Capacity diskCapacity; @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER) private Capacity memoryCapacity; public VDC() { } public VDC(String vdcName) { if(vdcName == null) throw new IllegalArgumentException("VDC name cannot be null"); this.vdcName = vdcName; } @SuppressWarnings("unchecked") public static VDC createVDC(String instantiateOVFParams, String org) throws IOException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); VDC resultVDC = new VDC(); try { DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new ByteArrayInputStream(instantiateOVFParams.getBytes())); Element root= (Element) doc.getFirstChild(); resultVDC.tcloudId = Integer.parseInt(root.getAttribute("Id")); resultVDC.vdcName = root.getAttribute("name"); NodeList descriptionList = root.getElementsByTagName("Description"); if (descriptionList.getLength() > 0) { resultVDC.description = ((Element)descriptionList.item(0)).getTextContent(); } NodeList topologyList = root.getElementsByTagName("Topology"); if (topologyList.getLength()>0) { Element topology = (Element) topologyList.item(0); NodeList listZones= topology.getElementsByTagName("Zone"); for (int i=0; i < listZones.getLength(); i++) { Element zone = (Element) listZones.item(i); Zone tmpZone = new Zone(); tmpZone.setVdc(resultVDC); resultVDC.registerZone(tmpZone); tmpZone.setZoneType(ZoneType.valueOf(zone.getAttribute("type").replace('-', '_').toUpperCase())); NodeList netList = zone.getElementsByTagName("VirtualNetwork"); for (int j=0; j < netList.getLength(); j++) { Element network = (Element) netList.item(j); String name = network.getAttribute("name"); Network tmpNet = new Network(name, tmpZone); NodeList modeList = network.getElementsByTagName("Mode"); if (modeList.getLength() > 0) { Element mode = (Element) modeList.item(0); tmpNet.setNetworkMode(NetworkModeType.valueOf(mode.getTextContent().trim().toUpperCase())); } switch(tmpNet.getNetworkMode()) { case ISOLATED: tmpNet.setNetworkMode(NetworkModeType.ISOLATED); break; default: tmpNet.setNetworkMode(NetworkModeType.ROUTED); } tmpNet.setTcloudId(Integer.parseInt(network.getAttribute("id"))); NodeList sizeList = network.getElementsByTagName("Size"); if (sizeList.getLength() > 0) { Element size = (Element) sizeList.item(0); tmpNet.setSize(Integer.parseInt(size.getTextContent().trim())); } descriptionList = network.getElementsByTagName("Description"); if (descriptionList.getLength() > 0) { Element description = (Element) descriptionList.item(0); tmpNet.setDescription(description.getTextContent().trim()); } NodeList bandwidthList = network.getElementsByTagName("Bandwidth"); if (bandwidthList.getLength() > 0) { Element bandwidth = (Element) bandwidthList.item(0); tmpNet.setBandwidth(Long.parseLong(bandwidth.getTextContent().trim())); if (bandwidth.hasAttribute("units")) tmpNet.setBandwidthUnits(bandwidth.getAttribute("units")); } tmpZone.registerNetwork(tmpNet); } } } else { throw new IllegalArgumentException("Topology element is mandatory"); } NodeList computeCapacityList = root.getElementsByTagName("ComputeCapacity"); if (computeCapacityList.getLength()>0) { Element computeCapacity = (Element) computeCapacityList.item(0); NodeList listCpus= computeCapacity.getElementsByTagName("Cpu"); String cpuUnits; double cpuValue; if (listCpus.getLength()>0) { Element cpu = (Element) listCpus.item(0); Element allocated = (Element) cpu.getElementsByTagName("Limit").item(0); Element units = (Element) cpu.getElementsByTagName("Units").item(0); cpuUnits = units.getTextContent(); try { cpuValue = Double.parseDouble(allocated.getTextContent()); } catch (Throwable t) { throw new IllegalArgumentException("Error parsing cpu capacity: " + allocated.getTextContent()); } } else { cpuUnits = DEFAULT_CPU_UNITS; cpuValue = DEFAULT_CPU_ALLOCATION; } Capacity ct = new Capacity(); ct.setAllocated(cpuValue); ct.setUsed(0.0); ct.setUnits(cpuUnits); ct.setType(HWType.CPU); resultVDC.cpuCapacity = ct; NodeList listMemory= computeCapacity.getElementsByTagName("Memory"); double memValue; if (listMemory.getLength()>0) { Element memory = (Element) listMemory.item(0); Element allocated = (Element) memory.getElementsByTagName("Limit").item(0); Element units = (Element) memory.getElementsByTagName("Units").item(0); try { memValue= Double.parseDouble(allocated.getTextContent())*DataTypesUtils.getStorageUnitConversion(units.getTextContent()); } catch (Throwable t) { throw new IllegalArgumentException("Error parsing memory capacity: " + allocated.getTextContent()); } } else { memValue= DEFAULT_MEMORY_ALLOCATION; } ct = new Capacity(); ct.setUnits(DataTypesUtils.STANDARD_STORAGE_UNIT_DEFAULT); ct.setAllocated(memValue); ct.setUsed(0.0); ct.setType(HWType.MEMORY); resultVDC.memoryCapacity = ct; } else { Capacity ct = new Capacity(); ct.setAllocated(DEFAULT_CPU_ALLOCATION); ct.setUsed(0.0); ct.setUnits(DEFAULT_CPU_UNITS); ct.setType(HWType.CPU); resultVDC.cpuCapacity = ct; ct = new Capacity(); ct.setAllocated(DEFAULT_MEMORY_ALLOCATION); ct.setUsed(0.0); ct.setUnits(DataTypesUtils.STANDARD_STORAGE_UNIT_DEFAULT); ct.setType(HWType.MEMORY); resultVDC.memoryCapacity = ct; } NodeList storageCapacityList = root.getElementsByTagName("StorageCapacity"); if (storageCapacityList.getLength()>0) { Element storageCapacity = (Element) storageCapacityList.item(0); NodeList listDisks= storageCapacity.getElementsByTagName("Disk"); Element disk = (Element) listDisks.item(0); Element allocated = (Element) disk.getElementsByTagName("Limit").item(0); Element units = (Element) disk.getElementsByTagName("Units").item(0); Capacity ct = new Capacity(); ct.setUnits(DataTypesUtils.STANDARD_STORAGE_UNIT_DEFAULT); try { ct.setAllocated(Double.parseDouble(allocated.getTextContent())*DataTypesUtils.getStorageUnitConversion(units.getTextContent())); } catch (Throwable t) { throw new IllegalArgumentException("Error parsing storage capacity: " + allocated.getTextContent()); } ct.setUsed(0.0); ct.setType(HWType.DISK); resultVDC.diskCapacity=ct; } else { Capacity ct = new Capacity(); ct.setAllocated(DEFAULT_DISK_ALLOCATION); ct.setUsed(0.0); ct.setUnits(DataTypesUtils.STANDARD_STORAGE_UNIT_DEFAULT); ct.setType(HWType.DISK); resultVDC.diskCapacity=ct; } if (ReservoirDirectory.getInstance().isNameRegistered(resultVDC.getFQN())) { throw new IllegalArgumentException("The VDC already exists"); } else { ReservoirDirectory.getInstance().registerObject(resultVDC.getFQN(), resultVDC); logger.info("New VDC: " + resultVDC.toString() + ", registering in directory"); } return resultVDC; } catch (ParserConfigurationException e) { logger.error("Parser Configuration Error: " + e.getMessage()); throw new IOException ("Parser Configuration Error", e); } catch (SAXException e) { logger.error("Parse error reading the answer: " + e.getMessage()); throw new IOException ("XML Parse error", e); } } public String getVdcName(){ return vdcName; } public Set<ServiceApplication> getServices() { return services; } public void registerService(ServiceApplication service) { if(service == null) throw new IllegalArgumentException("Cannot register null service"); if(!service.getVdc().equals(this)) throw new IllegalArgumentException("Trying to register Service " + service + " on a different customer " + this); services.add(service); } public boolean isServiceRegistered(ServiceApplication service) { return services.contains(service); } public void unregisterService(ServiceApplication service) { services.remove(service); } public FQN getFQN(){ if(vdcFQN == null) vdcFQN = ReservoirDirectory.getInstance().buildFQN(this); return vdcFQN; } @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 VDC)) return false; return ((VDC)object).internalId == internalId; } public Set<Object> getDescendants() { Set<Object> result = new HashSet<Object>(); result.add(this); return result; } public void registerZone(Zone zone) { if(zone == null) throw new IllegalArgumentException("Cannot register null network"); if(!zone.getVdc().equals(this)) throw new IllegalArgumentException("Trying to register network " + zone + " on a different Service " + this); zones.add(zone); } public boolean isZoneRegistered(Zone zone) { return zones.contains(zone); } public void unregisterZone(Zone zone) { zones.remove(zone); } /** * @param netName * @return the Network class correspondig to that name, null if no Netwokr can be found */ public Network getNetworkByName(String netName) { for (Iterator<Zone> itz= zones.iterator(); itz.hasNext(); ) { Zone z= itz.next(); for (Iterator<Network> it = z.getNetworks().iterator(); it.hasNext(); ) { Network net = it.next(); if (net.getName().equals(netName)) { return net; } } } return null; } public Set<Zone> getZones() { return zones; } public void setDescription(String description) { this.description = description; } public String getDescription() { return description; } public void setTcloudId(long tcloudId) { this.tcloudId = tcloudId; } public long getTcloudId() { return tcloudId; } public Capacity getCpuCapacity() { return cpuCapacity; } public void setCpuCapacity(double capacity) { cpuCapacity.setAllocated(capacity); } public Capacity getDiskCapacity() { return diskCapacity; } public void setDiskCapacity(double capacity) { diskCapacity.setAllocated(capacity); } public Capacity getMemoryCapacity() { return memoryCapacity; } public void setMemoryCapacity(double capacity) { memoryCapacity.setAllocated(capacity); } public long getObjectId() { return internalId; } }