/**
* Copyright 2013 Technische Universitat Wien (TUW), Distributed SystemsGroup
* E184. This work was partially supported by the European Commission in terms
* of the CELAR FP7 project (FP7-ICT-2011-8 #317790).
*
* 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.rSybl.dataProcessingUnit.monitoringPlugins.melaPlugin;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import at.ac.tuwien.dsg.csdg.DependencyGraph;
import at.ac.tuwien.dsg.csdg.Node;
import at.ac.tuwien.dsg.csdg.Node.NodeType;
import at.ac.tuwien.dsg.csdg.Relationship.RelationshipType;
import at.ac.tuwien.dsg.csdg.elasticityInformation.ElasticityRequirement;
import at.ac.tuwien.dsg.csdg.elasticityInformation.elasticityRequirements.BinaryRestriction;
import at.ac.tuwien.dsg.csdg.elasticityInformation.elasticityRequirements.BinaryRestrictionsConjunction;
import at.ac.tuwien.dsg.csdg.elasticityInformation.elasticityRequirements.Constraint;
import at.ac.tuwien.dsg.csdg.elasticityInformation.elasticityRequirements.SYBLSpecification;
import at.ac.tuwien.dsg.csdg.inputProcessing.multiLevelModel.abstractModelXML.SYBLDirectiveMappingFromXML;
import at.ac.tuwien.dsg.mela.common.configuration.metricComposition.CompositionRulesConfiguration;
import at.ac.tuwien.dsg.mela.common.monitoringConcepts.Metric;
import at.ac.tuwien.dsg.mela.common.monitoringConcepts.MetricValue;
import at.ac.tuwien.dsg.mela.common.monitoringConcepts.MonitoredElement;
import at.ac.tuwien.dsg.mela.common.monitoringConcepts.MonitoredElementMonitoringSnapshot;
import at.ac.tuwien.dsg.mela.common.monitoringConcepts.ServiceMonitoringSnapshot;
import at.ac.tuwien.dsg.mela.common.requirements.Condition.Type;
import at.ac.tuwien.dsg.mela.common.requirements.Requirement;
import at.ac.tuwien.dsg.mela.common.requirements.Requirements;
import at.ac.tuwien.dsg.rSybl.dataProcessingUnit.api.model.MonitoringSnapshot;
import at.ac.tuwien.dsg.rSybl.dataProcessingUnit.monitoringPlugins.interfaces.MonitoringInterface;
import at.ac.tuwien.dsg.rSybl.dataProcessingUnit.utils.Configuration;
import at.ac.tuwien.dsg.rSybl.dataProcessingUnit.utils.RuntimeLogger;
import java.io.StringWriter;
import java.util.HashMap;
public class MELA_API implements MonitoringInterface {
private boolean existsStructureData = false;
private boolean serviceSet = false;
private static final String REST_API_URL = Configuration.getMonitoringServiceURL();
//private static final String REST_API_URL = "http://localhost:8080/MELA-AnalysisService-0.1-SNAPSHOT/REST_WS";
// private static final String REST_API_URL="http://localhost:8080/MELA-AnalysisService-1.0/REST_WS";
private static final int MONITORING_DATA_REFRESH_INTERVAL = 10; //in seconds
private MonitoredElementMonitoringSnapshot latestMonitoringData;
private AtomicBoolean monitoringDataUsed;
private ArrayList<String> ongoingAction;
private List<String> actionTargetEntity;
private Node controlService;
{
latestMonitoringData = new MonitoredElementMonitoringSnapshot();
monitoringDataUsed = new AtomicBoolean(false);
}
public MELA_API() {
ongoingAction = new ArrayList<String>();
actionTargetEntity = new ArrayList<String>();
}
//todo: Continuous refresh data with a semaphore like mechanism to synchronzie resource access
{
TimerTask task = new TimerTask() {
@Override
public void run() {
if (serviceSet) {
refreshMonitoringData();
}
}
};
Timer monitoringDataRefreshTimer = new Timer();
monitoringDataRefreshTimer.schedule(task, 0, MONITORING_DATA_REFRESH_INTERVAL * 1000);
}
// private List<MetricFilter> getMetricFilters() {
// List<MetricFilter> filters = new ArrayList<MetricFilter>();
// MetricFilter metricFilter = new MetricFilter();
// metricFilter.setId("VMLevelCassandra");
// Metric m;
// metricFilter.setLevel(ServiceElement.ServiceElementLevel.VM);
// Collection<Metric> metrics = new ArrayList<Metric>();
// metrics.add(new Metric("cpu_usage"));
// metrics.add(new Metric("mem_used"));
// metrics.add(new Metric("pkts_total"));
//
// metricFilter.setMetrics(metrics);
// filters.add(metricFilter);
//
//
// metricFilter = new MetricFilter();
//
// metricFilter.setId("SERVICE_UNITLevel");
// metricFilter.setLevel(ServiceElement.ServiceElementLevel.SERVICE_UNIT);
//
// metrics = new ArrayList<Metric>();
// m = new Metric("cpu_usage");
// metrics.add(m);
// m = new Metric("read_latency");
// metrics.add(m);
// m = new Metric("costPerHour");
// metrics.add(m);
// m = new Metric("write_latency");
// metrics.add(m);
// m = new Metric("responseTime");
// metrics.add(m);
// m = new Metric("throughput");
// metrics.add(m);
// m = new Metric("throughput_average");
// metrics.add(m);
// m = new Metric("clientsNb");
// metrics.add(m);
// metricFilter.setMetrics(metrics);
//
//
// filters.add(metricFilter);
// metricFilter = new MetricFilter();
// metricFilter.setId("SERVICE_TOPOLOGYLevel");
// metricFilter.setLevel(ServiceElement.ServiceElementLevel.SERVICE_TOPOLOGY);
//
// metrics = new ArrayList<Metric>();
// m = new Metric("costPerHour");
// metrics.add(m);
// m = new Metric("responseTime");
// metrics.add(m);
// m = new Metric("clientsNb");
// metrics.add(m);
// metricFilter.setMetrics(metrics);
//
// filters.add(metricFilter);
// metricFilter = new MetricFilter();
// metricFilter.setId("SERVICELevel");
// metricFilter.setLevel(ServiceElement.ServiceElementLevel.SERVICE);
// metrics = new ArrayList<Metric>();
// metrics.add(new Metric("cpu_usage"));
// m = new Metric("clientsNb");
// metrics.add(m);
// m = new Metric("costPerHour");
//
// metrics.add(m);
//
//
// m = new Metric("costPerClientPerHour");
// metrics.add(m);
// metricFilter.setMetrics(metrics);
//
// filters.add(metricFilter);
// return filters;
//
// }
/**
* pulls new monitoring data
*/
public void refreshMonitoringData() {
URL url = null;
HttpURLConnection connection = null;
try {
url = new URL(REST_API_URL + "/monitoringdataXML");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "application/xml");
connection.setRequestProperty("Accept", "application/xml");
InputStream errorStream = connection.getErrorStream();
if (errorStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
InputStream inputStream = connection.getInputStream();
JAXBContext jAXBContext = JAXBContext.newInstance(MonitoredElementMonitoringSnapshot.class);
MonitoredElementMonitoringSnapshot retrievedData = (MonitoredElementMonitoringSnapshot) jAXBContext.createUnmarshaller().unmarshal(inputStream);
if (retrievedData != null) {
//P
getLatestMonitoringDataLock();
latestMonitoringData = retrievedData;
//V
releaseLatestMonitoringDataLock();
}
} catch (Exception e) {
// Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, e.getMessage(), e);
Logger.getLogger(MELA_API.class.getName()).log(Level.WARNING, "Trying to connect to MELA - failing ... . Retrying later");
RuntimeLogger.logger.error("Failing to connect to MELA");
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
//uses a semaphore like mechanism to synchronzie access to the latestMonitoringData to avoid data refresh when data is queried
private void getLatestMonitoringDataLock() {
while (monitoringDataUsed.get()) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, null, ex);
}
};
monitoringDataUsed.set(true);
}
private void releaseLatestMonitoringDataLock() {
monitoringDataUsed.set(false);
}
public void setCurrentCloudService (Node cloudService){
this.controlService=cloudService;
}
public void submitServiceConfiguration(Node cloudService) {
controlService = cloudService;
MonitoredElement element = new MonitoredElement();
element.setId(cloudService.getId());
element.setLevel(MonitoredElement.MonitoredElementLevel.SERVICE);
MELA_ClientUtils.convertServiceTopology(element, cloudService);
URL url = null;
HttpURLConnection connection = null;
boolean notConnected = true;
while (notConnected) {
try {
RuntimeLogger.logger.info("Trying to connect to MELA ...");
url = new URL(REST_API_URL + "/servicedescription");
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("PUT");
connection.setRequestProperty("Content-Type", "application/xml");
connection.setRequestProperty("Accept", "text/plain");
InputStream errorStream = connection.getErrorStream();
if (errorStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
InputStream inputStream = connection.getInputStream();
if (inputStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
serviceSet = true;
notConnected = false;
} catch (Exception e) {
//Logger.getLogger(MELA_API.class.getName()).log(Level.WARNING, "Trying to connect to MELA - failing ... . Retrying later");
RuntimeLogger.logger.error("Failing to connect to MELA" + e.getMessage());
try {
Thread.sleep(MONITORING_DATA_REFRESH_INTERVAL * 1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}
public void refreshServiceStructure(Node cloudService) {
MonitoredElement element = new MonitoredElement();
element.setId(cloudService.getId());
element.setLevel(MonitoredElement.MonitoredElementLevel.SERVICE);
MELA_ClientUtils.convertServiceTopology(element, cloudService);
URL url = null;
HttpURLConnection connection = null;
try {
url = new URL(REST_API_URL + "/servicedescription");
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/xml");
connection.setRequestProperty("Accept", "application/json");
//write message body
OutputStream os = connection.getOutputStream();
JAXBContext jaxbContext = JAXBContext.newInstance(MonitoredElement.class);
jaxbContext.createMarshaller().marshal(element, os);
os.flush();
os.close();
InputStream errorStream = connection.getErrorStream();
if (errorStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
InputStream inputStream = connection.getInputStream();
if (inputStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
} catch (Exception e) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, e.getMessage(), e);
} finally {
if (connection != null) {
connection.disconnect();
}
}
submitCompositionRules();
serviceSet = true;
}
public void submitMetricCompositionConfiguration(CompositionRulesConfiguration compositionRulesConfiguration) {
URL url = null;
HttpURLConnection connection = null;
try {
url = new URL(REST_API_URL + "/metricscompositionrules");
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("PUT");
connection.setRequestProperty("Content-Type", "application/xml");
connection.setRequestProperty("Accept", "application/json");
//write message body
OutputStream os = connection.getOutputStream();
JAXBContext jaxbContext = JAXBContext.newInstance(CompositionRulesConfiguration.class);
jaxbContext.createMarshaller().marshal(compositionRulesConfiguration, os);
os.flush();
os.close();
InputStream errorStream = connection.getErrorStream();
if (errorStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
InputStream inputStream = connection.getInputStream();
if (inputStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
} catch (Exception e) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, e.getMessage(), e);
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
// public Double getCpuUsage(Node entity) {
// Metric metric = new Metric("cpu_usage");
// RuntimeLogger.logger.info("For entity " + entity.getId() + " Cpu usage is " + getMetricValue(metric, entity) + "cpu idle is" + getMetricValue(new Metric("cpu_idle"), entity));
// return getMetricValue(metric, entity);
// }
//
// public Double getMemoryAvailable(Node entity) {
// Metric metric = new Metric("mem_free_in_GB");
// return getMetricValue(metric, entity);
// }
//
// public Double getMemorySize(Node entity) {
// Metric metric = new Metric("mem_total_in_GB");
// return getMetricValue(metric, entity);
// }
//
// public Double getMemoryUsage(Node entity) {
// Metric metric = new Metric("mem_used");
// return getMetricValue(metric, entity);
// }
//
// public Double getDiskSize(Node entity) {
// Metric metric = new Metric("disk_total");
// return getMetricValue(metric, entity);
// }
//
// public Double getDiskAvailable(Node entity) {
// Metric metric = new Metric("disk_free");
// return getMetricValue(metric, entity);
// }
//
// //TODO: define agg rule in procentaj
// public Double getDiskUsage(Node entity) {
//
// return (getDiskSize(entity) - getDiskAvailable(entity)) / getDiskSize(entity) * 100;
// }
//
// public Double getCPUSpeed(Node entity) {
//
// Metric metric = new Metric("cpu_speed");
// return getMetricValue(metric, entity);
// }
//
// //TODO: define agg rule in TOTAL
// public Double getPkts(Node entity) {
// Metric metric = new Metric("pkts_total");
// return getMetricValue(metric, entity);
// }
//
// public Double getPktsIn(Node entity) {
// Metric metric = new Metric("pkts_in");
// return getMetricValue(metric, entity);
// }
//
// public Double getPktsOut(Node entity) {
// Metric metric = new Metric("pkts_out");
// return getMetricValue(metric, entity);
// }
//
// public Double getReadLatency(Node entity) {
// Metric metric = new Metric("read_latency");
// return getMetricValue(metric, entity);
// }
//
// public Double getWriteLatency(Node entity) {
// Metric metric = new Metric("write_latency");
// return getMetricValue(metric, entity);
// }
//
// public Double getReadCount(Node entity) {
// Metric metric = new Metric("read_count");
// return getMetricValue(metric, entity);
// }
//
// public Double getCostPerHour(Node entity) {
// Metric metric = new Metric("costPerHour");
// return getMetricValue(metric, entity);
// }
//
// public Double getWriteCount(Node entity) {
// Metric metric = new Metric("write_count");
// return getMetricValue(metric, entity);
// }
//
// //TODO: can;t be done currentlu
// public Double getTotalCostSoFar(Node entity) {
// Metric metric = new Metric("costPerHour");
// return getMetricValue(metric, entity);
// }
//
// /**
// * @return currently, all metrics for the first VM that is monitored. While
// * MELA can return metrics for different VMs belonging to different service
// * units, it would require a Service_unit_id to be added as parameter to
// * this call
// */
// public List<String> getAvailableMetrics() {
// ServiceMonitoringSnapshot monitoringSnapshot = systemControl.getRawMonitoringData();
// Map<ServiceElement, ServiceElementMonitoringSnapshot> monitoringData = monitoringSnapshot.getMonitoredData(ServiceElement.ServiceElementLevel.VM);
//
// Collection<Metric> metrics = monitoringData.values().iterator().next().getMonitoredData().keySet();
// List<String> strings = new ArrayList<String>();
// for (Metric metric : metrics) {
// strings.add(metric.getName());
// }
// return strings;
// }
//
// //should at least have an action name in name
public void notifyControlActionStarted(String actionName, Node actionTargetEntity) {
URL url = null;
HttpURLConnection connection = null;
try {
this.ongoingAction.add(actionName);
this.actionTargetEntity.add(actionTargetEntity.getId());
url = new URL(REST_API_URL + "/addexecutingactions");
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/xml");
connection.setRequestProperty("Accept", "application/xml");
//write message body
OutputStream os = connection.getOutputStream();
String compositionRules = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ "<Action targetEntityID=\"" + actionTargetEntity.getId() + "\" action=\"" + actionName + "\" />";
os.write(compositionRules.getBytes());
os.flush();
os.close();
InputStream errorStream = connection.getErrorStream();
if (errorStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
InputStream inputStream = connection.getInputStream();
if (inputStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
} catch (Exception e) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, e.getMessage(), e);
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
public void notifyControlActionEnded(String actionName, Node actionTargetEntity) {
URL url = null;
HttpURLConnection connection = null;
try {
url = new URL(REST_API_URL + "/removeexecutingactions");
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/xml");
connection.setRequestProperty("Accept", "application/xml");
//write message body
OutputStream os = connection.getOutputStream();
String compositionRules = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ "<Action targetEntityID=\"" + actionTargetEntity.getId() + "\" action=\"" + actionName + "\" />";
os.write(compositionRules.getBytes());
os.flush();
os.close();
InputStream errorStream = connection.getErrorStream();
if (errorStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
InputStream inputStream = connection.getInputStream();
if (inputStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
} catch (Exception e) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, e.getMessage(), e);
} finally {
this.ongoingAction.remove(actionName);
actionName = "";
this.actionTargetEntity.remove(actionTargetEntity.getId());
if (connection != null) {
connection.disconnect();
}
}
}
public Double getMetricValue(Metric metric, Node entity) {
if (entity.getId() == null) {
Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Supplied entity has no ID. Can't get metric value");
return -1.0;
}
//get the Entity level so I can search it in the monitored snapshot easily (only in entity and its children)
MonitoredElement.MonitoredElementLevel level = MELA_ClientUtils.getElementLevelFromEntity(entity);
MonitoredElement element = new MonitoredElement();
element.setId(entity.getId());
element.setLevel(level);
//search in the aggregated data over time for the target entity
MonitoredElement elementSearchingFor = new MonitoredElement(entity.getId());
List<MonitoredElementMonitoringSnapshot> processing = new ArrayList<MonitoredElementMonitoringSnapshot>();
processing.add(latestMonitoringData);
while (!processing.isEmpty()) {
MonitoredElementMonitoringSnapshot currentlyUnderInspection = processing.remove(0);
if (currentlyUnderInspection.getMonitoredElement().equals(elementSearchingFor)) {
if (currentlyUnderInspection.containsMetric(metric)) {
MetricValue value = currentlyUnderInspection.getMetricValue(metric);
switch (value.getValueType()) {
case NUMERIC:
return Double.parseDouble(value.getValueRepresentation());
default:
Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Value ''{0}''for metric {1} for Node {2} is not Numeric", new Object[]{value.getValueRepresentation(), metric.toString(), entity.getId()});
return -1.0;
}
}
} else {
processing.addAll(currentlyUnderInspection.getChildren());
}
}
//if we have reached this point, either the monitored element was not found, either the metric
RuntimeLogger.logger.info("Metric " + metric.toString() + " OR Node " + entity.getId() + " not found");
return -1.0;
}
@Override
public void sendMessageToAnalysisService(String message) {
URL url = null;
HttpURLConnection connection = null;
boolean notConnected = true;
while (notConnected) {
try {
RuntimeLogger.logger.info("Trying to connect to MELA ...");
url = new URL(REST_API_URL + "/"+controlService.getId()+"/events");
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "text/plain");
//write message body
OutputStream os = connection.getOutputStream();
//JAXBContext jaxbContext = JAXBContext.newInstance(MonitoredElement.class);
//jaxbContext.createMarshaller().marshal(message, os);
os.write(message.getBytes());
os.flush();
os.close();
InputStream errorStream = connection.getErrorStream();
if (errorStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
InputStream inputStream = connection.getInputStream();
if (inputStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
serviceSet = true;
notConnected = false;
} catch (Exception e) {
//Logger.getLogger(MELA_API.class.getName()).log(Level.WARNING, "Trying to connect to MELA - failing ... . Retrying later");
RuntimeLogger.logger.error("Failing to connect to MELA" + e.getMessage());
try {
Thread.sleep(MONITORING_DATA_REFRESH_INTERVAL * 1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}
@Override
public void sendControlIncapacityMessage(String message, List<ElasticityRequirement> cause) {
URL url = null;
HttpURLConnection connection = null;
boolean notConnected = true;
while (notConnected) {
try {
RuntimeLogger.logger.info("Trying to connect to MELA ...");
url = new URL(REST_API_URL + "/"+controlService.getId()+"/events");
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "text/plain");
//write message body
OutputStream os = connection.getOutputStream();
//JAXBContext jaxbContext = JAXBContext.newInstance(MonitoredElement.class);
//jaxbContext.createMarshaller().marshal(message, os);
String myCause = "";
for (ElasticityRequirement req: cause){
myCause+=req.getAnnotation().getConstraints()+"; ";
}
os.write((message+"Cause : "+myCause).getBytes());
os.flush();
os.close();
InputStream errorStream = connection.getErrorStream();
if (errorStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
InputStream inputStream = connection.getInputStream();
if (inputStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
serviceSet = true;
notConnected = false;
} catch (Exception e) {
//Logger.getLogger(MELA_API.class.getName()).log(Level.WARNING, "Trying to connect to MELA - failing ... . Retrying later");
RuntimeLogger.logger.error("Failing to connect to MELA" + e.getMessage());
try {
Thread.sleep(MONITORING_DATA_REFRESH_INTERVAL * 1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}
@Override
public boolean isHealthy() {
return true;
}
@Override
public List<MonitoringSnapshot> getAllMonitoringInformation() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public List<MonitoringSnapshot> getAllMonitoringInformationOnPeriod(long time) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public List<MonitoringSnapshot> getAllMonitoringInformationFromTimestamp(long timestamp) {
throw new UnsupportedOperationException("Not supported yet.");
}
private static class MELA_ClientUtils {
//works as side effect
public static void convertServiceTopology(MonitoredElement serviceElement, Node cloudService) {
//RuntimeLogger.logger.info("Related nodes for node "+ cloudService +" are "+ cloudService.getAllRelatedNodesOfType(RelationshipType.COMPOSITION_RELATIONSHIP));
List<Node> serviceTopologies = new ArrayList<Node>();
MonitoredElement mainServiceTopologyElement = new MonitoredElement();
if (cloudService.getAllRelatedNodesOfType(RelationshipType.COMPOSITION_RELATIONSHIP, NodeType.SERVICE_TOPOLOGY).size() == 1) {
mainServiceTopologyElement = new MonitoredElement();
Node serviceTopology = cloudService.getAllRelatedNodesOfType(RelationshipType.COMPOSITION_RELATIONSHIP, NodeType.SERVICE_TOPOLOGY).get(0);
mainServiceTopologyElement.setId(serviceTopology.getId());
mainServiceTopologyElement.setLevel(MonitoredElement.MonitoredElementLevel.SERVICE_TOPOLOGY);
serviceTopologies.addAll(serviceTopology.getAllRelatedNodesOfType(RelationshipType.COMPOSITION_RELATIONSHIP));
} else {
serviceTopologies.addAll(cloudService.getAllRelatedNodesOfType(RelationshipType.COMPOSITION_RELATIONSHIP));
}
while (!serviceTopologies.isEmpty()) {
MonitoredElement serviceTopologyElement = new MonitoredElement();
Node serviceTopology = serviceTopologies.get(0);
serviceTopologyElement.setId(serviceTopology.getId());
serviceTopologyElement.setLevel(MonitoredElement.MonitoredElementLevel.SERVICE_TOPOLOGY);
if (serviceTopology.getAllRelatedNodesOfType(RelationshipType.COMPOSITION_RELATIONSHIP) != null) {
for (Node serviceUnit : serviceTopology.getAllRelatedNodesOfType(RelationshipType.COMPOSITION_RELATIONSHIP)) {
if (serviceUnit.getNodeType() == NodeType.SERVICE_UNIT) {
MonitoredElement serviceUnitElement = new MonitoredElement();
serviceUnitElement.setId(serviceUnit.getId());
serviceUnitElement.setLevel(MonitoredElement.MonitoredElementLevel.SERVICE_UNIT);
Node artifact = null;
Node container = null;
Node accessToVM = serviceUnit;
if (serviceUnit.getAllRelatedNodesOfType(RelationshipType.HOSTED_ON_RELATIONSHIP, NodeType.ARTIFACT) != null && serviceUnit.getAllRelatedNodesOfType(RelationshipType.HOSTED_ON_RELATIONSHIP, NodeType.ARTIFACT).size() > 0) {
artifact = serviceUnit.getAllRelatedNodesOfType(RelationshipType.HOSTED_ON_RELATIONSHIP, NodeType.ARTIFACT).get(0);
if (artifact.getAllRelatedNodesOfType(RelationshipType.HOSTED_ON_RELATIONSHIP, NodeType.CONTAINER) != null && artifact.getAllRelatedNodesOfType(RelationshipType.HOSTED_ON_RELATIONSHIP, NodeType.CONTAINER).size() > 0) {
container = artifact.getAllRelatedNodesOfType(RelationshipType.HOSTED_ON_RELATIONSHIP, NodeType.CONTAINER).get(0);
}
}
if (artifact != null || container != null) {
if (container == null) {
accessToVM = artifact;
} else {
accessToVM = container;
}
}
for (Node vm : accessToVM.getAllRelatedNodesOfType(RelationshipType.HOSTED_ON_RELATIONSHIP, NodeType.VIRTUAL_MACHINE)) {
// RuntimeLogger.logger.info("Translating hosted on "+vm.getId()+" for node "+serviceUnitElement.getId());
MonitoredElement virtualMachine = new MonitoredElement();
virtualMachine.setId(vm.getId());
virtualMachine.setLevel(MonitoredElement.MonitoredElementLevel.VM);
serviceUnitElement.addElement(virtualMachine);
}
for (Node vm : accessToVM.getAllRelatedNodesOfType(RelationshipType.ASSOCIATED_AT_RUNTIME_RELATIONSHIP, NodeType.VIRTUAL_MACHINE)) {
MonitoredElement virtualMachine = new MonitoredElement();
virtualMachine.setId(vm.getId());
boolean alreadyContained = false;
virtualMachine.setLevel(MonitoredElement.MonitoredElementLevel.VM);
for (MonitoredElement el : serviceUnitElement.getContainedElements()) {
if (el.getId().equalsIgnoreCase(vm.getId())) {
alreadyContained = true;
}
}
if (!alreadyContained) {
serviceUnitElement.addElement(virtualMachine);
}
}
serviceTopologyElement.addElement(serviceUnitElement);
}
if (serviceUnit.getNodeType() == NodeType.SERVICE_TOPOLOGY) {
MonitoredElement serviceUnitElement = new MonitoredElement();
serviceTopologyElement.setId(serviceUnit.getId());
serviceTopologyElement.setLevel(MonitoredElement.MonitoredElementLevel.SERVICE_TOPOLOGY);
serviceTopologyElement.addElement(serviceUnitElement);
}
}
}
if (mainServiceTopologyElement != null) {
mainServiceTopologyElement.addElement(serviceTopologyElement);
} else {
serviceElement.addElement(serviceTopologyElement);
}
if (serviceTopology.getAllRelatedNodesOfType(RelationshipType.COMPOSITION_RELATIONSHIP) != null) {
for (Node subTopology : serviceTopology.getAllRelatedNodesOfType(RelationshipType.COMPOSITION_RELATIONSHIP)) {
if (subTopology.getNodeType() == NodeType.SERVICE_TOPOLOGY) {
serviceTopologies.add(subTopology);
}
}
}
serviceTopologies.remove(0);
}
if (mainServiceTopologyElement != null) {
serviceElement.addElement(mainServiceTopologyElement);
}
}
public static MonitoredElement.MonitoredElementLevel getElementLevelFromEntity(Node entity) {
if (entity.getNodeType() == NodeType.CLOUD_SERVICE) {
return MonitoredElement.MonitoredElementLevel.SERVICE;
} else if (entity.getNodeType() == NodeType.SERVICE_TOPOLOGY) {
return MonitoredElement.MonitoredElementLevel.SERVICE_TOPOLOGY;
} else if (entity.getNodeType() == NodeType.SERVICE_UNIT) {
return MonitoredElement.MonitoredElementLevel.SERVICE_UNIT;
} else {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, "Error. Cannot determine the source class of entity " + entity);
return null;
}
}
}
public static void main(String[] args) throws Exception {
}
@Override
public void submitElasticityRequirements(
ArrayList<ElasticityRequirement> description) {
Requirements requirements = new Requirements();
ArrayList<Requirement> requirements2 = new ArrayList<Requirement>();
for (ElasticityRequirement elasticityRequirement : description) {
// RuntimeLogger.logger.info("Setting elasticity requirement " + elasticityRequirement.getAnnotation().getConstraints());
SYBLSpecification specification = SYBLDirectiveMappingFromXML.mapFromSYBLAnnotation(elasticityRequirement.getAnnotation());
// !!!Set all info
for (Constraint constraint : specification.getConstraint()) {
RuntimeLogger.logger.info("Transformed constraint " + elasticityRequirement.getAnnotation().getConstraints());
for (BinaryRestrictionsConjunction binaryRestrictions : constraint.getToEnforce().getBinaryRestriction()) {
for (BinaryRestriction binaryRestriction : binaryRestrictions.getBinaryRestrictions()) {
Requirement req = new Requirement();
req.setId(specification.getComponentId());
ArrayList<String> targetedEls = new ArrayList<String>();
targetedEls.add(specification.getComponentId());
req.setTargetMonitoredElementIDs(targetedEls);
List<at.ac.tuwien.dsg.mela.common.requirements.Condition> conditions = new ArrayList<at.ac.tuwien.dsg.mela.common.requirements.Condition>();
at.ac.tuwien.dsg.mela.common.requirements.Condition cond = new at.ac.tuwien.dsg.mela.common.requirements.Condition();
DependencyGraph dep = new DependencyGraph();
dep.setCloudService(controlService);
req.setTargetMonitoredElementLevel(MELA_ClientUtils.getElementLevelFromEntity(dep.getNodeWithID(specification.getComponentId())));
if (binaryRestriction.getLeftHandSide().getMetric() != null) {
String metric = binaryRestriction.getLeftHandSide().getMetric();
Metric m = new Metric();
m.setName(metric);
m.setMeasurementUnit(null);
req.setMetric(m);
MetricValue metricValue = new MetricValue();
metricValue.setValue(Double.parseDouble(binaryRestriction.getRightHandSide().getNumber()));
cond.addValue(metricValue);
switch (binaryRestriction.getType()) {
case "lessThan":
cond.setType(Type.LESS_THAN);
break;
case "greaterThan":
cond.setType(Type.GREATER_THAN);
break;
case "lessThanOrEqual":
cond.setType(Type.LESS_EQUAL);
break;
case "greaterThanOrEqual":
cond.setType(Type.GREATER_EQUAL);
break;
case "differentThan":
//cond.setType(Type.)
break;
case "equals":
cond.setType(Type.EQUAL);
break;
default:
cond.setType(Type.LESS_THAN);
break;
}
} else {
if (binaryRestriction.getRightHandSide().getMetric() != null) {
String metric = binaryRestriction.getRightHandSide().getMetric();
Metric m = new Metric();
m.setName(metric);
m.setMeasurementUnit(null);
req.setMetric(m);
switch (binaryRestriction.getType()) {
case "lessThan":
cond.setType(Type.GREATER_THAN);
break;
case "greaterThan":
cond.setType(Type.LESS_THAN);
break;
case "lessThanOrEqual":
cond.setType(Type.GREATER_EQUAL);
break;
case "greaterThanOrEqual":
cond.setType(Type.LESS_EQUAL);
break;
case "differentThan":
//cond.setType(Type.)
break;
case "equals":
cond.setType(Type.EQUAL);
break;
default:
cond.setType(Type.LESS_THAN);
break;
}
MetricValue metricValue = new MetricValue();
metricValue.setValue(Double.parseDouble(binaryRestriction.getRightHandSide().getNumber()));
cond.addValue(metricValue);
}
}
conditions.add(cond);
req.setConditions(conditions);
RuntimeLogger.logger.info("Requirements for MELA" + req.toString());
requirements2.add(req);
}
}
}
}
requirements.setRequirements(requirements2);
URL url = null;
HttpURLConnection connection = null;
try {
url = new URL(REST_API_URL + "/servicerequirements");
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("PUT");
connection.setRequestProperty("Content-Type", "application/xml");
connection.setRequestProperty("Accept", "application/json");
//write message body
OutputStream os = connection.getOutputStream();
JAXBContext jaxbContext = JAXBContext.newInstance(Requirements.class);
jaxbContext.createMarshaller().marshal(requirements, os);
os.flush();
os.close();
InputStream errorStream = connection.getErrorStream();
if (errorStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
InputStream inputStream = connection.getInputStream();
if (inputStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
} catch (Exception e) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, e.getMessage(), e);
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
@Override
public Double getNumberInstances(Node entity) {
Metric metric = new Metric("vmCount");
return getMetricValue(metric, entity);
}
public Double getCpuUsage(Node entity) {
Metric metric = new Metric("cpu_usage");
RuntimeLogger.logger.info("For entity " + entity.getId() + " Cpu usage is " + getMetricValue(metric, entity) + "cpu idle is" + getMetricValue(new Metric("cpu_idle"), entity));
return getMetricValue(metric, entity);
}
public Double getMemoryAvailable(Node entity) {
Metric metric = new Metric("mem_free_in_GB");
return getMetricValue(metric, entity);
}
public Double getMemorySize(Node entity) {
Metric metric = new Metric("mem_total_in_GB");
return getMetricValue(metric, entity);
}
public Double getMemoryUsage(Node entity) {
Metric metric = new Metric("mem_used");
return getMetricValue(metric, entity);
}
public Double getDiskSize(Node entity) {
Metric metric = new Metric("disk_total");
return getMetricValue(metric, entity);
}
public Double getDiskAvailable(Node entity) {
Metric metric = new Metric("disk_free");
return getMetricValue(metric, entity);
}
//TODO: define agg rule in procentaj
public Double getDiskUsage(Node entity) {
return (getDiskSize(entity) - getDiskAvailable(entity)) / getDiskSize(entity) * 100;
}
public Double getCPUSpeed(Node entity) {
Metric metric = new Metric("cpu_speed");
return getMetricValue(metric, entity);
}
//TODO: define agg rule in TOTAL
public Double getPkts(Node entity) {
Metric metric = new Metric("pkts_total");
return getMetricValue(metric, entity);
}
public Double getPktsIn(Node entity) {
Metric metric = new Metric("pkts_in");
return getMetricValue(metric, entity);
}
public Double getPktsOut(Node entity) {
Metric metric = new Metric("pkts_out");
return getMetricValue(metric, entity);
}
public Double getReadLatency(Node entity) {
Metric metric = new Metric("read_latency");
return getMetricValue(metric, entity);
}
public Double getWriteLatency(Node entity) {
Metric metric = new Metric("write_latency");
return getMetricValue(metric, entity);
}
public Double getReadCount(Node entity) {
Metric metric = new Metric("read_count");
return getMetricValue(metric, entity);
}
public Double getCostPerHour(Node entity) {
Metric metric = new Metric("costPerHour");
return getMetricValue(metric, entity);
}
public Double getWriteCount(Node entity) {
Metric metric = new Metric("write_count");
return getMetricValue(metric, entity);
}
//TODO: can;t be done currentlu
public Double getTotalCostSoFar(Node entity) {
Metric metric = new Metric("costPerHour");
return getMetricValue(metric, entity);
}
/**
* @return currently, all metrics for the first VM that is monitored. While
* MELA can return metrics for different VMs belonging to different service
* units, it would require a Service_unit_id to be added as parameter to
* this call
*/
public List<String> getAvailableMetrics(Node node) {
refreshMonitoringData();
List<MonitoredElementMonitoringSnapshot> processing = new ArrayList<MonitoredElementMonitoringSnapshot>();
List<String> metrics = new ArrayList<String>();
processing.add(latestMonitoringData);
while (!processing.isEmpty() && processing != null) {
MonitoredElementMonitoringSnapshot currentlyUnderInspection = processing.remove(0);
if (currentlyUnderInspection.getMonitoredElement().getId().equalsIgnoreCase(node.getId())) {
for (Metric m : currentlyUnderInspection.getMetrics()) {
metrics.add(m.getName());
}
} else {
processing.addAll(currentlyUnderInspection.getChildren());
}
}
return metrics;
}
public List<String> getAvailableMetrics(String id) {
refreshMonitoringData();
List<MonitoredElementMonitoringSnapshot> processing = new ArrayList<MonitoredElementMonitoringSnapshot>();
List<String> metrics = new ArrayList<String>();
processing.add(latestMonitoringData);
while (!processing.isEmpty() && processing != null) {
MonitoredElementMonitoringSnapshot currentlyUnderInspection = processing.remove(0);
if (currentlyUnderInspection.getMonitoredElement().getId().equals(id)) {
for (Metric m : currentlyUnderInspection.getMetrics()) {
metrics.add(m.getName());
}
} else {
processing.addAll(currentlyUnderInspection.getChildren());
}
}
return metrics;
}
public void removeService(Node cloudService) {
controlService = cloudService;
MonitoredElement element = new MonitoredElement();
element.setId(cloudService.getId());
element.setLevel(MonitoredElement.MonitoredElementLevel.SERVICE);
MELA_ClientUtils.convertServiceTopology(element, cloudService);
URL url = null;
HttpURLConnection connection = null;
boolean notConnected = true;
while (notConnected) {
try {
RuntimeLogger.logger.info("Trying to connect to MELA ...");
url = new URL(REST_API_URL + "/" + controlService.getId() );
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("DELETE");
connection.setRequestProperty("Content-Type", "application/xml");
connection.setRequestProperty("Accept", "application/json");
//write message body
OutputStream os = connection.getOutputStream();
JAXBContext jaxbContext = JAXBContext.newInstance(MonitoredElement.class);
jaxbContext.createMarshaller().marshal(element, os);
StringWriter stringWriter = new StringWriter();
jaxbContext.createMarshaller().marshal(element, stringWriter);
RuntimeLogger.logger.info(stringWriter.toString());
os.flush();
os.close();
InputStream errorStream = connection.getErrorStream();
if (errorStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
InputStream inputStream = connection.getInputStream();
if (inputStream != null) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
Logger.getLogger(MELA_API.class.getName()).log(Level.SEVERE, line);
}
}
serviceSet = true;
notConnected = false;
} catch (Exception e) {
//Logger.getLogger(MELA_API.class.getName()).log(Level.WARNING, "Trying to connect to MELA - failing ... . Retrying later");
RuntimeLogger.logger.error("Failing to connect to MELA" + e.getMessage());
try {
Thread.sleep(MONITORING_DATA_REFRESH_INTERVAL * 1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}
public void submitCompositionRules() {
try {
Unmarshaller unmarshaller = JAXBContext.newInstance(CompositionRulesConfiguration.class).createUnmarshaller();
CompositionRulesConfiguration compositionRulesConfiguration = (CompositionRulesConfiguration) unmarshaller.unmarshal(this.getClass().getClassLoader().getResourceAsStream(Configuration.getCompositionRulesPath()));
submitMetricCompositionConfiguration(compositionRulesConfiguration);
} catch (Exception e) {
Unmarshaller unmarshaller;
try {
unmarshaller = JAXBContext.newInstance(CompositionRulesConfiguration.class).createUnmarshaller();
CompositionRulesConfiguration compositionRulesConfiguration = (CompositionRulesConfiguration) unmarshaller.unmarshal(new FileReader(new File(Configuration.getCompositionRulesPath())));
submitMetricCompositionConfiguration(compositionRulesConfiguration);
} catch (JAXBException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
RuntimeLogger.logger.error("Submitting file composition rules. Error when submitting composition rules, in MELA_API" + e.getMessage());
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
public void submitCompositionRules(String compositionRules) {
try {
RuntimeLogger.logger.info("In MELA_API: setting composition rules = " + compositionRules);
Unmarshaller unmarshaller = JAXBContext.newInstance(CompositionRulesConfiguration.class).createUnmarshaller();
StringReader reader = new StringReader(compositionRules);
CompositionRulesConfiguration compositionRulesConfiguration = (CompositionRulesConfiguration) unmarshaller.unmarshal(reader);
submitMetricCompositionConfiguration(compositionRulesConfiguration);
} catch (Exception e) {
e.printStackTrace();
RuntimeLogger.logger.error("Error when submitting composition rules, in MELA_API " + e.getMessage());
}
}
public Double getMetricValue(String metricName, Node entity) {
Metric metric = new Metric(metricName);
return getMetricValue(metric, entity);
}
public boolean checkIfMetricsValid(Node node) {
boolean validity = true;
for (String metric : getAvailableMetrics(node)) {
if (getMetricValue(metric, node) < 0) {
validity = false;
}
}
return validity;
}
@Override
public List<String> getOngoingActionID() {
return this.ongoingAction;
}
@Override
public List<String> getOngoingActionNodeID() {
return this.actionTargetEntity;
}
}