Repository: cassandra
Updated Branches:
  refs/heads/trunk 3747a6cd9 -> 42efbddd3


nodetool describecluster should be more informative

Patch by Preetika Tyagi, Reviewed by Ariel Weisberg for CASSANDRA-13853


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/42efbddd
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/42efbddd
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/42efbddd

Branch: refs/heads/trunk
Commit: 42efbddd3aa942e2f325b035ace05fc3755d021f
Parents: 3747a6c
Author: Ariel Weisberg <aweisb...@apple.com>
Authored: Wed Apr 11 15:18:17 2018 -0400
Committer: Ariel Weisberg <aweisb...@apple.com>
Committed: Thu Apr 12 16:08:27 2018 -0400

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 src/java/org/apache/cassandra/gms/Gossiper.java | 22 +++++
 .../org/apache/cassandra/gms/GossiperMBean.java |  4 +
 .../cassandra/service/StorageService.java       | 11 +++
 .../cassandra/service/StorageServiceMBean.java  |  5 ++
 .../org/apache/cassandra/tools/NodeProbe.java   | 10 +++
 .../tools/nodetool/DescribeCluster.java         | 94 +++++++++++++++++++-
 7 files changed, 144 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/42efbddd/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 754b9f3..0935434 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.0
+ * nodetool describecluster should be more informative (CASSANDRA-13853)
  * Compaction performance improvements (CASSANDRA-14261) 
  * Refactor Pair usage to avoid boxing ints/longs (CASSANDRA-14260)
  * Add options to nodetool tablestats to sort and limit output 
(CASSANDRA-13889)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/42efbddd/src/java/org/apache/cassandra/gms/Gossiper.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/gms/Gossiper.java 
b/src/java/org/apache/cassandra/gms/Gossiper.java
index 24b659b..0f3a5cd 100644
--- a/src/java/org/apache/cassandra/gms/Gossiper.java
+++ b/src/java/org/apache/cassandra/gms/Gossiper.java
@@ -32,6 +32,7 @@ import javax.management.ObjectName;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
 import com.google.common.util.concurrent.Uninterruptibles;
 
 import org.apache.cassandra.locator.InetAddressAndPort;
@@ -1732,6 +1733,27 @@ public class Gossiper implements 
IFailureDetectionEventListener, GossiperMBean
         return state != null ? state.getReleaseVersion() : null;
     }
 
+    public Map<String, List<String>> getReleaseVersionsWithPort()
+    {
+        Map<String, List<String>> results = new HashMap<String, 
List<String>>();
+        Iterable<InetAddressAndPort> allHosts = 
Iterables.concat(Gossiper.instance.getLiveMembers(), 
Gossiper.instance.getUnreachableMembers());
+
+        for (InetAddressAndPort host : allHosts)
+        {
+            CassandraVersion version = getReleaseVersion(host);
+            String stringVersion = version == null ? "" : version.toString();
+            List<String> hosts = results.get(stringVersion);
+            if (hosts == null)
+            {
+                hosts = new ArrayList<>();
+                results.put(stringVersion, hosts);
+            }
+            hosts.add(host.getHostAddress(true));
+        }
+
+        return results;
+    }
+
     @Nullable
     public UUID getSchemaVersion(InetAddressAndPort ep)
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/42efbddd/src/java/org/apache/cassandra/gms/GossiperMBean.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/gms/GossiperMBean.java 
b/src/java/org/apache/cassandra/gms/GossiperMBean.java
index 1b116e1..92df2cd 100644
--- a/src/java/org/apache/cassandra/gms/GossiperMBean.java
+++ b/src/java/org/apache/cassandra/gms/GossiperMBean.java
@@ -19,6 +19,7 @@ package org.apache.cassandra.gms;
 
 import java.net.UnknownHostException;
 import java.util.List;
