This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 8c97e1e584 HDDS-7329. Extend ozone admin datanode usageinfo and list 
info to accept hostname parameter (#3835)
8c97e1e584 is described below

commit 8c97e1e5840882608f6bbb8a6963fb24ea885364
Author: Christos Bisias <[email protected]>
AuthorDate: Mon Nov 27 19:44:23 2023 +0200

    HDDS-7329. Extend ozone admin datanode usageinfo and list info to accept 
hostname parameter (#3835)
    
    Co-authored-by: Doroszlai, Attila <[email protected]>
---
 .../apache/hadoop/hdds/scm/client/ScmClient.java   |  6 +-
 .../protocol/StorageContainerLocationProtocol.java |  6 +-
 ...inerLocationProtocolClientSideTranslatorPB.java |  6 +-
 .../hadoop/hdds/scm/node/SCMNodeManager.java       | 97 +++++++++++-----------
 .../hdds/scm/server/SCMClientProtocolServer.java   | 10 +--
 .../hadoop/hdds/scm/node/TestSCMNodeManager.java   | 59 +++++--------
 .../hdds/scm/cli/ContainerOperationClient.java     |  4 +-
 .../hdds/scm/cli/datanode/ListInfoSubcommand.java  |  9 ++
 .../hdds/scm/cli/datanode/UsageInfoSubcommand.java | 20 +++--
 .../src/main/smoketest/admincli/datanode.robot     | 60 +++++++++----
 10 files changed, 150 insertions(+), 127 deletions(-)

diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java
 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java
index 179bf489cb..b03cead27e 100644
--- 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java
+++ 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java
@@ -400,15 +400,15 @@ public interface ScmClient extends Closeable {
   int resetDeletedBlockRetryCount(List<Long> txIDs) throws IOException;
 
   /**
-   * Get usage information of datanode by ipaddress or uuid.
+   * Get usage information of datanode by address or uuid.
    *
-   * @param ipaddress datanode ipaddress String
+   * @param address datanode address String
    * @param uuid datanode uuid String
    * @return List of DatanodeUsageInfoProto. Each element contains info such as
    * capacity, SCMused, and remaining space.
    * @throws IOException
    */
-  List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(String 
ipaddress,
+  List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(String address,
                                                                String uuid)
       throws IOException;
 
diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java
 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java
index 7cdb7bf7d5..b587cc924b 100644
--- 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java
+++ 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java
@@ -410,9 +410,9 @@ public interface StorageContainerLocationProtocol extends 
Closeable {
   boolean getContainerBalancerStatus() throws IOException;
 
   /**
-   * Get Datanode usage information by ip or uuid.
+   * Get Datanode usage information by ip or hostname or uuid.
    *
-   * @param ipaddress datanode IP address String
+   * @param address datanode IP address or Hostname String
    * @param uuid datanode UUID String
    * @param clientVersion Client's version number
    * @return List of DatanodeUsageInfoProto. Each element contains info such as
@@ -421,7 +421,7 @@ public interface StorageContainerLocationProtocol extends 
Closeable {
    * @see org.apache.hadoop.ozone.ClientVersion
    */
   List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(
-      String ipaddress, String uuid, int clientVersion) throws IOException;
+      String address, String uuid, int clientVersion) throws IOException;
 
   /**
    * Get usage information of most or least used datanodes.
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java
index 79ea966933..80db9047ba 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java
@@ -932,7 +932,7 @@ public final class 
StorageContainerLocationProtocolClientSideTranslatorPB
   /**
    * Builds request for datanode usage information and receives response.
    *
-   * @param ipaddress Address String
+   * @param address Address String
    * @param uuid UUID String
    * @return List of DatanodeUsageInfoProto. Each element contains info such as
    * capacity, SCMUsed, and remaining space.
@@ -940,11 +940,11 @@ public final class 
StorageContainerLocationProtocolClientSideTranslatorPB
    */
   @Override
   public List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(
-      String ipaddress, String uuid, int clientVersion) throws IOException {
+      String address, String uuid, int clientVersion) throws IOException {
 
     DatanodeUsageInfoRequestProto request =
         DatanodeUsageInfoRequestProto.newBuilder()
-            .setIpaddress(ipaddress)
+            .setIpaddress(address)
             .setUuid(uuid)
             .build();
 
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java
index 0d323b996c..3103d5a7d4 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/node/SCMNodeManager.java
@@ -82,6 +82,7 @@ import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
@@ -379,19 +380,15 @@ public class SCMNodeManager implements NodeManager {
       datanodeDetails.setIpAddress(dnAddress.getHostAddress());
     }
 
-    String dnsName;
-    String networkLocation;
+    final String ipAddress = datanodeDetails.getIpAddress();
+    final String hostName = datanodeDetails.getHostName();
     datanodeDetails.setNetworkName(datanodeDetails.getUuidString());
-    if (useHostname) {
-      dnsName = datanodeDetails.getHostName();
-    } else {
-      dnsName = datanodeDetails.getIpAddress();
-    }
-    networkLocation = nodeResolve(dnsName);
+    String networkLocation = nodeResolve(useHostname ? hostName : ipAddress);
     if (networkLocation != null) {
       datanodeDetails.setNetworkLocation(networkLocation);
     }
 
+    final UUID uuid = datanodeDetails.getUuid();
     if (!isNodeRegistered(datanodeDetails)) {
       try {
         clusterMap.add(datanodeDetails);
@@ -399,14 +396,14 @@ public class SCMNodeManager implements NodeManager {
         // Check that datanode in nodeStateManager has topology parent set
         DatanodeDetails dn = nodeStateManager.getNode(datanodeDetails);
         Preconditions.checkState(dn.getParent() != null);
-        addToDnsToUuidMap(dnsName, datanodeDetails.getUuid());
+        addToDnsToUuidMap(uuid, ipAddress, hostName);
         // Updating Node Report, as registration is successful
         processNodeReport(datanodeDetails, nodeReport);
-        LOG.info("Registered Data node : {}", datanodeDetails.toDebugString());
+        LOG.info("Registered datanode: {}", datanodeDetails.toDebugString());
         scmNodeEventPublisher.fireEvent(SCMEvents.NEW_NODE, datanodeDetails);
       } catch (NodeAlreadyExistsException e) {
         if (LOG.isTraceEnabled()) {
-          LOG.trace("Datanode is already registered. Datanode: {}",
+          LOG.trace("Datanode is already registered: {}",
               datanodeDetails);
         }
       } catch (NodeNotFoundException e) {
@@ -416,32 +413,20 @@ public class SCMNodeManager implements NodeManager {
     } else {
       // Update datanode if it is registered but the ip or hostname changes
       try {
-        final DatanodeInfo datanodeInfo =
-                nodeStateManager.getNode(datanodeDetails);
-        if (!datanodeInfo.getIpAddress().equals(datanodeDetails.getIpAddress())
-                || !datanodeInfo.getHostName()
-                .equals(datanodeDetails.getHostName())) {
-          LOG.info("Updating data node {} from {} to {}",
+        final DatanodeInfo oldNode = nodeStateManager.getNode(datanodeDetails);
+        if (updateDnsToUuidMap(oldNode.getHostName(), oldNode.getIpAddress(),
+            hostName, ipAddress, uuid)) {
+          LOG.info("Updating datanode {} from {} to {}",
                   datanodeDetails.getUuidString(),
-                  datanodeInfo,
+                  oldNode,
                   datanodeDetails);
-          clusterMap.update(datanodeInfo, datanodeDetails);
-
-          String oldDnsName;
-          if (useHostname) {
-            oldDnsName = datanodeInfo.getHostName();
-          } else {
-            oldDnsName = datanodeInfo.getIpAddress();
-          }
-          updateDnsToUuidMap(oldDnsName, dnsName, datanodeDetails.getUuid());
-
+          clusterMap.update(oldNode, datanodeDetails);
           nodeStateManager.updateNode(datanodeDetails, layoutInfo);
           DatanodeDetails dn = nodeStateManager.getNode(datanodeDetails);
           Preconditions.checkState(dn.getParent() != null);
           processNodeReport(datanodeDetails, nodeReport);
-          LOG.info("Updated Datanode to: {}", dn);
-          scmNodeEventPublisher
-                  .fireEvent(SCMEvents.NODE_ADDRESS_UPDATE, dn);
+          LOG.info("Updated datanode to: {}", dn);
+          scmNodeEventPublisher.fireEvent(SCMEvents.NODE_ADDRESS_UPDATE, dn);
         }
       } catch (NodeNotFoundException e) {
         LOG.error("Cannot find datanode {} from nodeStateManager",
@@ -458,31 +443,49 @@ public class SCMNodeManager implements NodeManager {
   /**
    * Add an entry to the dnsToUuidMap, which maps hostname / IP to the DNs
    * running on that host. As each address can have many DNs running on it,
-   * this is a one to many mapping.
+   * and each host can have multiple addresses,
+   * this is a many to many mapping.
    *
-   * @param addr the hostname or IP of the node
    * @param uuid the UUID of the registered node.
+   * @param addresses hostname and/or IP of the node
    */
-  private synchronized void addToDnsToUuidMap(String addr, UUID uuid) {
-    dnsToUuidMap.computeIfAbsent(addr, k -> ConcurrentHashMap.newKeySet())
-        .add(uuid);
+  private synchronized void addToDnsToUuidMap(UUID uuid, String... addresses) {
+    for (String addr : addresses) {
+      if (!Strings.isNullOrEmpty(addr)) {
+        dnsToUuidMap.computeIfAbsent(addr, k -> ConcurrentHashMap.newKeySet())
+            .add(uuid);
+      }
+    }
   }
 
-  private synchronized void removeFromDnsToUuidMap(String addr, UUID uuid) {
-    Set<UUID> dnSet = dnsToUuidMap.get(addr);
-    if (dnSet != null && dnSet.remove(uuid) && dnSet.isEmpty()) {
-      dnsToUuidMap.remove(addr);
+  private synchronized void removeFromDnsToUuidMap(UUID uuid, String address) {
+    if (address != null) {
+      Set<UUID> dnSet = dnsToUuidMap.get(address);
+      if (dnSet != null && dnSet.remove(uuid) && dnSet.isEmpty()) {
+        dnsToUuidMap.remove(address);
+      }
     }
   }
 
-  private synchronized void updateDnsToUuidMap(
-      String oldDnsName, String newDnsName, UUID uuid) {
-    Preconditions.checkNotNull(oldDnsName, "old address == null");
-    Preconditions.checkNotNull(newDnsName, "new address == null");
-    if (!oldDnsName.equals(newDnsName)) {
-      removeFromDnsToUuidMap(oldDnsName, uuid);
-      addToDnsToUuidMap(newDnsName, uuid);
+  private boolean updateDnsToUuidMap(
+      String oldHostName, String oldIpAddress,
+      String newHostName, String newIpAddress,
+      UUID uuid) {
+    final boolean ipChanged = !Objects.equals(oldIpAddress, newIpAddress);
+    final boolean hostNameChanged = !Objects.equals(oldHostName, newHostName);
+    if (ipChanged || hostNameChanged) {
+      synchronized (this) {
+        if (ipChanged) {
+          removeFromDnsToUuidMap(uuid, oldIpAddress);
+          addToDnsToUuidMap(uuid, newIpAddress);
+        }
+        if (hostNameChanged) {
+          removeFromDnsToUuidMap(uuid, oldHostName);
+          addToDnsToUuidMap(uuid, newHostName);
+        }
+      }
     }
+    return ipChanged || hostNameChanged;
   }
 
   /**
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
index 21ab8a2501..315be62b87 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
@@ -1106,9 +1106,9 @@ public class SCMClientProtocolServer implements
 
   /**
    * Get Datanode usage info such as capacity, SCMUsed, and remaining by ip
-   * or uuid.
+   * or hostname or uuid.
    *
-   * @param ipaddress Datanode Address String
+   * @param address Datanode Address String
    * @param uuid Datanode UUID String
    * @return List of DatanodeUsageInfoProto. Each element contains usage info
    * such as capacity, SCMUsed, and remaining space.
@@ -1116,7 +1116,7 @@ public class SCMClientProtocolServer implements
    */
   @Override
   public List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(
-      String ipaddress, String uuid, int clientVersion) throws IOException {
+      String address, String uuid, int clientVersion) throws IOException {
 
     // check admin authorisation
     try {
@@ -1130,8 +1130,8 @@ public class SCMClientProtocolServer implements
     List<DatanodeDetails> nodes = new ArrayList<>();
     if (!Strings.isNullOrEmpty(uuid)) {
       nodes.add(scm.getScmNodeManager().getNodeByUuid(uuid));
-    } else if (!Strings.isNullOrEmpty(ipaddress)) {
-      nodes = scm.getScmNodeManager().getNodesByAddress(ipaddress);
+    } else if (!Strings.isNullOrEmpty(address)) {
+      nodes = scm.getScmNodeManager().getNodesByAddress(address);
     } else {
       throw new IOException(
           "Could not get datanode with the specified parameters."
diff --git 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestSCMNodeManager.java
 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestSCMNodeManager.java
index e75f6e6f41..d13cd8952a 100644
--- 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestSCMNodeManager.java
+++ 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/node/TestSCMNodeManager.java
@@ -1794,26 +1794,6 @@ public class TestSCMNodeManager {
     }
   }
 
-  /**
-   * Test add node into network topology during node register. Datanode
-   * uses Ip address to resolve network location.
-   */
-  @Test
-  public void testScmRegisterNodeWithIpAddress()
-      throws IOException, InterruptedException, AuthenticationException {
-    testScmRegisterNodeWithNetworkTopology(false);
-  }
-
-  /**
-   * Test add node into network topology during node register. Datanode
-   * uses hostname to resolve network location.
-   */
-  @Test
-  public void testScmRegisterNodeWithHostname()
-      throws IOException, InterruptedException, AuthenticationException {
-    testScmRegisterNodeWithNetworkTopology(true);
-  }
-
   /**
    * Test add node into a 4-layer network topology during node register.
    */
@@ -1859,11 +1839,15 @@ public class TestSCMNodeManager {
     }
   }
 
-  private void testScmRegisterNodeWithNetworkTopology(boolean useHostname)
+  @ParameterizedTest
+  @ValueSource(booleans = {true, false})
+  void testScmRegisterNodeWithNetworkTopology(boolean useHostname)
       throws IOException, InterruptedException, AuthenticationException {
     OzoneConfiguration conf = getConf();
     conf.setTimeDuration(OZONE_SCM_HEARTBEAT_PROCESS_INTERVAL, 1000,
         MILLISECONDS);
+    conf.setBoolean(DFSConfigKeysLegacy.DFS_DATANODE_USE_DN_HOSTNAME,
+        useHostname);
 
     // create table mapping file
     String[] hostNames = {"host1", "host2", "host3", "host4"};
@@ -1875,9 +1859,7 @@ public class TestSCMNodeManager {
     conf.set(NET_TOPOLOGY_NODE_SWITCH_MAPPING_IMPL_KEY,
         "org.apache.hadoop.net.TableMapping");
     conf.set(NET_TOPOLOGY_TABLE_MAPPING_FILE_KEY, mapFile);
-    if (useHostname) {
-      conf.set(DFSConfigKeysLegacy.DFS_DATANODE_USE_DN_HOSTNAME, "true");
-    }
+
     final int nodeCount = hostNames.length;
     // use default IP address to resolve node
     try (SCMNodeManager nodeManager = createNodeManager(conf)) {
@@ -1899,13 +1881,11 @@ public class TestSCMNodeManager {
           assertEquals("/rack1", node.getNetworkLocation()));
 
       // test get node
-      if (useHostname) {
-        Arrays.stream(hostNames).forEach(hostname -> assertNotEquals(0,
-            nodeManager.getNodesByAddress(hostname).size()));
-      } else {
-        Arrays.stream(ipAddress).forEach(ip -> assertNotEquals(0,
-            nodeManager.getNodesByAddress(ip).size()));
-      }
+      Arrays.stream(hostNames).forEach(hostname -> assertNotEquals(0,
+          nodeManager.getNodesByAddress(hostname).size()));
+
+      Arrays.stream(ipAddress).forEach(ip -> assertNotEquals(0,
+          nodeManager.getNodesByAddress(ip).size()));
     }
   }
 
@@ -1998,15 +1978,14 @@ public class TestSCMNodeManager {
       }
       // test get node
       assertEquals(0, nodeManager.getNodesByAddress(null).size());
-      if (useHostname) {
-        assertEquals(2, nodeManager.getNodesByAddress("host1").size());
-        assertEquals(1, nodeManager.getNodesByAddress("host2").size());
-        assertEquals(0, nodeManager.getNodesByAddress("unknown").size());
-      } else {
-        assertEquals(2, nodeManager.getNodesByAddress("1.2.3.4").size());
-        assertEquals(1, nodeManager.getNodesByAddress("2.3.4.5").size());
-        assertEquals(0, nodeManager.getNodesByAddress("1.9.8.7").size());
-      }
+
+      assertEquals(2, nodeManager.getNodesByAddress("host1").size());
+      assertEquals(1, nodeManager.getNodesByAddress("host2").size());
+      assertEquals(0, nodeManager.getNodesByAddress("unknown").size());
+
+      assertEquals(2, nodeManager.getNodesByAddress("1.2.3.4").size());
+      assertEquals(1, nodeManager.getNodesByAddress("2.3.4.5").size());
+      assertEquals(0, nodeManager.getNodesByAddress("1.9.8.7").size());
     }
   }
 
diff --git 
a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/ContainerOperationClient.java
 
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/ContainerOperationClient.java
index ee33c6b0e7..13e8aa77af 100644
--- 
a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/ContainerOperationClient.java
+++ 
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/ContainerOperationClient.java
@@ -519,8 +519,8 @@ public class ContainerOperationClient implements ScmClient {
 
   @Override
   public List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(
-      String ipaddress, String uuid) throws IOException {
-    return storageContainerLocationClient.getDatanodeUsageInfo(ipaddress,
+      String address, String uuid) throws IOException {
+    return storageContainerLocationClient.getDatanodeUsageInfo(address,
         uuid, ClientVersion.CURRENT_VERSION);
   }
 
diff --git 
a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/datanode/ListInfoSubcommand.java
 
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/datanode/ListInfoSubcommand.java
index 08daa1fa71..db12ee2aac 100644
--- 
a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/datanode/ListInfoSubcommand.java
+++ 
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/datanode/ListInfoSubcommand.java
@@ -52,6 +52,11 @@ public class ListInfoSubcommand extends ScmSubcommand {
       defaultValue = "")
   private String uuid;
 
+  @CommandLine.Option(names = {"--hostname"},
+      description = "Show info by datanode hostname.",
+      defaultValue = "")
+  private String hostname;
+
   @CommandLine.Option(names = {"--operational-state"},
       description = "Show info by datanode NodeOperationalState(" +
           "IN_SERVICE, " +
@@ -82,6 +87,10 @@ public class ListInfoSubcommand extends ScmSubcommand {
       allNodes = allNodes.filter(p -> p.getDatanodeDetails().getIpAddress()
           .compareToIgnoreCase(ipaddress) == 0);
     }
+    if (!Strings.isNullOrEmpty(hostname)) {
+      allNodes = allNodes.filter(p -> p.getDatanodeDetails().getHostName()
+          .compareToIgnoreCase(hostname) == 0);
+    }
     if (!Strings.isNullOrEmpty(uuid)) {
       allNodes = allNodes.filter(p ->
           p.getDatanodeDetails().getUuidString().equals(uuid));
diff --git 
a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/datanode/UsageInfoSubcommand.java
 
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/datanode/UsageInfoSubcommand.java
index 5bd6b42b44..d46513b24b 100644
--- 
a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/datanode/UsageInfoSubcommand.java
+++ 
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/datanode/UsageInfoSubcommand.java
@@ -45,7 +45,7 @@ import java.util.stream.Collectors;
     name = "usageinfo",
     description = "List usage information " +
         "(such as Capacity, SCMUsed, Remaining) of a datanode by IP address " +
-        "or UUID",
+        "or Host name or UUID",
     mixinStandardHelpOptions = true,
     versionProvider = HddsVersionProvider.class)
 public class UsageInfoSubcommand extends ScmSubcommand {
@@ -61,9 +61,10 @@ public class UsageInfoSubcommand extends ScmSubcommand {
   private ExclusiveArguments exclusiveArguments;
 
   private static class ExclusiveArguments {
-    @CommandLine.Option(names = {"--ip"}, paramLabel = "IP", description =
-        "Show info by datanode ip address.", defaultValue = "")
-    private String ipaddress;
+    @CommandLine.Option(names = {"--address"}, paramLabel = "ADDRESS",
+        description = "Show info by datanode ip or hostname address.",
+        defaultValue = "")
+    private String address;
 
     @CommandLine.Option(names = {"--uuid"}, paramLabel = "UUID", description =
         "Show info by datanode UUID.", defaultValue = "")
@@ -98,10 +99,10 @@ public class UsageInfoSubcommand extends ScmSubcommand {
       throw new IOException("Count must be an integer greater than 0.");
     }
 
-    // fetch info by ip or uuid
-    if (!Strings.isNullOrEmpty(exclusiveArguments.ipaddress) ||
+    // fetch info by ip or hostname or uuid
+    if (!Strings.isNullOrEmpty(exclusiveArguments.address) ||
         !Strings.isNullOrEmpty(exclusiveArguments.uuid)) {
-      infoList = scmClient.getDatanodeUsageInfo(exclusiveArguments.ipaddress,
+      infoList = scmClient.getDatanodeUsageInfo(exclusiveArguments.address,
           exclusiveArguments.uuid);
     } else { // get info of most used or least used nodes
       infoList = scmClient.getDatanodeUsageInfo(exclusiveArguments.mostUsed,
@@ -129,8 +130,9 @@ public class UsageInfoSubcommand extends ScmSubcommand {
   private void printInfo(DatanodeUsage info) {
     System.out.printf("%-13s: %s %n", "UUID",
         info.getDatanodeDetails().getUuid());
-    System.out.printf("%-13s: %s (%s) %n", "IP Address",
-        info.getDatanodeDetails().getIpAddress(),
+    System.out.printf("%-13s: %s %n", "IP Address",
+        info.getDatanodeDetails().getIpAddress());
+    System.out.printf("%-13s: %s %n", "Hostname",
         info.getDatanodeDetails().getHostName());
     // print capacity in a readable format
     System.out.printf("%-13s: %s (%s) %n", "Capacity", info.getCapacity()
diff --git a/hadoop-ozone/dist/src/main/smoketest/admincli/datanode.robot 
b/hadoop-ozone/dist/src/main/smoketest/admincli/datanode.robot
index 340d3de825..b4ee5b9529 100644
--- a/hadoop-ozone/dist/src/main/smoketest/admincli/datanode.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/admincli/datanode.robot
@@ -17,8 +17,18 @@
 Documentation       Test ozone admin datanode command
 Library             BuiltIn
 Resource            ../commonlib.robot
+Suite Setup         Run Keyword if    '${SECURITY_ENABLED}' == 'true'    Kinit 
test user     testuser     testuser.keytab
 Test Timeout        5 minutes
 
+*** Keywords ***
+Assert Output
+    [arguments]    ${output}    ${expected}    ${uuid}
+    Should contain         ${output}    Datanode: ${uuid}
+    ${datanodes} =         Get Lines Containing String    ${output}    
Datanode:
+    @{lines} =          Split To Lines   ${datanodes}
+    ${count} =          Get Length   ${lines}
+    Should Be Equal As Integers    ${count}    ${expected}
+
 *** Test Cases ***
 List datanodes
                         Execute      ozone admin datanode list > datanode.list
@@ -29,31 +39,51 @@ List datanodes
 Filter list by UUID
     ${uuid} =           Execute      grep '^Datanode:' datanode.list | head -1 
| awk '{ print \$2 }'
     ${output} =         Execute      ozone admin datanode list --id "${uuid}"
-    Should contain      ${output}    Datanode: ${uuid}
-    ${datanodes} =      Get Lines Containing String    ${output}    Datanode:
-    @{lines} =          Split To Lines   ${datanodes}
-    ${count} =          Get Length   ${lines}
-    Should Be Equal As Integers    ${count}    1
+    Assert Output       ${output}    1    ${uuid}
+
+Filter list by Ip address
+    ${uuid} =           Execute      grep '^Datanode:' datanode.list | head -1 
| awk '{ print \$2 }'
+    ${ip} =             Execute      grep '^Datanode:' datanode.list | head -1 
| awk '{ print \$3 }' | awk -F '[/]' '{ print \$3 }'
+    ${output} =         Execute      ozone admin datanode list --ip "${ip}"
+    Assert Output       ${output}    1    ${uuid}
+
+Filter list by Hostname
+    ${uuid} =           Execute      grep '^Datanode:' datanode.list | head -1 
| awk '{ print \$2 }'
+    ${hostname} =       Execute      grep '^Datanode:' datanode.list | head -1 
| awk '{ print \$3 }' | awk -F '[/]' '{ print \$4 }'
+    ${output} =         Execute      ozone admin datanode list --hostname 
"${hostname}"
+    Assert Output       ${output}    1    ${uuid}
 
 Filter list by NodeOperationalState
     ${uuid} =           Execute      grep '^Datanode:' datanode.list | head -1 
| awk '{ print \$2 }'
     ${expected} =       Execute      grep -c 'Operational State: IN_SERVICE' 
datanode.list
     ${output} =         Execute      ozone admin datanode list 
--operational-state IN_SERVICE
-    Should contain      ${output}    Datanode: ${uuid}
-    ${datanodes} =      Get Lines Containing String    ${output}    Datanode:
-    @{lines} =          Split To Lines   ${datanodes}
-    ${count} =          Get Length   ${lines}
-    Should Be Equal As Integers    ${count}    ${expected}
+    Assert Output       ${output}    ${expected}    ${uuid}
 
 Filter list by NodeState
     ${uuid} =           Execute      grep '^Datanode:' datanode.list | head -1 
| awk '{ print \$2 }'
     ${expected} =       Execute      grep -c 'Health State: HEALTHY' 
datanode.list
     ${output} =         Execute      ozone admin datanode list --node-state 
HEALTHY
-    Should contain      ${output}    Datanode: ${uuid}
-    ${datanodes} =      Get Lines Containing String    ${output}    Datanode:
-    @{lines} =          Split To Lines   ${datanodes}
-    ${count} =          Get Length   ${lines}
-    Should Be Equal As Integers    ${count}    ${expected}
+    Assert Output       ${output}    ${expected}    ${uuid}
+
+Get usage info by UUID
+    ${uuid} =           Execute      grep '^Datanode:' datanode.list | head -1 
| awk '{ print \$2 }'
+    ${output} =         Execute      ozone admin datanode usageinfo --uuid 
"${uuid}"
+    Should contain      ${output}    Usage Information (1 Datanodes)
+
+Get usage info by Ip address
+    ${ip} =             Execute      grep '^Datanode:' datanode.list | head -1 
| awk '{ print \$3 }' | awk -F '[/]' '{ print \$3 }'
+    ${output} =         Execute      ozone admin datanode usageinfo --address 
"${ip}"
+    Should contain      ${output}    Usage Information (1 Datanodes)
+
+Get usage info by Hostname
+    ${hostname} =       Execute      grep '^Datanode:' datanode.list | head -1 
| awk '{ print \$3 }' | awk -F '[/]' '{ print \$4 }'
+    ${output} =         Execute      ozone admin datanode usageinfo --address 
"${hostname}"
+    Should contain      ${output}    Usage Information (1 Datanodes)
+
+Get usage info with invalid address
+    ${uuid} =           Execute      grep '^Datanode:' datanode.list | head -1 
| awk '{ print \$2 }'
+    ${output} =         Execute      ozone admin datanode usageinfo --address 
"${uuid}"
+    Should contain      ${output}    Usage Information (0 Datanodes)
 
 Incomplete command
     ${output} =         Execute And Ignore Error     ozone admin datanode


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to