/* * 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.impl.base; 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.ServiceUnit; import at.ac.tuwien.dsg.cloud.salsa.common.cloudservice.model.enums.SalsaEntityType; import at.ac.tuwien.dsg.cloud.salsa.engine.impl.base.GangliaHostInfo.METRIC; import at.ac.tuwien.dsg.cloud.salsa.engine.utils.EngineLogger; import at.ac.tuwien.dsg.cloud.salsa.engine.utils.SystemFunctions; import at.ac.tuwien.dsg.cloud.salsa.tosca.extension.SalsaInstanceDescription_VM; import java.io.StringReader; import java.util.Scanner; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author Duc-Hung LE */ public class DynamicPlacementHelper { static Logger LOGGER = LoggerFactory.getLogger("EngineLogger"); /** * Main method using for higher level app to check the placement condition for a service instance * * @param threadhold * @param service * @param unitID * @param instanceID * @return */ public static boolean checkMemoryUsageIsBelowThreadholdByInstanceID_NoDockerConcern(float threadhold, CloudService service, String unitID, int instanceID) { String ip = getIpOfInstance(service, unitID, instanceID, false); if (ip == null) { return false; } LOGGER.debug("Checking memory usage of instance: {}/{}/{}, found IP of VM: {}", service.getId(), unitID, instanceID, ip); return checkMemoryUsageIsBelowThreadhold(threadhold, ip); } private static boolean checkMemoryUsageIsBelowThreadhold(float threadhold, String ip) { String gangliaInfo = getVMInformationFromGanglia(ip); String mem_free = extractGangliaMetric("mem_free", gangliaInfo); String mem_cached = extractGangliaMetric("mem_cached", gangliaInfo); String mem_total = extractGangliaMetric("mem_total", gangliaInfo); LOGGER.debug("Query mem_free: {}, mem_cached: {}, mem_total: {}", mem_free, mem_cached, mem_total); double mem_freeL = Float.parseFloat(mem_free); double mem_cachedL = Float.parseFloat(mem_cached); double mem_totalL = Float.parseFloat(mem_total); LOGGER.debug("Query mem_free Float value: {}, mem_cached: {}, mem_total: {}", mem_freeL, mem_cachedL, mem_totalL); double mem_free_percent = ( mem_freeL + mem_cachedL) / mem_totalL; double mem_usaged_percent = 1 - mem_free_percent; LOGGER.debug("Calculate mem_usage_percent: {}, threadhold: {}", mem_usaged_percent, threadhold); return (mem_usaged_percent < threadhold); } public static String getIpOfInstance(CloudService service, String nodeID, int instanceID, boolean countingDocker) { LOGGER.debug("Getting the IP of the instance: {}/{}/{}. Counting docker: {}", service.getId(), nodeID, instanceID, countingDocker); ServiceUnit unit = service.getComponentById(nodeID); ServiceInstance instance = unit.getInstanceById(instanceID); ServiceUnit hostedUnit = unit; ServiceInstance hostedInstance = instance; while (!hostedUnit.getType().equals(SalsaEntityType.OPERATING_SYSTEM.getEntityTypeString()) && !(countingDocker && hostedUnit.getType().equals(SalsaEntityType.DOCKER.getEntityTypeString()))) { hostedUnit = service.getComponentById(hostedUnit.getHostedId()); if (hostedUnit == null) { LOGGER.debug(" - getingIPOfInstance: but the hosted unit is null (could not happen, so weird)"); return null; } hostedInstance = hostedUnit.getInstanceById(hostedInstance.getHostedId_Integer()); // if there is no instance is deployed if (hostedInstance == null) { LOGGER.debug(" - getingIPOfInstance: but the hosted instance is null, I should check lower stacks"); return null; } } LOGGER.debug("Hosted instance: " + hostedUnit.getId() + "/" + hostedInstance.getInstanceId()); SalsaInstanceDescription_VM vm = (SalsaInstanceDescription_VM) hostedInstance.getProperties().getAny(); return vm.getPrivateIp().trim(); } public static String extractGangliaMetric(String metricName, String gangliaInfo) { JAXBContext jaxbContext; try { jaxbContext = JAXBContext.newInstance(GangliaHostInfo.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); StringReader sr = new StringReader(gangliaInfo); GangliaHostInfo info = (GangliaHostInfo) jaxbUnmarshaller.unmarshal(sr); LOGGER.debug("Parsed the ganglia info done. The name is: {}, there are {} metrics. Will check metric {} now", info.getNAME(), info.getMETRICS().size(), metricName); for (METRIC metric : info.getMETRICS()) { LOGGER.debug("Checking metric name: {} ...", metric.getNAME()); if (metric.getNAME().equals(metricName)) { return metric.getVAL(); } } } catch (JAXBException ex) { LOGGER.error("Cannot parse the ganglia info to get the metric with name: {}", metricName); ex.printStackTrace(); } LOGGER.error("There is no metric with name: {}", metricName); return null; } public static String getGangliaVMInfo(CloudService service, String nodeID, int instanceID){ String ip = getIpOfInstance(service, nodeID, instanceID, false); return getVMInformationFromGanglia(ip); } private static String getVMInformationFromGanglia(String ip) { EngineLogger.logger.debug("Querying ganglia information and return: " + ip); //ProcessBuilder pb = new ProcessBuilder("/usr/bin/telnet",ip,"8649"); EngineLogger.logger.debug("Debug ganglia 1"); // try { //Process p = pb.start(); // Process p = Runtime.getRuntime().exec("/usr/bin/telnet " + ip + " 8649"); String gangliaXML = SystemFunctions.executeCommandGetOutput("/usr/bin/telnet " + ip + " 8649", "/tmp", ""); EngineLogger.logger.debug("Debug ganglia 2"); System.out.println("GANGLIA XML: "+gangliaXML); EngineLogger.logger.debug("Get gangliaXML, length: " + gangliaXML.length()); StringBuilder sb = new StringBuilder(); // get subString Scanner scanner = new Scanner(gangliaXML); boolean writing = false; while (scanner.hasNextLine()) { String line = scanner.nextLine(); if (line.contains("<HOST")){ EngineLogger.logger.debug("Found a line starting of HOST: {}", line); } if (line.contains("<HOST") && line.contains("IP=\"" + ip + "\"")) { EngineLogger.logger.debug("The IP is correct: {}", ip); writing = true; } if (writing) { sb.append(line); } if (writing && line.contains("</HOST>")) { EngineLogger.logger.debug("Closing HOST tag ..."); writing = false; break; } } scanner.close(); EngineLogger.logger.debug("Extract the information from ganglia is done: "); EngineLogger.logger.debug(sb.toString()); return sb.toString(); // Process p = Runtime.getRuntime().exec("/bin/netcat " + ip.trim() + " 8649"); // EngineLogger.logger.debug("Debug ganglia 2"); // p.waitFor(); // EngineLogger.logger.debug("Debug ganglia 3"); // // BufferedReader reader = new BufferedReader( // new InputStreamReader(p.getInputStream())); // String output = ""; // boolean writing = false; // // String line = reader.readLine(); // EngineLogger.logger.debug("Debug ganglia 4"); // EngineLogger.logger.debug(line); // //line = reader.readLine(); line = reader.readLine(); line = reader.readLine(); // 3 first line of telnet command // // we write out the HOST information of GANGLIA_XML // while (line != null) { // if (line.contains("<HOST") && line.contains("IP=\"" + ip + "\"")) { // writing = true; // } // if (writing) { // output += line; // } // if (writing && line.contains("</HOST>")) { // writing = false; // } // // line = reader.readLine(); // } // EngineLogger.logger.debug(output); // return output; // } catch (IOException e) { // EngineLogger.logger.debug(e.toString()); // return "<Error>Error when query monitoring information !</Error>"; // // } catch (InterruptedException e1) { // EngineLogger.logger.debug(e1.toString()); // return "Error when execute command to query monitoring information !"; // } } }