+import java.util.Map;
 
 public interface GossiperMBean
 {
@@ -34,4 +35,7 @@ public interface GossiperMBean
 
     public List<String> getSeeds();
 
+    /** Returns each node's database release version */
+    public Map<String, List<String>> getReleaseVersionsWithPort();
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cassandra/blob/42efbddd/src/java/org/apache/cassandra/service/StorageService.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/StorageService.java 
b/src/java/org/apache/cassandra/service/StorageService.java
index 91206c1..e5911f3 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -79,6 +79,7 @@ import org.apache.cassandra.repair.messages.RepairOption;
 import org.apache.cassandra.schema.CompactionParams.TombstoneOption;
 import org.apache.cassandra.schema.KeyspaceMetadata;
 import org.apache.cassandra.schema.MigrationManager;
+import org.apache.cassandra.schema.ReplicationParams;
 import org.apache.cassandra.schema.Schema;
 import org.apache.cassandra.schema.SchemaConstants;
 import org.apache.cassandra.schema.SchemaPullVerbHandler;
@@ -2968,6 +2969,16 @@ public class StorageService extends 
NotificationBroadcasterSupport implements IE
         return Schema.instance.getVersion().toString();
     }
 
+    public String getKeyspaceReplicationInfo(String keyspaceName)
+    {
+        Keyspace keyspaceInstance = 
Schema.instance.getKeyspaceInstance(keyspaceName);
+        if (keyspaceInstance == null)
+            throw new IllegalArgumentException(); // ideally should never 
happen
+        ReplicationParams replicationParams = 
keyspaceInstance.getMetadata().params.replication;
+        String replicationInfo = replicationParams.klass.getSimpleName() + " " 
+ replicationParams.options.toString();
+        return replicationInfo;
+    }
+
     @Deprecated
     public List<String> getLeavingNodes()
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/42efbddd/src/java/org/apache/cassandra/service/StorageServiceMBean.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/StorageServiceMBean.java 
b/src/java/org/apache/cassandra/service/StorageServiceMBean.java
index 0676419..206a37b 100644
--- a/src/java/org/apache/cassandra/service/StorageServiceMBean.java
+++ b/src/java/org/apache/cassandra/service/StorageServiceMBean.java
@@ -100,6 +100,11 @@ public interface StorageServiceMBean extends 
NotificationEmitter
      */
     public String getSchemaVersion();
 
+    /**
+     * Fetch the replication factor for a given keyspace.
+     * @return An integer that represents replication factor for the given 
keyspace.
+     */
+    public String getKeyspaceReplicationInfo(String keyspaceName);
 
     /**
      * Get the list of all data file locations from conf

http://git-wip-us.apache.org/repos/asf/cassandra/blob/42efbddd/src/java/org/apache/cassandra/tools/NodeProbe.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/NodeProbe.java 
b/src/java/org/apache/cassandra/tools/NodeProbe.java
index 1bace2e..04a5781 100644
--- a/src/java/org/apache/cassandra/tools/NodeProbe.java
+++ b/src/java/org/apache/cassandra/tools/NodeProbe.java
@@ -387,6 +387,11 @@ public class NodeProbe implements AutoCloseable
         ssProxy.forceKeyspaceFlush(keyspaceName, tableNames);
     }
 
+    public String getKeyspaceReplicationInfo(String keyspaceName)
+    {
+        return ssProxy.getKeyspaceReplicationInfo(keyspaceName);
+    }
+
     public void repairAsync(final PrintStream out, final String keyspace, 
Map<String, String> options) throws IOException
     {
         RepairRunner runner = new RepairRunner(out, ssProxy, keyspace, 
options);
@@ -906,6 +911,11 @@ public class NodeProbe implements AutoCloseable
         return spProxy;
     }
 
+    public GossiperMBean getGossProxy()
+    {
+        return gossProxy;
+    }
+
     public String getEndpoint()
     {
         Map<String, String> hostIdToEndpoint = ssProxy.getHostIdToEndpoint();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/42efbddd/src/java/org/apache/cassandra/tools/nodetool/DescribeCluster.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/nodetool/DescribeCluster.java 
b/src/java/org/apache/cassandra/tools/nodetool/DescribeCluster.java
index ed91b8b..da02db6 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/DescribeCluster.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/DescribeCluster.java
@@ -17,19 +17,29 @@
  */
 package org.apache.cassandra.tools.nodetool;
 
-import static java.lang.String.format;
-import io.airlift.airline.Command;
-
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.SortedMap;
+
+import com.google.common.collect.ArrayListMultimap;
 
+import io.airlift.airline.Command;
 import org.apache.cassandra.locator.DynamicEndpointSnitch;
