/* * Copyright (c) 2013 Technische Universitat Wien (TUW), Distributed Systems Group. http://dsg.tuwien.ac.at * * This work was partially supported by the European Commission in terms of the CELAR FP7 project (FP7-ICT-2011-8 #317790), http://www.celarcloud.eu/ * * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package at.ac.tuwien.dsg.cloud.salsa.engine.services; import generated.JaxbGangliaEntities.GangliaHostInfo; import java.io.File; import java.io.IOException; import java.io.StringReader; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import org.apache.commons.io.FileUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Service; import at.ac.tuwien.dsg.cloud.salsa.common.cloudservice.model.CloudService; import at.ac.tuwien.dsg.cloud.salsa.common.cloudservice.model.ServiceInstance; import at.ac.tuwien.dsg.cloud.salsa.common.cloudservice.model.ServiceTopology; import at.ac.tuwien.dsg.cloud.salsa.common.cloudservice.model.ServiceUnit; import at.ac.tuwien.dsg.cloud.salsa.common.cloudservice.model.enums.SalsaEntityType; import at.ac.tuwien.dsg.cloud.salsa.common.interfaces.ApplicationInfoAPI; import at.ac.tuwien.dsg.cloud.salsa.engine.dataprocessing.SalsaXmlDataProcess; import at.ac.tuwien.dsg.cloud.salsa.engine.impl.base.DynamicPlacementHelper; import at.ac.tuwien.dsg.cloud.salsa.engine.services.jsondata.ServiceJsonDataForceDirect; import at.ac.tuwien.dsg.cloud.salsa.engine.services.jsondata.ServiceJsonDataTree; import at.ac.tuwien.dsg.cloud.salsa.engine.services.jsondata.ServiceJsonDataTreeSimple; import at.ac.tuwien.dsg.cloud.salsa.engine.services.jsondata.ServiceJsonList; import at.ac.tuwien.dsg.cloud.salsa.engine.utils.EngineLogger; import at.ac.tuwien.dsg.cloud.salsa.engine.utils.SalsaConfiguration; import at.ac.tuwien.dsg.cloud.salsa.tosca.extension.SalsaInstanceDescription_VM; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import java.util.ArrayList; import java.util.concurrent.CopyOnWriteArrayList; import java.util.logging.Level; @Service @Path("/viewgenerator") public class ViewGenerator{ static Logger logger; static { logger = Logger.getLogger("SalsaCenterLogger"); } @GET @Path("/cloudservice/json/compact/{serviceId}") @Produces(MediaType.TEXT_PLAIN) public String getServiceRuntimeJsonTreeCompact(@PathParam("serviceId") String serviceDeployId) { if (serviceDeployId.equals("") || serviceDeployId.equals("null")) { return ""; } try { String salsaFile = SalsaConfiguration.getServiceStorageDir() + "/" + serviceDeployId + ".data"; CloudService service = SalsaXmlDataProcess.readSalsaServiceFile(salsaFile); ServiceJsonDataTree datatree = new ServiceJsonDataTree(); datatree.setId(service.getName()); datatree.setNodeType("CLOUD SERVICE"); datatree.setState(service.getState()); List<ServiceTopology> topos = service.getComponentTopologyList(); for (ServiceTopology topo : topos) { ServiceJsonDataTree topoNode = new ServiceJsonDataTree(); topoNode.setAbstract(true); topoNode.setId(topo.getId()); topoNode.setNodeType("TOPOLOGY"); topoNode.addProperty("Number of service units", topo.getComponents().size() + ""); topoNode.setState(topo.getState()); datatree.addChild(topoNode); List<ServiceUnit> components = topo.getComponentsByType(SalsaEntityType.OPERATING_SYSTEM); for (ServiceUnit compo : components) { ServiceJsonDataTree componode = new ServiceJsonDataTree(); componode.loadData(compo, -1, topo); // -1 will not check instance id topoNode.addChild(componode); } } datatree.compactData(); // parent=null for root node datatree.reduceLargeNumberOfInstances(); Gson json = new GsonBuilder().setPrettyPrinting().create(); return json.toJson(datatree); } catch (IOException e) { logger.error("Cannot read service file. " + e); } catch (JAXBException e1) { logger.error("Error when parsing service file." + e1); } return ""; } @GET @Path("/cloudservice/json/full/{serviceId}") @Produces(MediaType.TEXT_PLAIN) public String getServiceRuntimeJsonTree(@PathParam("serviceId") String serviceDeployId, @DefaultValue("0") @QueryParam("health") int health) { if (serviceDeployId.equals("") || serviceDeployId.equals("null")) { return ""; } try { String salsaFile = SalsaConfiguration.getServiceStorageDir() + "/" + serviceDeployId + ".data"; CloudService service = SalsaXmlDataProcess.readSalsaServiceFile(salsaFile); if (health == 1) { enrichWithGangliaInfo(service); } ServiceJsonDataTree datatree = new ServiceJsonDataTree(); datatree.setId(service.getName()); datatree.setNodeType("CLOUD SERVICE"); datatree.setState(service.getState()); List<ServiceTopology> topos = service.getComponentTopologyList(); for (ServiceTopology topo : topos) { List<ServiceUnit> components = service.getAllComponentByType(SalsaEntityType.OPERATING_SYSTEM); for (ServiceUnit compo : components) { ServiceJsonDataTree componode = new ServiceJsonDataTree(); componode.loadData(compo, -1, topo); // -1 will not check instance id datatree.addChild(componode); // logger.debug("add a child node: " + componode.getId()); } } Gson json = new GsonBuilder().setPrettyPrinting().create(); return json.toJson(datatree); } catch (IOException e) { logger.error("Cannot read service file. " + e); } catch (JAXBException e1) { logger.error("Error when parsing service file." + e1); } return ""; } @GET @Path("/cloudservice/xml/{serviceId}") @Produces(MediaType.TEXT_PLAIN) public String getServiceRuntimeXml(@PathParam("serviceId") String serviceDeployId) { if (serviceDeployId.equals("") || serviceDeployId.equals("null")) { return ""; } String fileName = SalsaConfiguration.getServiceStorageDir() + "/" + serviceDeployId + ".data"; try { String xml = FileUtils.readFileToString(new File(fileName)); return xml; } catch (Exception e) { // logger.error("Could not find service: " + serviceDeployId // + ". Data did not be sent. Error: " + e.toString()); return "Error"; } } @GET @Path("/cloudservice/json/list") @Produces(MediaType.TEXT_PLAIN) public String getServiceJsonList() { String pathName = SalsaConfiguration.getServiceStorageDir(); try { ServiceJsonList serviceList = new ServiceJsonList(pathName); Gson json = new GsonBuilder().setPrettyPrinting().create(); return json.toJson(serviceList); } catch (Exception e) { logger.error("Could not list services"); return ""; } } /** * This generate the JSON to view in the appstructure.html, which reuses the MELA visualization * * @param serviceDeployId * @return */ @GET @Path("/cloudservice/json/structure/{serviceId}") @Produces(MediaType.TEXT_PLAIN) public String getServiceJsonStructure(@PathParam("serviceId") String serviceDeployId) { if (serviceDeployId.equals("") || serviceDeployId.equals("null")) { return ""; } try { String salsaFile = SalsaConfiguration.getServiceStorageDir() + "/" + serviceDeployId + ".data"; CloudService service = SalsaXmlDataProcess.readSalsaServiceFile(salsaFile); ServiceJsonDataTreeSimple jsonObject = new ServiceJsonDataTreeSimple(); // add clouservice jsonObject.setName(service.getName()); jsonObject.setType("SERVICE"); // cloud service for (ServiceTopology topo : service.getComponentTopologyList()) { ServiceJsonDataTreeSimple newTopo = createServiceJsonNode(topo.getId(), "SERVICE_TOPOLOGY"); // service topology //newTopo.getChildren().add(createServiceJsonNode("State[" + topo.getState() + "]", "metric")); jsonObject.getChildren().add(newTopo); List<ServiceUnit> allSoftwareUnits = new ArrayList<>(); allSoftwareUnits.addAll(topo.getComponentsByType(SalsaEntityType.SOFTWARE)); allSoftwareUnits.addAll(topo.getComponentsByType(SalsaEntityType.SERVICE)); for (ServiceUnit unit : allSoftwareUnits) { for (ServiceInstance instance : unit.getInstancesList()) { ServiceJsonDataTreeSimple newInstance = createServiceJsonNode(unit.getId() + "-" + instance.getInstanceId(), "SERVICE_INSTANCE"); //newInstance.getChildren().add(createServiceJsonNode("State[" + instance.getState() + "]", "metric")); // get VM host the components ServiceUnit hostedUnit = topo.getComponentById(unit.getHostedId()); ServiceInstance hostedInstance = hostedUnit.getInstanceById(instance.getHostedId_Integer()); // in the case we have more than one software stack while (!hostedUnit.getType().equals(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString())) { hostedUnit = topo.getComponentById(hostedUnit.getHostedId()); hostedInstance = hostedUnit.getInstanceById(hostedInstance.getHostedId_Integer()); ServiceJsonDataTreeSimple hostedInstanceJson = createServiceJsonNode("HostedBy[" + hostedUnit.getId() + "-" + hostedInstance.getInstanceId() + "]", "metric"); if (unit.getType().equals(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString())) { SalsaInstanceDescription_VM vm = (SalsaInstanceDescription_VM) instance.getProperties().getAny(); if (vm != null) { hostedInstanceJson.setName("HostedByVM[" + vm.getPrivateIp() + "]"); } } //newInstance.getChildren().add(hostedInstanceJson); } newTopo.getChildren().add(newInstance); } // in the case that unit have no instance, set it as undeployed if(unit.getInstancesList().isEmpty()){ ServiceJsonDataTreeSimple newSU_undeployed = createServiceJsonNode(unit.getId(), "SERVICE_UNIT"); newTopo.getChildren().add(newSU_undeployed); } } } Gson gson = new GsonBuilder().setPrettyPrinting().create(); return gson.toJson(jsonObject); } catch (IOException e) { logger.error("Cannot read service file. " + e); return "root:{error: " + e + "}"; } catch (JAXBException e1) { logger.error("Error when parsing service file." + e1); return "root:{error: " + e1 + "}"; } } @GET @Path("/cloudservice/json/brief/{serviceId}") @Produces(MediaType.TEXT_PLAIN) public String getServiceBriefInfo(@PathParam("serviceId") String serviceDeployId) { String salsaFile = SalsaConfiguration.getServiceStorageDir() + "/" + serviceDeployId + ".data"; try { // logger.debug("Generating brief info for service"); CloudService service = SalsaXmlDataProcess.readSalsaServiceFile(salsaFile); JsonObject root = new JsonObject(); Date modifiedTime = new Date((new File(salsaFile)).lastModified()); SimpleDateFormat sdf = new SimpleDateFormat("EEE, MMM dd yyyy 'at' HH:mm"); String modTime = sdf.format(modifiedTime); root.addProperty("Service ID: ", service.getId()); root.addProperty("Service Name: ", service.getId()); root.addProperty("Deployment Time:", modTime); root.addProperty("Number of topologies:", service.getComponentTopologyList().size()); root.addProperty("Number of service units: ", service.getAllComponent().size()); root.addProperty("Number of VMs: ", service.getAllReplicaByType(SalsaEntityType.OPERATING_SYSTEM).size()); Gson json = new GsonBuilder().setPrettyPrinting().create(); return json.toJson(root); } catch (IOException e) { logger.error("IOException: Error when reading data file !"); return "Error: Service not found!"; } catch (JAXBException e1) { logger.error("JAXBException: "); return "Intenal error when reading service data!"; } } @GET @Path("/cloudservice/json/forcedirect/{serviceId}") @Produces(MediaType.TEXT_PLAIN) public String getServiceRuntimeForceDirect(@PathParam("serviceId") String serviceDeployId) { if (serviceDeployId.equals("") || serviceDeployId.equals("null")) { return ""; } ServiceJsonDataForceDirect jsonObject = new ServiceJsonDataForceDirect(); try { String salsaFile = SalsaConfiguration.getServiceStorageDir() + "/" + serviceDeployId + ".data"; CloudService service = SalsaXmlDataProcess.readSalsaServiceFile(salsaFile); // add root node //jsonObject.addNode(service.getId(), service.getId(), service.getState().getNodeStateString()); // add all the nodes for (ServiceTopology topo : service.getComponentTopologyList()) { logger.debug("getServiceRuntimeForceDirect - Checking topo size: " + service.getComponentTopologyList().size()); logger.debug("getServiceRuntimeForceDirect - Checking topo ID : " + topo.getId()); // add topo node jsonObject.addNode(topo.getId(), service.getId(),"TOPOLOGY", topo.getState().getNodeStateString()); //jsonObject.addLink(service.getId(), topo.getId(), "abstract"); for (ServiceUnit unit : topo.getComponents()) { logger.debug("getServiceRuntimeForceDirect - Checking unit ID : " + unit.getId()); for (ServiceInstance instance : unit.getInstancesList()) { logger.debug("getServiceRuntimeForceDirect - Checking instance ID : " + instance.getInstanceId()); String fullInstanceId = unit.getId()+"_"+instance.getInstanceId(); jsonObject.addNode(fullInstanceId, topo.getId(), "INSTANCE", instance.getState().getNodeStateString()); // group is topology id //jsonObject.addLink(topo.getId(), fullInstanceId, "abstract"); // if (topo.getComponentById(unit.getHostedId()) != null){ // if (!topo.getComponentById(unit.getHostedId()).getInstancesList().isEmpty()){ // jsonObject.addLink(unit.getHostedId()+"_"+topo.getComponentById(unit.getHostedId()).getInstancesList().get(0).getInstanceId(), fullInstanceId, "HOSTON"); // } // } // for (String connectUnit : unit.getConnecttoId()) { // if (topo.getComponentById(connectUnit)!=null){ // if (!topo.getComponentById(connectUnit).getInstancesList().isEmpty()){ // jsonObject.addLink(fullInstanceId, connectUnit +"_"+ topo.getComponentById(connectUnit).getInstancesList().get(0).getInstanceId(), "CONNECTTO"); // } // } // } } } } // add all the link List<ServiceTopology> topoTmps = new CopyOnWriteArrayList<>(service.getComponentTopologyList()); for (ServiceTopology topo : service.getComponentTopologyList()) { for (ServiceTopology topoTmp: topoTmps){ // get rid of concurent modification of List if (topo.getId().equals(topoTmp.getId())){ topoTmps.remove(topoTmp); for (ServiceTopology connectTopo: topoTmps){ jsonObject.addLink(topoTmp.getId(), connectTopo.getId(), "TOPO_TOPO"); } } } //jsonObject.addLink(service.getId(), topo.getId(), "SERVICE_TOPO"); for (ServiceUnit unit : topo.getComponents()) { for (ServiceInstance instance : unit.getInstancesList()) { String fullInstanceId = unit.getId()+"_"+instance.getInstanceId(); jsonObject.addLink(topo.getId(), fullInstanceId, "TOPOLOGY_INSTANCE"); if (service.getComponentById(unit.getHostedId()) != null){ if (!service.getComponentById(unit.getHostedId()).getInstancesList().isEmpty()){ jsonObject.addLink(unit.getHostedId()+"_"+service.getComponentById(unit.getHostedId()).getInstancesList().get(0).getInstanceId(), fullInstanceId, "HOSTON"); } } for (String connectUnit : unit.getConnecttoId()) { if (service.getComponentById(connectUnit)!=null){ if (!service.getComponentById(connectUnit).getInstancesList().isEmpty()){ jsonObject.addLink(fullInstanceId, connectUnit +"_"+ service.getComponentById(connectUnit).getInstancesList().get(0).getInstanceId(), "CONNECTTO"); } } } } } } // TOPO_TOPO link } catch (JAXBException | IOException e){ logger.error("Error when build force direct graph", e); } Gson gson = new GsonBuilder().setPrettyPrinting().create(); return gson.toJson(jsonObject); } private ServiceJsonDataTreeSimple createServiceJsonNode(String name, String type) { ServiceJsonDataTreeSimple newNode = new ServiceJsonDataTreeSimple(); newNode.setName(name); newNode.setType(type); return newNode; } private void enrichWithGangliaInfo(CloudService service) { for (ServiceTopology topo : service.getComponentTopologyList()) { for (ServiceUnit unit : topo.getComponentsByType(SalsaEntityType.OPERATING_SYSTEM)) { for (ServiceInstance instance : unit.getInstancesList()) { InternalManagement moni = new InternalManagement(); SalsaInstanceDescription_VM vm = (SalsaInstanceDescription_VM) instance.getProperties().getAny(); String gangliaXML = moni.getVMInformation(vm); try { JAXBContext jaxbContext = JAXBContext.newInstance(GangliaHostInfo.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); GangliaHostInfo gangliaObj = (GangliaHostInfo) jaxbUnmarshaller.unmarshal(new StringReader(gangliaXML)); instance.setMonitoring(gangliaObj); } catch (JAXBException e) { EngineLogger.logger.error(e.toString()); } } } } for (ServiceInstance osNode : service.getAllReplicaByType(SalsaEntityType.OPERATING_SYSTEM)) { // get the ganglia info InternalManagement moni = new InternalManagement(); // moni.getMonitorOfInstance(service.getId(), service.get, nodeId, instanceId) // String str = SalsaEngineInternal. // parse the XML to GangliaHostInfo // attach to the osNode // GangliaHostInfo ganglia; // osNode.g } } }