diff --git a/src/exec/admin/ShowHostsExecutor.cpp b/src/exec/admin/ShowHostsExecutor.cpp
index e9d776698cfdc8ea0b51f6a5742f38c8036c4feb..7ea14e1dc2507662c26769a20d457f2de001772b 100644
--- a/src/exec/admin/ShowHostsExecutor.cpp
+++ b/src/exec/admin/ShowHostsExecutor.cpp
@@ -57,7 +57,7 @@ folly::Future<Status> ShowHostsExecutor::showHosts() {
                 i = 0;
                 for (const auto &p : host.get_all_parts()) {
                     parts << p.first << ":" << p.second.size();
-                    if (i < host.get_leader_parts().size() - 1) {
+                    if (i < host.get_all_parts().size() - 1) {
                         parts << kPartitionDelimeter;
                     }
                     ++i;
diff --git a/src/validator/AdminValidator.cpp b/src/validator/AdminValidator.cpp
index 047b9c6074cb8232481548030083ecc06a64c9d1..2301911bf5c572f9d1eba17ed7119b74f2685193 100644
--- a/src/validator/AdminValidator.cpp
+++ b/src/validator/AdminValidator.cpp
@@ -202,6 +202,17 @@ Status ShowSnapshotsValidator::toPlan() {
     return Status::OK();
 }
 
+Status ShowHostsValidator::validateImpl() {
+    return Status::OK();
+}
+
+Status ShowHostsValidator::toPlan() {
+    auto *showHosts = ShowHosts::make(qctx_->plan(), nullptr);
+    root_ = showHosts;
+    tail_ = root_;
+    return Status::OK();
+}
+
 Status ShowPartsValidator::validateImpl() {
     return Status::OK();
 }
diff --git a/src/validator/AdminValidator.h b/src/validator/AdminValidator.h
index 7caabb9b683061ff92d0e1ba027274e34189e64e..3a4a84ef6645228b2d2bd6d9ea55b8748672b556 100644
--- a/src/validator/AdminValidator.h
+++ b/src/validator/AdminValidator.h
@@ -123,6 +123,19 @@ private:
     Status toPlan() override;
 };
 
+class ShowHostsValidator final : public Validator {
+public:
+    ShowHostsValidator(Sentence* sentence, QueryContext* context)
+            : Validator(sentence, context) {
+        setNoSpaceRequired();
+    }
+
+private:
+    Status validateImpl() override;
+
+    Status toPlan() override;
+};
+
 class ShowPartsValidator final : public Validator {
 public:
     ShowPartsValidator(Sentence* sentence, QueryContext* context)
@@ -134,6 +147,7 @@ private:
 
     Status toPlan() override;
 };
+
 }  // namespace graph
 }  // namespace nebula
 #endif  // VALIDATOR_ADMINVALIDATOR_H_
diff --git a/src/validator/Validator.cpp b/src/validator/Validator.cpp
index aa455ebfbe5b5c412d4eb039b45473288a24c666..78921d4be5cc7c1d45ffc63131431fc9648c871e 100644
--- a/src/validator/Validator.cpp
+++ b/src/validator/Validator.cpp
@@ -121,11 +121,50 @@ std::unique_ptr<Validator> Validator::makeValidator(Sentence* sentence, QueryCon
             return std::make_unique<UpdateVertexValidator>(sentence, context);
         case Sentence::Kind::kUpdateEdge:
             return std::make_unique<UpdateEdgeValidator>(sentence, context);
+        case Sentence::Kind::kShowHosts:
+            return std::make_unique<ShowHostsValidator>(sentence, context);
         case Sentence::Kind::kShowParts:
             return std::make_unique<ShowPartsValidator>(sentence, context);
-        default:
-            return std::make_unique<ReportError>(sentence, context);
+        case Sentence::Kind::kUnknown:
+        case Sentence::Kind::kMatch:
+        case Sentence::Kind::kCreateTagIndex:
+        case Sentence::Kind::kShowCreateTagIndex:
+        case Sentence::Kind::kShowTagIndexStatus:
+        case Sentence::Kind::kDescribeTagIndex:
+        case Sentence::Kind::kShowTagIndexes:
+        case Sentence::Kind::kRebuildTagIndex:
+        case Sentence::Kind::kDropTagIndex:
+        case Sentence::Kind::kCreateEdgeIndex:
+        case Sentence::Kind::kShowCreateEdgeIndex:
+        case Sentence::Kind::kShowEdgeIndexStatus:
+        case Sentence::Kind::kDescribeEdgeIndex:
+        case Sentence::Kind::kShowEdgeIndexes:
+        case Sentence::Kind::kRebuildEdgeIndex:
+        case Sentence::Kind::kDropEdgeIndex:
+        case Sentence::Kind::kShowUsers:
+        case Sentence::Kind::kCreateUser:
+        case Sentence::Kind::kDropUser:
+        case Sentence::Kind::kAlterUser:
+        case Sentence::Kind::kGrant:
+        case Sentence::Kind::kRevoke:
+        case Sentence::Kind::kShowRoles:
+        case Sentence::Kind::kChangePassword:
+        case Sentence::Kind::kShowCharset:
+        case Sentence::Kind::kShowCollation:
+        case Sentence::Kind::kLookup:
+        case Sentence::Kind::kDownload:
+        case Sentence::Kind::kIngest:
+        case Sentence::Kind::kBalance:
+        case Sentence::Kind::kConfig:
+        case Sentence::Kind::kFindPath:
+        case Sentence::Kind::kReturn:
+        case Sentence::Kind::kAdmin: {
+            // nothing
+            DLOG(FATAL) << "Unimplemented sentence " << kind;
+        }
     }