+import org.apache.cassandra.locator.InetAddressAndPort;
 import org.apache.cassandra.tools.NodeProbe;
+import org.apache.cassandra.tools.NodeTool;
 import org.apache.cassandra.tools.NodeTool.NodeToolCmd;
 
+import static java.lang.String.format;
+
 @Command(name = "describecluster", description = "Print the name, snitch, 
partitioner and schema version of a cluster")
 public class DescribeCluster extends NodeToolCmd
 {
+    private boolean resolveIp = false;
+    private String keyspace = null;
+    private Collection<String> joiningNodes, leavingNodes, movingNodes, 
liveNodes, unreachableNodes;
+
     @Override
     public void execute(NodeProbe probe)
     {
@@ -54,5 +64,83 @@ public class DescribeCluster extends NodeToolCmd
         {
             System.out.println(format("\t\t%s: %s%n", version, 
schemaVersions.get(version)));
         }
+
+        // Collect status information of all nodes
+        boolean withPort = true;
+        joiningNodes = probe.getJoiningNodes(withPort);
+        leavingNodes = probe.getLeavingNodes(withPort);
+        movingNodes = probe.getMovingNodes(withPort);
+        liveNodes = probe.getLiveNodes(withPort);
+        unreachableNodes = probe.getUnreachableNodes(withPort);
+
+        // Get the list of all keyspaces
+        List<String> keyspaces = probe.getKeyspaces();
+
+        System.out.println("Stats for all nodes:");
+        System.out.println("\tLive: " + liveNodes.size());
+        System.out.println("\tJoining: " + joiningNodes.size());
+        System.out.println("\tMoving: " + movingNodes.size());
+        System.out.println("\tLeaving: " + leavingNodes.size());
+        System.out.println("\tUnreachable: " + unreachableNodes.size());
+
+        Map<String, String> tokensToEndpoints = 
probe.getTokenToEndpointMap(withPort);
+        Map<String, Float> ownerships = null;
+        try
+        {
+            ownerships = probe.effectiveOwnershipWithPort(keyspace);
+        }
+        catch (IllegalStateException ex)
+        {
+            ownerships = probe.getOwnershipWithPort();
+            System.out.println("Error: " + ex.getMessage());
+        }
+        catch (IllegalArgumentException ex)
+        {
+            System.out.println("%nError: " + ex.getMessage());
+            System.exit(1);
+        }
+
+        SortedMap<String, SetHostStatWithPort> dcs = 
NodeTool.getOwnershipByDcWithPort(probe, resolveIp, tokensToEndpoints, 
ownerships);
+
+        System.out.println("\nData Centers: ");
+        for (Map.Entry<String, SetHostStatWithPort> dc : dcs.entrySet())
+        {
+            System.out.print("\t" + dc.getKey());
+
+            ArrayListMultimap<InetAddressAndPort, HostStatWithPort> 
hostToTokens = ArrayListMultimap.create();
+            for (HostStatWithPort stat : dc.getValue())
+                hostToTokens.put(stat.endpoint, stat);
+
+            int totalNodes = 0; // total number of nodes in a datacenter
+            int downNodes = 0; // number of down nodes in a datacenter
+
+            for (InetAddressAndPort endpoint : hostToTokens.keySet())
+            {
+                totalNodes++;
+                if (unreachableNodes.contains(endpoint.toString()))
+                    downNodes++;
+            }
+            System.out.print(" #Nodes: " + totalNodes);
+            System.out.println(" #Down: " + downNodes);
+        }
+
+        // display database version for each node
+        System.out.println("\nDatabase versions:");
+        Map<String, List<String>> databaseVersions = 
probe.getGossProxy().getReleaseVersionsWithPort();
+        for (String version : databaseVersions.keySet())
+        {
+            System.out.println(format("\t%s: %s%n", version, 
databaseVersions.get(version)));
+        }
+
+        System.out.println("Keyspaces:");
+        for (String keyspaceName : keyspaces)
+        {
+            String replicationInfo = 
probe.getKeyspaceReplicationInfo(keyspaceName);
+            if (replicationInfo == null)
+            {
+                System.out.println("something went wrong for keyspace: " + 
keyspaceName);
+            }
+            System.out.println("\t" + keyspaceName + " -> Replication class: " 
+ replicationInfo);
+        }
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to