diff --git a/curvefs/src/tools/create/curvefs_create_fs.cpp b/curvefs/src/tools/create/curvefs_create_fs.cpp index 88283138b1..c32952dcfb 100644 --- a/curvefs/src/tools/create/curvefs_create_fs.cpp +++ b/curvefs/src/tools/create/curvefs_create_fs.cpp @@ -99,7 +99,7 @@ int CreateFsTool::Init() { mds::CreateFsRequest request; request.set_fsname(FLAGS_fsName); request.set_blocksize(FLAGS_blockSize); - if (FLAGS_fsType == "s3") { + if (FLAGS_fsType == kFsTypeS3) { // s3 request.set_fstype(common::FSType::TYPE_S3); auto s3 = new common::S3Info(); @@ -110,7 +110,7 @@ int CreateFsTool::Init() { s3->set_blocksize(FLAGS_s3_blocksize); s3->set_chunksize(FLAGS_s3_chunksize); request.mutable_fsdetail()->set_allocated_s3info(s3); - } else if (FLAGS_fsType == "volume") { + } else if (FLAGS_fsType == kFsTypeVolume) { // volume request.set_fstype(common::FSType::TYPE_VOLUME); auto volume = new common::Volume(); @@ -121,7 +121,8 @@ int CreateFsTool::Init() { volume->set_password(FLAGS_volumePassword); request.mutable_fsdetail()->set_allocated_volume(volume); } else { - std::cerr << "-fsType should be s3 or volume." << std::endl; + std::cerr << "-fsType should be " << kFsTypeS3 << " or " + << kFsTypeVolume << "." << std::endl; ret = -1; } diff --git a/curvefs/src/tools/curvefs_tool_define.cpp b/curvefs/src/tools/curvefs_tool_define.cpp index 4d8ed8ba42..7d3baeb905 100644 --- a/curvefs/src/tools/curvefs_tool_define.cpp +++ b/curvefs/src/tools/curvefs_tool_define.cpp @@ -57,6 +57,10 @@ DEFINE_string(s3_bucket_name, "bucketname", "s3 bucket name"); DEFINE_uint64(s3_blocksize, 1048576, "s3 block size"); DEFINE_uint64(s3_chunksize, 4194304, "s3 chunk size"); +// list-topology +DEFINE_string(jsonPath, "/tmp/topology.json", "output json path"); +DEFINE_string(jsonType, "build", "output json type(build or tree)"); + // topology DEFINE_string(mds_addr, "127.0.0.1:6700", "mds ip and port, separated by \",\""); // NOLINT @@ -215,6 +219,10 @@ std::function CheckPartitionIdDefault = std::bind(&CheckFlagInfoDefault, std::placeholders::_1, "partitionId"); +std::function CheckJsonPathDefault = + std::bind(&CheckFlagInfoDefault, std::placeholders::_1, + "jsonPath"); + /* translate to string */ auto StrVec2Str(const std::vector& strVec) -> std::string { diff --git a/curvefs/src/tools/curvefs_tool_define.h b/curvefs/src/tools/curvefs_tool_define.h index c90095f413..ee42b310a9 100644 --- a/curvefs/src/tools/curvefs_tool_define.h +++ b/curvefs/src/tools/curvefs_tool_define.h @@ -133,6 +133,14 @@ const char kHostFollowerValue[] = "follower"; const char kEtcdLeaderValue[] = "StateLeader"; const char kEtcdFollowerValue[] = "StateFollower"; +/* fs type */ +const char kFsTypeS3[] = "s3"; +const char kFsTypeVolume[] = "volume"; + +/* json type */ +const char kJsonTypeBuild[] = "build"; +const char kJsonTypeTree[] = "tree"; + } // namespace tools } // namespace curvefs @@ -155,6 +163,23 @@ const char kZone[] = "zone"; const char kReplicasNum[] = "replicasnum"; const char kCopysetNum[] = "copysetnum"; const char kZoneNum[] = "zonenum"; +const char kClusterId[] = "clusterid"; +const char kPoolId[] = "poolid"; +const char kPoolName[] = "poolname"; +const char kCreateTime[] = "createtime"; +const char kPolicy[] = "policy"; +const char kPoollist[] = "poollist"; +const char kZonelist[] = "zonelist"; +const char kZoneId[] = "zoneid"; +const char kZoneName[] = "zonename"; +const char kServerlist[] = "serverlist"; +const char kServerId[] = "serverid"; +const char kHostName[] = "hostname"; +const char kMetaserverList[] = "metaserverlist"; +const char kMetaserverId[] = "metaserverid"; +const char kHostIp[] = "hostip"; +const char kPort[] = "port"; +const char kOnlineState[] = "state"; } // namespace topology } // namespace mds @@ -245,6 +270,8 @@ extern std::function CheckCopysetIdDefault; extern std::function CheckPartitionIdDefault; +extern std::function CheckJsonPathDefault; + /* translate to string */ std::string StrVec2Str(const std::vector&); diff --git a/curvefs/src/tools/list/curvefs_topology_list.cpp b/curvefs/src/tools/list/curvefs_topology_list.cpp index ccc434321c..b32d4012a2 100644 --- a/curvefs/src/tools/list/curvefs_topology_list.cpp +++ b/curvefs/src/tools/list/curvefs_topology_list.cpp @@ -23,9 +23,14 @@ #include +#include +#include + #include "src/common/string_util.h" DECLARE_string(mdsAddr); +DECLARE_string(jsonPath); +DECLARE_string(jsonType); namespace curvefs { namespace tools { @@ -33,8 +38,9 @@ namespace list { void TopologyListTool::PrintHelp() { CurvefsToolRpc::PrintHelp(); - std::cout << " [-mdsAddr=" << FLAGS_mdsAddr << "]"; - std::cout << std::endl; + std::cout << " [-mdsAddr=" << FLAGS_mdsAddr + << "] [-jsonType=" << FLAGS_jsonType + << " -jsonPath=" << FLAGS_jsonPath << "]" << std::endl; } void TopologyListTool::AddUpdateFlags() { @@ -69,6 +75,9 @@ bool TopologyListTool::AfterSendRequestToHost(const std::string& host) { ret = true; // clusterId clusterId_ = response_->clusterid(); + clusterId2CLusterInfo_.insert(std::pair( + clusterId_, + ClusterInfo(clusterId_, std::vector()))); // pool if (!GetPoolInfoFromResponse()) { ret = false; @@ -89,29 +98,36 @@ bool TopologyListTool::AfterSendRequestToHost(const std::string& host) { // show if (show_) { // cluster - std::cout << "[cluster]\nclusterId: " << clusterId_ << std::endl; + std::cout << "[cluster]\n" + << mds::topology::kClusterId << ": " << clusterId_ + << std::endl; // pool std::cout << "[pool]" << std::endl; - for (auto const& i : poolId2PoolInfo) { + for (auto const& i : poolId2PoolInfo_) { ShowPoolInfo(i.second); } // zone std::cout << "[zone]" << std::endl; - for (auto const& i : zoneId2ZoneInfo) { + for (auto const& i : zoneId2ZoneInfo_) { ShowZoneInfo(i.second); } // server std::cout << "[server]" << std::endl; - for (auto const& i : serverId2ServerInfo) { + for (auto const& i : serverId2ServerInfo_) { ShowServerInfo(i.second); } // metaserver std::cout << "[metaserver]" << std::endl; - for (auto const& i : metaserverId2MetaserverInfo) { + for (auto const& i : metaserverId2MetaserverInfo_) { ShowMetaserverInfo(i.second); } } + + google::CommandLineFlagInfo info; + if (!CheckJsonPathDefault(&info) && ret) { + OutputFile(); + } } return ret; } @@ -119,9 +135,8 @@ bool TopologyListTool::AfterSendRequestToHost(const std::string& host) { PoolPolicy::PoolPolicy(const std::string& jsonStr) { Json::CharReaderBuilder reader; std::stringstream ss(jsonStr); - std::string err; Json::Value json; - bool parseCode = Json::parseFromStream(reader, ss, &json, &err); + bool parseCode = Json::parseFromStream(reader, ss, &json, nullptr); if (parseCode && !json["replicaNum"].isNull() && !json["copysetNum"].isNull() && !json["zoneNum"].isNull()) { replicaNum = json["replicaNum"].asUInt(); @@ -136,9 +151,9 @@ std::ostream& operator<<(std::ostream& os, const PoolPolicy& policy) { if (policy.error) { os << "policy has error!"; } else { - os << "copysetNum:" << policy.copysetNum - << " replicaNum:" << policy.replicaNum - << " zoneNum:" << policy.zoneNum; + os << mds::topology::kCopysetNum << ":" << policy.copysetNum << " " + << mds::topology::kReplicasNum << ":" << policy.replicaNum << " " + << mds::topology::kZoneNum << ":" << policy.zoneNum; } return os; } @@ -155,10 +170,11 @@ bool TopologyListTool::GetPoolInfoFromResponse() { ret = false; } else { for (auto const& i : pools.poolinfos()) { - poolId2PoolInfo.insert( + poolId2PoolInfo_.insert( std::pair( i.poolid(), PoolInfoType(i, std::vector()))); + clusterId2CLusterInfo_[clusterId_].second.emplace_back(i.poolid()); } } return ret; @@ -176,13 +192,13 @@ bool TopologyListTool::GetZoneInfoFromResponse() { ret = false; } else { for (auto const& i : zones.zoneinfos()) { - zoneId2ZoneInfo.insert( + zoneId2ZoneInfo_.insert( std::pair( i.zoneid(), ZoneInfoType(i, std::vector()))); - if (poolId2PoolInfo.find(i.poolid()) != poolId2PoolInfo.end()) { - poolId2PoolInfo[i.poolid()].second.emplace_back(i.zoneid()); + if (poolId2PoolInfo_.find(i.poolid()) != poolId2PoolInfo_.end()) { + poolId2PoolInfo_[i.poolid()].second.emplace_back(i.zoneid()); } else { errorOutput_ << "zone:" << i.zoneid() << " has error: poolId:" << i.poolid() @@ -206,14 +222,14 @@ bool TopologyListTool::GetServerInfoFromResponse() { ret = false; } else { for (auto const& i : servers.serverinfos()) { - serverId2ServerInfo.insert( + serverId2ServerInfo_.insert( std::pair( i.serverid(), ServerInfoType( i, std::vector()))); - if (zoneId2ZoneInfo.find(i.zoneid()) != zoneId2ZoneInfo.end()) { - zoneId2ZoneInfo[i.zoneid()].second.emplace_back(i.serverid()); + if (zoneId2ZoneInfo_.find(i.zoneid()) != zoneId2ZoneInfo_.end()) { + zoneId2ZoneInfo_[i.zoneid()].second.emplace_back(i.serverid()); } else { errorOutput_ << "server:" << i.serverid() << " has error: zoneId:" << i.zoneid() @@ -237,12 +253,12 @@ bool TopologyListTool::GetMetaserverInfoFromResponse() { ret = false; } else { for (auto const& i : metaservers.metaserverinfos()) { - metaserverId2MetaserverInfo.insert( + metaserverId2MetaserverInfo_.insert( std::pair( i.metaserverid(), MetaserverInfoType(i))); - if (serverId2ServerInfo.find(i.serverid()) != - serverId2ServerInfo.end()) { - serverId2ServerInfo[i.serverid()].second.emplace_back( + if (serverId2ServerInfo_.find(i.serverid()) != + serverId2ServerInfo_.end()) { + serverId2ServerInfo_[i.serverid()].second.emplace_back( i.metaserverid()); } else { errorOutput_ << "metaserver:" << i.metaserverid() @@ -290,6 +306,27 @@ void TopologyListTool::ShowMetaserverInfo( std::cout << MetaserverInfo2Str(metaserver) << std::endl; } +bool TopologyListTool::OutputFile() { + Json::Value value; + topology::TopologyTreeJson treeJson(*this); + if (!treeJson.BuildJsonValue(&value, FLAGS_jsonType)) { + std::cerr << "build json file failed!" << std::endl; + return false; + } + + std::ofstream jsonFile; + jsonFile.open(FLAGS_jsonPath.c_str(), std::ios::out); + if (!jsonFile) { + std::cerr << "open json file failed!" << std::endl; + return false; + } + Json::StreamWriterBuilder clusterMap; + std::unique_ptr writer(clusterMap.newStreamWriter()); + writer->write(value, &jsonFile); + jsonFile.close(); + return true; +} + } // namespace list } // namespace tools } // namespace curvefs diff --git a/curvefs/src/tools/list/curvefs_topology_list.h b/curvefs/src/tools/list/curvefs_topology_list.h index 8b20361afa..a6c1a3593c 100644 --- a/curvefs/src/tools/list/curvefs_topology_list.h +++ b/curvefs/src/tools/list/curvefs_topology_list.h @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -33,11 +34,19 @@ #include "curvefs/src/mds/common/mds_define.h" #include "curvefs/src/tools/curvefs_tool.h" #include "curvefs/src/tools/curvefs_tool_define.h" +#include "curvefs/src/tools/list/curvefs_topology_tree_json.h" namespace curvefs { namespace tools { + +namespace topology { +class TopologyTreeJson; +} + namespace list { +using ClusterInfo = + std::pair>; using PoolInfoType = std::pair>; using ZoneInfoType = std::pair clusterId2CLusterInfo_; + /** * @brief poolId to poolInfo and zoneIds which belongs to pool * * @details */ - std::map poolId2PoolInfo; + std::map poolId2PoolInfo_; /** * @brief zoneId to zoneInfo and serverIds which belongs to zone * * @details */ - std::map zoneId2ZoneInfo; + std::map zoneId2ZoneInfo_; /** * @brief serverId to serverInfo and metaserverIds which belongs to server * * @details */ - std::map serverId2ServerInfo; + std::map serverId2ServerInfo_; /** * @brief metaserverId to metaserverInfo @@ -162,7 +179,7 @@ class TopologyListTool * @details */ std::map - metaserverId2MetaserverInfo; + metaserverId2MetaserverInfo_; }; } // namespace list diff --git a/curvefs/src/tools/list/curvefs_topology_tree_json.cpp b/curvefs/src/tools/list/curvefs_topology_tree_json.cpp new file mode 100644 index 0000000000..fc5ecf879a --- /dev/null +++ b/curvefs/src/tools/list/curvefs_topology_tree_json.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2022 NetEase Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Project: curve + * Created Date: 2022-01-14 + * Author: chengyi01 + */ + +#include "curvefs/src/tools/list/curvefs_topology_tree_json.h" + +#include "curvefs/src/tools/list/curvefs_topology_list.h" + +namespace curvefs { +namespace tools { +namespace topology { + +TopologyTreeJson::TopologyTreeJson(const list::TopologyListTool& topologyTool) { + clusterId_ = topologyTool.clusterId_; + clusterId2CLusterInfo_ = topologyTool.clusterId2CLusterInfo_; + poolId2PoolInfo_ = topologyTool.poolId2PoolInfo_; + zoneId2ZoneInfo_ = topologyTool.zoneId2ZoneInfo_; + serverId2ServerInfo_ = topologyTool.serverId2ServerInfo_; + metaserverId2MetaserverInfo_ = topologyTool.metaserverId2MetaserverInfo_; +} // namespace topology + +bool TopologyTreeJson::BuildClusterMapPools(Json::Value* pools) { + bool ret = true; + for (auto const& i : poolId2PoolInfo_) { + Json::Value value; + value[mds::topology::kName] = i.second.first.poolname(); + + auto policy = + list::PoolPolicy(i.second.first.redundanceandplacementpolicy()); + if (policy.error) { + std::cerr << "build pool error!" << std::endl; + ret = false; + break; + } + value[mds::topology::kReplicasNum] = policy.replicaNum; + value[mds::topology::kCopysetNum] = policy.copysetNum; + value[mds::topology::kZoneNum] = policy.zoneNum; + pools->append(value); + } + return ret; +} + +bool TopologyTreeJson::BuildClusterMapServers(Json::Value* servers) { + bool ret = true; + for (auto const& i : serverId2ServerInfo_) { + Json::Value value; + auto server = i.second.first; + value[mds::topology::kName] = server.hostname(); + value[mds::topology::kInternalIp] = server.internalip(); + value[mds::topology::kInternalPort] = server.internalport(); + value[mds::topology::kExternalIp] = server.externalip(); + value[mds::topology::kExternalPort] = server.externalport(); + auto zone = zoneId2ZoneInfo_[server.zoneid()].first; + value[mds::topology::kZone] = zone.zonename(); + auto pool = poolId2PoolInfo_[zone.poolid()].first; + value[mds::topology::kPool] = pool.poolname(); + servers->append(value); + } + return ret; +} + +bool TopologyTreeJson::BuildJsonValue(Json::Value* value, + const std::string& jsonType) { + if (jsonType == kJsonTypeBuild) { + // build json + Json::Value pools; + Json::Value servers; + if (!(BuildClusterMapPools(&pools) && + BuildClusterMapServers(&servers))) { + return false; + } + (*value)[mds::topology::kServers] = servers; + (*value)[mds::topology::kPools] = pools; + } else if (jsonType == kJsonTypeTree) { + if (!GetClusterTree(value, clusterId_)) { + return false; + } + } else { + std::cerr << "-jsonType should be " << kJsonTypeBuild << " or " + << kJsonTypeTree << "!" << std::endl; + return false; + } + + return true; +} +bool TopologyTreeJson::GetClusterTree(Json::Value* cluster, + const std::string& clusterId) { + bool ret = true; + auto clusterInfo = clusterId2CLusterInfo_[clusterId]; + (*cluster)[mds::topology::kClusterId] = clusterInfo.first; + for (auto const& poolId : clusterInfo.second) { + Json::Value pool; + ret = GetPoolTree(&pool, poolId); + if (!ret) { + break; + } + (*cluster)[mds::topology::kPoollist].append(pool); + } + return ret; +} + +bool TopologyTreeJson::GetPoolTree(Json::Value* pool, uint64_t poolId) { + bool ret = true; + auto poolInfo = poolId2PoolInfo_[poolId]; + (*pool)[mds::topology::kPoolId] = poolInfo.first.poolid(); + (*pool)[mds::topology::kPoolName] = poolInfo.first.poolname(); + (*pool)[mds::topology::kCreateTime] = poolInfo.first.createtime(); + Json::CharReaderBuilder reader; + std::stringstream ss(poolInfo.first.redundanceandplacementpolicy()); + Json::Value policyValue; + std::string err; + if (!Json::parseFromStream(reader, ss, &policyValue, &err)) { + std::cerr << "parse policy failed! error is " << err << std::endl; + ret = false; + } + (*pool)[mds::topology::kPolicy] = policyValue; + + for (auto const& zoneId : poolInfo.second) { + Json::Value zone; + ret = GetZoneTree(&zone, zoneId); + if (!ret) { + break; + } + (*pool)[mds::topology::kZonelist].append(zone); + } + + return ret; +} + +bool TopologyTreeJson::GetZoneTree(Json::Value* zone, uint64_t zoneId) { + bool ret = true; + auto zoneInfo = zoneId2ZoneInfo_[zoneId]; + (*zone)[mds::topology::kZoneId] = zoneInfo.first.zoneid(); + (*zone)[mds::topology::kZoneName] = zoneInfo.first.zonename(); + (*zone)[mds::topology::kPoolId] = zoneInfo.first.poolid(); + + for (auto const& serverId : zoneInfo.second) { + Json::Value server; + ret = GetServerTree(&server, serverId); + if (!ret) { + break; + } + (*zone)[mds::topology::kServerlist].append(server); + } + + return ret; +} + +bool TopologyTreeJson::GetServerTree(Json::Value* server, uint64_t serverId) { + bool ret = true; + auto serverinfo = serverId2ServerInfo_[serverId]; + (*server)[mds::topology::kServerId] = serverinfo.first.serverid(); + (*server)[mds::topology::kHostName] = serverinfo.first.hostname(); + (*server)[mds::topology::kInternalIp] = serverinfo.first.internalip(); + (*server)[mds::topology::kInternalPort] = serverinfo.first.internalport(); + (*server)[mds::topology::kExternalIp] = serverinfo.first.externalip(); + (*server)[mds::topology::kExternalPort] = serverinfo.first.externalport(); + (*server)[mds::topology::kZoneId] = serverinfo.first.zoneid(); + (*server)[mds::topology::kPoolId] = serverinfo.first.poolid(); + + for (auto const& metaserverId : serverinfo.second) { + Json::Value metaserver; + ret = GetMetaserverTree(&metaserver, metaserverId); + if (!ret) { + break; + } + (*server)[mds::topology::kMetaserverList].append(metaserver); + } + + return ret; +} + +bool TopologyTreeJson::GetMetaserverTree(Json::Value* metaserver, + uint64_t metaserverId) { + bool ret = true; + auto metaserverinfo = metaserverId2MetaserverInfo_[metaserverId]; + (*metaserver)[mds::topology::kMetaserverId] = metaserverinfo.metaserverid(); + (*metaserver)[mds::topology::kHostName] = metaserverinfo.hostname(); + (*metaserver)[mds::topology::kHostIp] = metaserverinfo.hostip(); + (*metaserver)[mds::topology::kPort] = metaserverinfo.port(); + (*metaserver)[mds::topology::kExternalIp] = metaserverinfo.externalip(); + (*metaserver)[mds::topology::kExternalPort] = metaserverinfo.externalport(); + (*metaserver)[mds::topology::kOnlineState] = metaserverinfo.onlinestate(); + (*metaserver)[mds::topology::kServerId] = metaserverinfo.serverid(); + + return ret; +} + +} // namespace topology +} // namespace tools +} // namespace curvefs diff --git a/curvefs/src/tools/list/curvefs_topology_tree_json.h b/curvefs/src/tools/list/curvefs_topology_tree_json.h new file mode 100644 index 0000000000..b8cd164349 --- /dev/null +++ b/curvefs/src/tools/list/curvefs_topology_tree_json.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2022 NetEase Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Project: curve + * Created Date: 2022-01-14 + * Author: chengyi01 + */ + +#ifndef CURVEFS_SRC_TOOLS_LIST_CURVEFS_TOPOLOGY_TREE_JSON_H_ +#define CURVEFS_SRC_TOOLS_LIST_CURVEFS_TOPOLOGY_TREE_JSON_H_ + +#include + +#include +#include +#include +#include + +#include "curvefs/proto/topology.pb.h" +#include "curvefs/src/mds/common/mds_define.h" +#include "curvefs/src/tools/list/curvefs_topology_list.h" + +namespace curvefs { +namespace tools { + +namespace list { +class TopologyListTool; +} + +namespace topology { + +using ClusterInfo = + std::pair>; +using PoolInfoType = + std::pair>; +using ZoneInfoType = std::pair>; +using ServerInfoType = std::pair>; +using MetaserverInfoType = mds::topology::MetaServerInfo; + +class TopologyTreeJson { + public: + explicit TopologyTreeJson(const list::TopologyListTool& topologyTool); + + protected: + std::string clusterId_; + /** + * poolId to clusterInfo and poolIds which belongs to pool + */ + std::map clusterId2CLusterInfo_; + + /** + * @brief poolId to poolInfo and zoneIds which belongs to pool + * + * @details + */ + std::map poolId2PoolInfo_; + + /** + * @brief zoneId to zoneInfo and serverIds which belongs to zone + * + * @details + */ + std::map zoneId2ZoneInfo_; + + /** + * @brief serverId to serverInfo and metaserverIds which belongs to server + * + * @details + */ + std::map serverId2ServerInfo_; + + /** + * @brief metaserverId to metaserverInfo + * + * @details + */ + std::map + metaserverId2MetaserverInfo_; + + public: + bool BuildClusterMapPools(Json::Value* pools); + + bool BuildClusterMapServers(Json::Value* servers); + + bool BuildJsonValue(Json::Value* value, const std::string& jsonType); + + bool GetClusterTree(Json::Value* cluster, const std::string& clusterId); + + bool GetPoolTree(Json::Value* pool, uint64_t poolId); + + bool GetZoneTree(Json::Value* zone, uint64_t zoneId); + + bool GetServerTree(Json::Value* server, uint64_t serverId); + + bool GetMetaserverTree(Json::Value* metaserver, uint64_t metaserverId); +}; + +} // namespace topology +} // namespace tools +} // namespace curvefs + +#endif // CURVEFS_SRC_TOOLS_LIST_CURVEFS_TOPOLOGY_TREE_JSON_H_