+    DLOG(FATAL) << "Unknown sentence " << static_cast<int>(kind);
+    return std::make_unique<ReportError>(sentence, context);
 }
 
 Status Validator::appendPlan(PlanNode* node, PlanNode* appended) {
diff --git a/src/validator/test/AdminValidatorTest.cpp b/src/validator/test/AdminValidatorTest.cpp
index 7609015add9c51d3d4eae51d17034d3f51d6c303..548e947b54d7846d8cbe577c498ca98980d68a84 100644
--- a/src/validator/test/AdminValidatorTest.cpp
+++ b/src/validator/test/AdminValidatorTest.cpp
@@ -26,5 +26,22 @@ TEST_F(AdminValidatorTest, SpaceTest) {
         ASSERT_TRUE(checkResult("CREATE SPACE TEST; USE TEST;", expected));
     }
 }
+
+TEST_F(AdminValidatorTest, ShowHosts) {
+    {
+        std::vector<PlanNode::Kind> expected = {
+            PK::kShowHosts, PK::kStart
+        };
+        ASSERT_TRUE(checkResult("SHOW HOSTS;", expected));
+    }
+    // chain
+    {
+        std::vector<PlanNode::Kind> expected = {
+            PK::kShowHosts, PK::kDescSpace, PK::kStart
+        };
+        ASSERT_TRUE(checkResult("DESC SPACE TEST; SHOW HOSTS", expected));
+    }
+}
+
 }  // namespace graph
 }  // namespace nebula
diff --git a/src/validator/test/ValidatorTestBase.h b/src/validator/test/ValidatorTestBase.h
index 86095a250ce95391cee4cbdc7d180d70f5b1cb97..6df88da348b2a44bb08cbee5d1d80f0bd38c57c1 100644
--- a/src/validator/test/ValidatorTestBase.h
+++ b/src/validator/test/ValidatorTestBase.h
@@ -153,6 +153,7 @@ protected:
                 case PlanNode::Kind::kStart: {
                     break;
                 }
+                case PlanNode::Kind::kShowHosts:
                 case PlanNode::Kind::kGetNeighbors:
                 case PlanNode::Kind::kGetVertices:
                 case PlanNode::Kind::kGetEdges:
diff --git a/tests/admin/test_show_hosts.py b/tests/admin/test_show_hosts.py
new file mode 100644
index 0000000000000000000000000000000000000000..89522faa98a24f3f39748236fa404c22da1a0bd5
--- /dev/null
+++ b/tests/admin/test_show_hosts.py
@@ -0,0 +1,40 @@
+# --coding:utf-8--
+#
+# Copyright (c) 2020 vesoft inc. All rights reserved.
+#
+# This source code is licensed under Apache 2.0 License,
+# attached with Common Clause Condition 1.0, found in the LICENSES directory.
+
+import time
+import re
+
+from tests.common.nebula_test_suite import NebulaTestSuite
+
+
+class TestShowHosts(NebulaTestSuite):
+    @classmethod
+    def prepare(self):
+        pass
+
+    @classmethod
+    def cleanup(self):
+        pass
+
+    def test_show_hosts(self):
+        query = "SHOW HOSTS";
+        expected_column_names = ['Host',
+                                 'Port',
+                                 'Status',
+                                 'Leader count',
+                                 'Leader distribution',
+                                 'Partition distribution']
+        expected_result_format = [[re.compile(r'\S+'),
+                                   re.compile(r'\d+'),
+                                   re.compile(r'ONLINE|OFFLINE'),
+                                   re.compile(r'\d+'),
+                                   re.compile(r'No valid partition|(\S+:\d+, )*\S+:\d+'),
+                                   re.compile(r'No valid partition|(\S+:\d+, )*\S+:\d+')]]
+        resp = self.execute_query(query)
+        self.check_resp_succeeded(resp)
+        self.check_column_names(resp, expected_column_names)
+        self.search_result(resp, expected_result_format, True)