/*******************************************************************************
* ===========================================================
* Ankush : Big Data Cluster Management Solution
* ===========================================================
*
* (C) Copyright 2014, by Impetus Technologies
*
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL v3) as
* published by the Free Software Foundation;
*
* This software 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
******************************************************************************/
package com.impetus.ankush.agent.cassandra;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import com.impetus.ankush.agent.Constant;
import com.impetus.ankush.agent.utils.AgentLogger;
import com.impetus.ankush.agent.utils.JmxUtil;
import com.impetus.ankush.agent.utils.TileInfo;
public class CassandraJMXData implements Serializable {
/** The log. */
private AgentLogger LOGGER = new AgentLogger(CassandraJMXData.class);
/** The tiles. */
private List<TileInfo> tiles = new ArrayList<TileInfo>();
/** The datacenters. */
private List<Datacenter> datacenters = new ArrayList<Datacenter>();
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;
/** The Constant ORG_APACHE_CASSANDRA. */
private static final String ORG_APACHE_CASSANDRA = "org.apache.cassandra.";
/** The Constant CASSANDRA_JMX_OBJECT_FAILUREDETECTOR. */
private static final String CASSANDRA_JMX_OBJECT_FAILUREDETECTOR = "FailureDetector";
/** The Constant CASSANDRA_JMX_SIMPLESTATES. */
private static final String CASSANDRA_JMX_ATTRIBUTE_SIMPLESTATES = "SimpleStates";
/** The Constant CASSANDRA_JMX_ATTRIBUTE_OWNERSHIP. */
private static final String CASSANDRA_JMX_ATTRIBUTE_OWNERSHIP = "Ownership";
/** The Constant CASSANDRA_JMX_ATTRIBUTE_GETRACK. */
private static final String CASSANDRA_JMX_ATTRIBUTE_GETRACK = "getRack";
/** The Constant CASSANDRA_JMX_ATTRIBUTE_GETDATACENTER. */
private static final String CASSANDRA_JMX_ATTRIBUTE_GETDATACENTER = "getDatacenter";
/** The Constant CASSANDRA_JMX_OBJECT_STORAGESERVICE. */
private static final String CASSANDRA_JMX_OBJECT_STORAGESERVICE = "StorageService";
/** The Constant CASSANDRA_JMX_OBJECT_ENDPOINT_SNITCH_INFO. */
private static final String CASSANDRA_JMX_OBJECT_ENDPOINT_SNITCH_INFO = "EndpointSnitchInfo";
/** The Constant CASSANDRA_JMX_OBJECT_DYNAMICENDPOINTSNITCH. */
private static final String CASSANDRA_JMX_OBJECT_DYNAMICENDPOINTSNITCH = "DynamicEndpointSnitch";
/** The Constant CASSANDRA_JMX_ENDPOINTSTATE. */
private static final String CASSANDRA_JMX_ATTRIBUTE_ENDPOINTSTATE = "getEndpointState";
/** The Constant CASSANDRA_JMX_ATTRIBUTE_LOADMAP. */
private static final String CASSANDRA_JMX_ATTRIBUTE_LOADMAP = "LoadMap";
private static final String CASSANDRA_JMX_ATTRIBUTE_HOSTIDMAP = "HostIdMap";
/** The Constant CASSANDRA_JMX_ATTRIBUTE_TOKENS. */
private static final String CASSANDRA_JMX_ATTRIBUTE_TOKENS = "getTokens";
/** The Constant CASSANDRA_JMX_ATTRIBUTE_LIVE_NODES. */
private static final String CASSANDRA_JMX_ATTRIBUTE_LIVE_NODES = "LiveNodes";
/** The Constant CASSANDRA_JMX_ATTRIBUTE_UNREACHABLE_NODES. */
private static final String CASSANDRA_JMX_ATTRIBUTE_UNREACHABLE_NODES = "UnreachableNodes";
/** The Constant CASSANDRA_JMX_ATTRIBUTE_KEYSPACES. */
private static final String CASSANDRA_JMX_ATTRIBUTE_KEYSPACES = "Keyspaces";
public CassandraJMXData(String hostname, Integer jmxPort) {
try {
createTopologyRing(hostname, jmxPort);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
/**
* Instantiates a new cassandra JMX data.
*/
public CassandraJMXData() {
// empty technology constructor.
}
private void createTopologyRing(String hostname, int jmxPort) {
JmxUtil jmxUtil = null;
try {
jmxUtil = new JmxUtil(hostname, jmxPort);
// connect to node
MBeanServerConnection connection = jmxUtil.connect();
if (connection != null) {
clusterTiles(jmxUtil);
Map<String, String> ownershipMap = new HashMap<String, String>();
Map<String, String> loadMap = new HashMap<String, String>();
Map<String, String> hostIdMap = new HashMap<String, String>();
Map<String, String> stateMap = new HashMap<String, String>();
// getting nodes
List<String> nodes = new ArrayList<String>();
ObjectName mObjNameStorageService = new ObjectName(
ORG_APACHE_CASSANDRA + "db:type="
+ CASSANDRA_JMX_OBJECT_STORAGESERVICE);
ObjectName mObjNameEndPointSnitchInfo = new ObjectName(
ORG_APACHE_CASSANDRA + "db:type="
+ CASSANDRA_JMX_OBJECT_ENDPOINT_SNITCH_INFO);
Object attributeLiveNodes = jmxUtil.getAttribute(
mObjNameStorageService,
CASSANDRA_JMX_ATTRIBUTE_LIVE_NODES);
Object attributeUnreachableNodes = jmxUtil.getAttribute(
mObjNameStorageService,
CASSANDRA_JMX_ATTRIBUTE_UNREACHABLE_NODES);
ObjectName mObjNameFailureDetector = new ObjectName(
ORG_APACHE_CASSANDRA + "net:type="
+ CASSANDRA_JMX_OBJECT_FAILUREDETECTOR);
// Getting ownership
Object attrOwnership = jmxUtil.getAttribute(
mObjNameStorageService,
CASSANDRA_JMX_ATTRIBUTE_OWNERSHIP);
LinkedHashMap ownership = (LinkedHashMap) attrOwnership;
DecimalFormat df = new DecimalFormat("###.##");
for (Object key : ownership.keySet()) {
ownershipMap.put(
key.toString().substring(
key.toString().lastIndexOf("/")),
String.valueOf(df.format(((Float) ownership
.get(key)) * 100)) + " %");
}
// Getting load
Object attrLoadMap = jmxUtil
.getAttribute(mObjNameStorageService,
CASSANDRA_JMX_ATTRIBUTE_LOADMAP);
Map<String, String> load = (HashMap<String, String>) attrLoadMap;
for (Map.Entry<String, String> entry : load.entrySet()) {
loadMap.put(entry.getKey().trim(), entry.getValue().trim());
}
// Getting hostID map
Object attrHostIdMap = jmxUtil.getAttribute(
mObjNameStorageService,
CASSANDRA_JMX_ATTRIBUTE_HOSTIDMAP);
Map<String, String> hostId = (HashMap<String, String>) attrHostIdMap;
for (Map.Entry<String, String> entry : hostId.entrySet()) {
hostIdMap.put(entry.getKey().trim(), entry.getValue()
.trim());
}
// Getting status
Object attrStatus = jmxUtil.getAttribute(
mObjNameFailureDetector,
CASSANDRA_JMX_ATTRIBUTE_SIMPLESTATES);
Map<String, String> status = (Map) attrStatus;
String nodeOwnership = new String();
for (Map.Entry<String, String> entry : status.entrySet()) {
stateMap.put(
entry.getKey().substring(
entry.getKey().lastIndexOf("/")),
entry.getValue());
}
nodes.addAll((List<String>) attributeLiveNodes);
nodes.addAll((List<String>) attributeUnreachableNodes);
List<Node> nodeList = new ArrayList<Node>();
// getting topology information
for (String cNodeConf : nodes) {
Object opParams[] = { cNodeConf };
String opSig[] = { String.class.getName() };
Node node = new Node();
Object result = connection.invoke(
mObjNameEndPointSnitchInfo,
CASSANDRA_JMX_ATTRIBUTE_GETRACK, opParams, opSig);
node.setRack((String) result);
result = connection.invoke(mObjNameEndPointSnitchInfo,
CASSANDRA_JMX_ATTRIBUTE_GETDATACENTER, opParams,
opSig);
node.setDataCenter((String) result);
node.setHost(cNodeConf);
node.setOwnership(ownershipMap.get(cNodeConf));
node.setLoad((loadMap.get(cNodeConf) != null
&& !loadMap.get(cNodeConf).isEmpty() ? loadMap
.get(cNodeConf) : "?"));
node.setStatus(stateMap.get(cNodeConf));
node.setHostId(hostIdMap.get(cNodeConf));
result = connection.invoke(mObjNameFailureDetector,
CASSANDRA_JMX_ATTRIBUTE_ENDPOINTSTATE, opParams,
opSig);
String strResult = (String) result;
List<String> sysoutList = new ArrayList<String>(
Arrays.asList(strResult.split("\n")));
for (String outData : sysoutList) {
List<String> paramList = new ArrayList<String>(
Arrays.asList(outData.split(":")));
String key = paramList.get(0).trim();
if (key.equals("STATUS")) {
node.setState((!paramList.get(1).trim().split(",")[0]
.isEmpty() ? paramList.get(1).trim()
.split(",")[0] : "?"));
break;
}
}
// Getting tokens
result = connection.invoke(mObjNameStorageService,
CASSANDRA_JMX_ATTRIBUTE_TOKENS, opParams, opSig);
List<String> tokens = (List<String>) result;
node.setTokenCount(String.valueOf(tokens.size()));
nodeList.add(node);
}
Map<String, Map<String, List<Node>>> datacenterMap = new HashMap<String, Map<String, List<Node>>>();
for (Node node : nodeList) {
if (!datacenterMap.containsKey(node.getDataCenter())) {
datacenterMap.put(node.getDataCenter(),
new HashMap<String, List<Node>>());
}
if (!datacenterMap.get(node.getDataCenter()).containsKey(
node.getRack())) {
datacenterMap.get(node.getDataCenter()).put(
node.getRack(), new ArrayList<Node>());
}
datacenterMap.get(node.getDataCenter()).get(node.getRack())
.add(node);
}
for (String dc : datacenterMap.keySet()) {
Datacenter datacenter = new Datacenter();
datacenter.setDatacenterName(dc);
List<Rack> racks = new ArrayList<Rack>();
for (String r : datacenterMap.get(dc).keySet()) {
Rack rack = new Rack();
rack.setRackName(r);
rack.setNodes(datacenterMap.get(dc).get(r));
racks.add(rack);
}
datacenter.setRacks(racks);
datacenters.add(datacenter);
}
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
jmxUtil.disconnect();
}
}
private void clusterTiles(JmxUtil jmxUtil) {
try {
ObjectName mObjNameStorageService = new ObjectName(
ORG_APACHE_CASSANDRA + "db:type="
+ CASSANDRA_JMX_OBJECT_STORAGESERVICE);
ObjectName mObjNameDynamicEndpointSnitch = new ObjectName(
ORG_APACHE_CASSANDRA + "db:type="
+ CASSANDRA_JMX_OBJECT_DYNAMICENDPOINTSNITCH);
// Get keyspace count
Object attrKeyspace = jmxUtil.getAttribute(mObjNameStorageService,
CASSANDRA_JMX_ATTRIBUTE_KEYSPACES);
int keyspaceCount = ((List<String>) attrKeyspace).size();
String keyspace = "Keyspace";
if (keyspaceCount > 1) {
keyspace = CASSANDRA_JMX_ATTRIBUTE_KEYSPACES;
}
// Create tiles
if (keyspaceCount > 0) {
tiles.add(getTile(String.valueOf(keyspaceCount), keyspace,
"Keyspace"));
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
private TileInfo getTile(String line1, String line2, String url) {
TileInfo tileInfo = null;
try {
tileInfo = new TileInfo();
tileInfo.setLine1(line1);
tileInfo.setLine2(line2);
tileInfo.setStatus(Constant.Tile.Status.NORMAL);
tileInfo.setUrl(url);
} catch (Exception e) {
e.printStackTrace();
}
return tileInfo;
}
/**
* Gets the tiles.
*
* @return the tiles
*/
public List<TileInfo> getTiles() {
return tiles;
}
/**
* Sets the tiles.
*
* @param tiles
* the tiles to set
*/
public void setTiles(List<TileInfo> tiles) {
this.tiles = tiles;
}
/**
* Gets the datacenters.
*
* @return the datacenters
*/
public List<Datacenter> getDatacenters() {
return datacenters;
}
/**
* Sets the datacenters.
*
* @param datacenters
* the datacenters to set
*/
public void setDatacenters(List<Datacenter> datacenters) {
this.datacenters = datacenters;
}
}