/* * 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.monitoring; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.json.JSONException; import org.json.JSONObject; import org.restlet.Client; import org.restlet.data.CharacterSet; import org.restlet.data.Form; import org.restlet.data.MediaType; import org.restlet.data.Method; import org.restlet.data.Parameter; import org.restlet.data.Protocol; import org.restlet.data.Reference; import org.restlet.data.Request; import org.restlet.data.Response; import org.restlet.ext.json.JsonRepresentation; import org.restlet.resource.DomRepresentation; import org.restlet.resource.Representation; import org.w3c.dom.Document; import org.w3c.dom.NodeList; public class WasupClient { private static Logger log = Logger.getLogger("Monitoring"); private static final String DATA_PATH = "/data"; private static final String ELEMENTS = "/elements"; private static final String ELEMENT_TYPES = "/elementTypes"; private static final String MEASUREMENT_TYPES = "/measurement_types"; private static final String MEASURED_VALUES = "/measured_values"; private static final String MEASUREMENT_RANGES = "/registerRanges"; public static final int NULL_ELEMENT_TYPE = 0; public static final int VDC_ELEMENT_TYPE = 1; public static final int SERVICE_ELEMENT_TYPE = 2; public static final int VEE_ELEMENT_TYPE = 3; public static final int VEEREPLICA_ELEMENT_TYPE = 4; public static final int NET_ELEMENT_TYPE = 9; public static final int NO_ELEMENT_FOUND = -9999; private String server = null; private String wasupSesionId = "invalid"; private Client client = new Client(Protocol.HTTP); private static WasupClient thisInstance=null; public static WasupClient getWasupClient() { if (thisInstance==null) { thisInstance = new WasupClient(); } return thisInstance; } private WasupClient() { } public void login(String server, String login, String passw) throws Exception { if (client.isStopped()) client.start(); this.server = server; log.info("WasupClient.login: server=" + server + "; user=" + login); Reference HWref = new Reference(server + "/login?format=HTML"); Request request = new Request(Method.POST, HWref); List<Parameter> parameterList = new ArrayList<Parameter>(); parameterList.add(new Parameter("username", login)); parameterList.add(new Parameter("password", passw)); Form form = new Form(parameterList); Representation webRepresentation = form.getWebRepresentation(CharacterSet.UTF_8); request.setEntity(webRepresentation); Response response = client.handle(request); wasupSesionId = response.getCookieSettings().getFirstValue("wasup-session-id"); log.info("wasupSesionId:" + wasupSesionId); } private Response get(String path) throws IOException { Reference ref = new Reference(server + path); log.info("WasupClient.get: uri=" + server + path); Request request = new Request(Method.GET, ref); request.getCookies().add("wasup-session-id", wasupSesionId); return client.handle(request); } private Response post(String path, Representation rep) throws IOException { Reference ref = new Reference(server + path); log.info("WasupClient.post: uri=" + server + path); Request request = new Request(Method.POST, ref); request.getCookies().add("wasup-session-id", wasupSesionId); request.setEntity(rep); return client.handle(request); } private Response delete(String path) throws IOException { Reference ref = new Reference(server + path); log.info("WasupClient.delete: uri=" + server + path); Request request = new Request(Method.DELETE, ref); request.getCookies().add("wasup-session-id", wasupSesionId); return client.handle(request); } public String getWasupSesionId() { return wasupSesionId; } public Representation getElementMeasurementTypesRepresentation(String elementId) { Representation rep = null; try { Response res = get(DATA_PATH + ELEMENTS + "/" + elementId + MEASUREMENT_TYPES+"/"); rep = res.getEntity(); } catch (IOException e) { log.error("I/O error retrieving measurement type: " + e.getMessage()); } return rep; } public Representation getMeasuredValuesRepresentation(String measureDescriptorId, int samples) { Representation rep = null; String uri = DATA_PATH + MEASUREMENT_TYPES + "/" + measureDescriptorId + MEASURED_VALUES+"/"; if (samples > 0) uri += "?limit=" + samples; try { Response res = get(uri); rep = res.getEntity(); } catch (IOException e) { log.error("I/O error retrieving measured values: " + e.getMessage()); } return rep; } public int getElementId(String name, int elementTypeId) { String url = DATA_PATH + ELEMENTS + "/" + "?name=" + name; if (elementTypeId > NULL_ELEMENT_TYPE) url += "&elementType.elementTypeId=" + elementTypeId; int ret = NO_ELEMENT_FOUND; try { Response res = get(url); JsonRepresentation jsonRep = new JsonRepresentation(res.getEntity()); JSONObject jo = jsonRep.toJsonArray().getJSONObject(0); int tableSize = jo.getInt("tableSize"); if (tableSize >= 1){ //Element name found JSONObject joElement = jo.getJSONArray("rows").getJSONObject(0); ret = joElement.getInt("elementId"); } log.debug(jsonRep.getText()); } catch (IOException e) { log.error("I/O error retrieving element Id for element["+ name +"] of type [" + elementTypeId + "]: " + e.getMessage()); } catch (JSONException e) { log.error("Error parsing JSON representatino of element["+ name +"] of type [" + elementTypeId + "]: " + e.getMessage()); } return ret; } public int getMeasurementTypeId(String measurementName, int elementId) { try { return Integer.parseInt(measurementName); } catch (NumberFormatException nfe) { } String url = DATA_PATH + MEASUREMENT_TYPES + "/?name=" + measurementName + "&element.elementId=" + elementId; int ret = -1; try { Response res = get(url); JsonRepresentation jsonRep = new JsonRepresentation(res.getEntity()); JSONObject jo = jsonRep.toJsonArray().getJSONObject(0); int tableSize = jo.getInt("tableSize"); if (tableSize >= 1){ //Measurement Type found JSONObject joElement = jo.getJSONArray("rows").getJSONObject(0); ret = joElement.getInt("measurementTypeId"); } log.debug(jsonRep.getText()); } catch (IOException e) { log.error("I/O error retrieving measurement type Id for measurement ["+ measurementName +"] of type [" + elementId + "]: " + e.getMessage()); } catch (JSONException e) { log.error("Error parsing JSON representatino of measurement ["+ measurementName +"] of type [" + elementId + "]: " + e.getMessage()); } return ret; } /** * Calls the wasup to obtain the id of a type through its name. * * @param typeName * Name of the type whose id is wanted. * * @return * The id of the element type if there is one or -1, otherwise * * @throws IOException * @throws JSONException */ public int getElementTypeId(String typeName) throws IOException, JSONException { String url = DATA_PATH + ELEMENT_TYPES + "/?name=" + typeName; int ret = -1; Response res = get(url); JsonRepresentation jsonRep = new JsonRepresentation(res.getEntity()); JSONObject jo = jsonRep.toJsonArray().getJSONObject(0); int tableSize = jo.getInt("tableSize"); if (tableSize >= 1){ //Measurement Type found JSONObject joElement = jo.getJSONArray("rows").getJSONObject(0); ret = joElement.getInt("elementTypeId"); } log.debug(jsonRep.getText()); return ret; } /** * Creates a new element in the wasup, under the element <i>parent</i>. * * The folloging information is needed for the element creation: * * - parentElement.elementId * - elementType.elementTypeId * - name * - description * - location * * @param parent * The element resource that will hold the target element. * * @param fqn * FQN of the target element to be created in the wasup under the parent. * * @return * The Wasup ID of the newly created element. * @throws IOException * @throws JSONException */ public int createElement(String parent, String fqn, String typeId) throws IOException, JSONException { log.info("Creating element: " + fqn + " under element " + parent); Form form = new Form(); form.add("parentElement.elementId", parent); form.add("elementType.elementTypeId", typeId); form.add("name", fqn); form.add("description", "Reservoir element " + fqn); form.add("location", "Local"); form.add("responseType", "XML"); Representation rep = form.getWebRepresentation(); String uri = DATA_PATH + ELEMENTS + "/"; Response response = post(uri, rep); if (response.getStatus().isSuccess()) { int ret=-1; if (response.getEntity().getMediaType().equals(MediaType.APPLICATION_JSON)) { JsonRepresentation jsonRep = new JsonRepresentation(response.getEntity()); JSONObject jo = jsonRep.toJsonArray().getJSONObject(0); int tableSize = jo.getInt("tableSize"); if (tableSize >= 1){ JSONObject joElement = jo.getJSONArray("rows").getJSONObject(0); ret = joElement.getInt("elementId"); } } else if (response.getEntity().getMediaType().equals(MediaType.TEXT_XML)) { DomRepresentation domRep = new DomRepresentation(response.getEntity()); Document doc = domRep.getDocument(); NodeList nodeId = doc.getElementsByTagName("elementId"); try { if (nodeId.getLength() <= 0) { throw new IOException("Wasup request succeed, but the response was empty"); } ret = Integer.parseInt(nodeId.item(0).getTextContent()); } catch (NumberFormatException nfe) { throw new IOException("Wasup request succeed, but the response could not be parsed: " + nfe.getMessage()); } } return ret; } else { throw new IOException("The wasup request didn't succeed; wrong server response."); } } /** * Removes the selected element. * * @param id * The element id. * * @throws IOException */ public void removeElement(String id) throws IOException { log.info("Removing element: " + id + "from wasup"); String uri = DATA_PATH + ELEMENTS + "/" + id; Response response = delete(uri); if (response.getStatus().isSuccess()) { log.info("Removed: " + id); } else { log.info("Element couldn't be erased: " + response.getStatus()); } } /** * Static counter to create the ids for the element Types. */ public static int idCounter=1; /** * Creates a new element type in wasup, under the element <i>parent</i>. * * The folloging information is needed for the element creation: * * - elementType.elementTypeId * - name * - description * * @param name * Name of the type to be created. * * @param description * Description of the created type. * * @return * The Wasup ID of the newly created element. * * @throws IOException * @throws JSONException * */ public int createElementType(String name, String description) throws IOException, JSONException { log.info("Creating element type: " + name); Form form = new Form(); form.add("elementTypeId", String.valueOf(idCounter++)); form.add("name", name); form.add("description", description); Representation rep = form.getWebRepresentation(); String uri = DATA_PATH + ELEMENT_TYPES + "/"; Response response = post(uri, rep); if (response.getStatus().isSuccess()) { int ret=-1; if (response.getEntity().getMediaType().equals(MediaType.APPLICATION_JSON)) { JsonRepresentation jsonRep = new JsonRepresentation(response.getEntity()); JSONObject jo = jsonRep.toJsonArray().getJSONObject(0); int tableSize = jo.getInt("tableSize"); if (tableSize >= 1){ JSONObject joElement = jo.getJSONArray("rows").getJSONObject(0); ret = joElement.getInt("elementTypeId"); } } else if (response.getEntity().getMediaType().equals(MediaType.TEXT_XML)) { DomRepresentation domRep = new DomRepresentation(response.getEntity()); Document doc = domRep.getDocument(); NodeList nodeId = doc.getElementsByTagName("elementTypeId"); try { if (nodeId.getLength() <= 0) { throw new IOException("Wasup request succeed, but the response was empty"); } ret = Integer.parseInt(nodeId.item(0).getTextContent()); } catch (NumberFormatException nfe) { throw new IOException("Wasup request succeed, but the response could not be parsed: " + nfe.getMessage()); } } return ret; } else { throw new IOException("The wasup request didn't succeed; wrong server response: " + response.getStatus() ); } } /** * Create a measurement type associated to the provided element. For each measurement type * a range for this type must also be created, or no measure will be accepted. * * @param name * Human readable name of the measurement type. * * @param itemName * Fully quallyfied name or identifier of the measurement type. * * @param elementId * Wasup id of the element associated to the measurement type. * * @param unit * Engeenering unit associated to this measure type (e.g. GB, MHz, etc) * * @param description * Brief description of the measure. * * @return * The Wasup Id of the newly created measure type. * * @throws IOException * @throws JSONException */ public int createMeasurementType(String name, String itemName, String elementId, String unit, String description, String lowerBound, String upperBound) throws IOException, JSONException { log.info("Creating measure type: " + name); Form form = new Form(); form.add("element.elementId", elementId); form.add("name", name); form.add("itemName", itemName); form.add("valueType", "xs:decimal"); form.add("engineeringUnit", unit); form.add("analogDigital", "D"); form.add("description", description); form.add("minValue", lowerBound); form.add("maxValue", upperBound); Representation rep = form.getWebRepresentation(); String uri = DATA_PATH + MEASUREMENT_TYPES + "/"; Response response = post(uri, rep); if (response.getStatus().isSuccess()) { int ret=-1; if (response.getEntity().getMediaType().equals(MediaType.APPLICATION_JSON)) { JsonRepresentation jsonRep = new JsonRepresentation(response.getEntity()); JSONObject jo = jsonRep.toJsonArray().getJSONObject(0); int tableSize = jo.getInt("tableSize"); if (tableSize >= 1){ JSONObject joElement = jo.getJSONArray("rows").getJSONObject(0); ret = joElement.getInt("measurementTypeId"); } } else if (response.getEntity().getMediaType().equals(MediaType.TEXT_XML)) { DomRepresentation domRep = new DomRepresentation(response.getEntity()); Document doc = domRep.getDocument(); NodeList nodeId = doc.getElementsByTagName("measurementTypeId"); try { if (nodeId.getLength() <= 0) { throw new IOException("Wasup request succeed, but the response was empty"); } ret = Integer.parseInt(nodeId.item(0).getTextContent()); } catch (NumberFormatException nfe) { throw new IOException("Wasup request succeed, but the response could not be parsed: " + nfe.getMessage()); } } return ret; } else { throw new IOException("The wasup request didn't succeed; wrong server response: " + response.getStatus() ); } } /** * Create a new measurement range associated to the given measureTypeId. The range is * defined with its lower and upper bounds. * * @param measureTypeId * Wasup id of the measure type associated to this range. * * @param lowerBound * String representation of the double value acting as lower bound. * * @param upperBound * String representation of the double value acting as the upper bound. * * @throws IOException * @throws JSONException */ public void createMeasurementRange(String measureTypeId, String lowerBound, String upperBound) throws IOException, JSONException { log.info("Creating range for measurement type: " + measureTypeId); Form form = new Form(); form.add("registerRangeId", measureTypeId); form.add("measurementType.measurementTypeId", measureTypeId); form.add("lowerLimit", lowerBound); form.add("upperLimit", upperBound); Representation rep = form.getWebRepresentation(); String uri = DATA_PATH + MEASUREMENT_RANGES + "/"; Response response = post(uri, rep); if (response.getStatus().isSuccess()) { log.info("Measurement range successfully created."); } else { throw new IOException("The wasup request didn't succeed; wrong server response: " + response.getStatus() ); } } /** * Post a measure of the selected measure type to Wasup. * * @param name * Human readable name of the measurement type. * * @param itemName * Fully quallyfied name or identifier of the measurement type. * * @throws IOException * @throws JSONException */ public void postMeasure(String measureType, String value) throws IOException, JSONException { log.info("Posting measure for type: " + measureType + " value: " + value); Form form = new Form(); form.add("measurementType.itemName", measureType); form.add("qualityType.qualityTypeId", "192"); form.add("value", value); Representation rep = form.getWebRepresentation(); String uri = DATA_PATH + MEASURED_VALUES + "/"; Response response = post(uri, rep); if (response.getStatus().isSuccess()) { log.info("Measure posted to Wasup"); } else { log.warn("Wasup rejected the measure. Reason: " + response.getStatus()); } } }