You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
7.2 KiB

  1. package shell
  2. import (
  3. "context"
  4. "flag"
  5. "fmt"
  6. "github.com/chrislusf/seaweedfs/weed/cluster"
  7. "github.com/chrislusf/seaweedfs/weed/pb"
  8. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  9. "github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb"
  10. "io"
  11. "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
  12. )
  13. func init() {
  14. Commands = append(Commands, &commandClusterCheck{})
  15. }
  16. type commandClusterCheck struct {
  17. }
  18. func (c *commandClusterCheck) Name() string {
  19. return "cluster.check"
  20. }
  21. func (c *commandClusterCheck) Help() string {
  22. return `check current cluster network connectivity
  23. cluster.check
  24. `
  25. }
  26. func (c *commandClusterCheck) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) {
  27. clusterPsCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
  28. if err = clusterPsCommand.Parse(args); err != nil {
  29. return nil
  30. }
  31. // collect topology information
  32. topologyInfo, volumeSizeLimitMb, err := collectTopologyInfo(commandEnv, 0)
  33. if err != nil {
  34. return err
  35. }
  36. fmt.Fprintf(writer, "Topology volumeSizeLimit:%d MB%s\n", volumeSizeLimitMb, diskInfosToString(topologyInfo.DiskInfos))
  37. emptyDiskTypeDiskInfo, emptyDiskTypeFound := topologyInfo.DiskInfos[""]
  38. hddDiskTypeDiskInfo, hddDiskTypeFound := topologyInfo.DiskInfos["hdd"]
  39. if !emptyDiskTypeFound && !hddDiskTypeFound {
  40. return fmt.Errorf("Need to a hdd disk type!")
  41. }
  42. if emptyDiskTypeFound && emptyDiskTypeDiskInfo.VolumeCount == 0 || hddDiskTypeFound && hddDiskTypeDiskInfo.VolumeCount == 0 {
  43. return fmt.Errorf("Need to a hdd disk type!")
  44. }
  45. // collect filers
  46. var filers []pb.ServerAddress
  47. err = commandEnv.MasterClient.WithClient(false, func(client master_pb.SeaweedClient) error {
  48. resp, err := client.ListClusterNodes(context.Background(), &master_pb.ListClusterNodesRequest{
  49. ClientType: cluster.FilerType,
  50. })
  51. for _, node := range resp.ClusterNodes {
  52. filers = append(filers, pb.ServerAddress(node.Address))
  53. }
  54. return err
  55. })
  56. if err != nil {
  57. return
  58. }
  59. fmt.Fprintf(writer, "the cluster has %d filers: %+v\n", len(filers), filers)
  60. // collect volume servers
  61. var volumeServers []pb.ServerAddress
  62. t, _, err := collectTopologyInfo(commandEnv, 0)
  63. if err != nil {
  64. return err
  65. }
  66. for _, dc := range t.DataCenterInfos {
  67. for _, r := range dc.RackInfos {
  68. for _, dn := range r.DataNodeInfos {
  69. volumeServers = append(volumeServers, pb.NewServerAddressFromDataNode(dn))
  70. }
  71. }
  72. }
  73. fmt.Fprintf(writer, "the cluster has %d volume servers: %+v\n", len(volumeServers), volumeServers)
  74. // collect all masters
  75. var masters []pb.ServerAddress
  76. for _, master := range commandEnv.MasterClient.GetMasters() {
  77. masters = append(masters, master)
  78. }
  79. // check from master to volume servers
  80. for _, master := range masters {
  81. for _, volumeServer := range volumeServers {
  82. fmt.Fprintf(writer, "checking master %s to volume server %s ... ", string(master), string(volumeServer))
  83. err := pb.WithMasterClient(false, master, commandEnv.option.GrpcDialOption, func(client master_pb.SeaweedClient) error {
  84. _, err := client.Ping(context.Background(), &master_pb.PingRequest{
  85. Target: string(volumeServer),
  86. TargetType: cluster.VolumeServerType,
  87. })
  88. return err
  89. })
  90. if err == nil {
  91. fmt.Fprintf(writer, "ok\n")
  92. } else {
  93. fmt.Fprintf(writer, "%v\n", err)
  94. }
  95. }
  96. }
  97. // check between masters
  98. for _, sourceMaster := range masters {
  99. for _, targetMaster := range masters {
  100. if sourceMaster == targetMaster {
  101. continue
  102. }
  103. fmt.Fprintf(writer, "checking master %s to %s ... ", string(sourceMaster), string(targetMaster))
  104. err := pb.WithMasterClient(false, sourceMaster, commandEnv.option.GrpcDialOption, func(client master_pb.SeaweedClient) error {
  105. _, err := client.Ping(context.Background(), &master_pb.PingRequest{
  106. Target: string(targetMaster),
  107. TargetType: cluster.MasterType,
  108. })
  109. return err
  110. })
  111. if err == nil {
  112. fmt.Fprintf(writer, "ok\n")
  113. } else {
  114. fmt.Fprintf(writer, "%v\n", err)
  115. }
  116. }
  117. }
  118. // check from volume servers to masters
  119. for _, volumeServer := range volumeServers {
  120. for _, master := range masters {
  121. fmt.Fprintf(writer, "checking volume server %s to master %s ... ", string(volumeServer), string(master))
  122. err := pb.WithVolumeServerClient(false, volumeServer, commandEnv.option.GrpcDialOption, func(client volume_server_pb.VolumeServerClient) error {
  123. _, err := client.Ping(context.Background(), &volume_server_pb.PingRequest{
  124. Target: string(master),
  125. TargetType: cluster.MasterType,
  126. })
  127. return err
  128. })
  129. if err == nil {
  130. fmt.Fprintf(writer, "ok\n")
  131. } else {
  132. fmt.Fprintf(writer, "%v\n", err)
  133. }
  134. }
  135. }
  136. // check from filers to masters
  137. for _, filer := range filers {
  138. for _, master := range masters {
  139. fmt.Fprintf(writer, "checking filer %s to master %s ... ", string(filer), string(master))
  140. err := pb.WithFilerClient(false, filer, commandEnv.option.GrpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
  141. _, err := client.Ping(context.Background(), &filer_pb.PingRequest{
  142. Target: string(master),
  143. TargetType: cluster.MasterType,
  144. })
  145. return err
  146. })
  147. if err == nil {
  148. fmt.Fprintf(writer, "ok\n")
  149. } else {
  150. fmt.Fprintf(writer, "%v\n", err)
  151. }
  152. }
  153. }
  154. // check from filers to volume servers
  155. for _, filer := range filers {
  156. for _, volumeServer := range volumeServers {
  157. fmt.Fprintf(writer, "checking filer %s to volume server %s ... ", string(filer), string(volumeServer))
  158. err := pb.WithFilerClient(false, filer, commandEnv.option.GrpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
  159. _, err := client.Ping(context.Background(), &filer_pb.PingRequest{
  160. Target: string(volumeServer),
  161. TargetType: cluster.VolumeServerType,
  162. })
  163. return err
  164. })
  165. if err == nil {
  166. fmt.Fprintf(writer, "ok\n")
  167. } else {
  168. fmt.Fprintf(writer, "%v\n", err)
  169. }
  170. }
  171. }
  172. // check between volume servers
  173. for _, sourceVolumeServer := range volumeServers {
  174. for _, targetVolumeServer := range volumeServers {
  175. if sourceVolumeServer == targetVolumeServer {
  176. continue
  177. }
  178. fmt.Fprintf(writer, "checking volume server %s to %s ... ", string(sourceVolumeServer), string(targetVolumeServer))
  179. err := pb.WithVolumeServerClient(false, sourceVolumeServer, commandEnv.option.GrpcDialOption, func(client volume_server_pb.VolumeServerClient) error {
  180. _, err := client.Ping(context.Background(), &volume_server_pb.PingRequest{
  181. Target: string(targetVolumeServer),
  182. TargetType: cluster.VolumeServerType,
  183. })
  184. return err
  185. })
  186. if err == nil {
  187. fmt.Fprintf(writer, "ok\n")
  188. } else {
  189. fmt.Fprintf(writer, "%v\n", err)
  190. }
  191. }
  192. }
  193. // check between filers, and need to connect to itself
  194. for _, sourceFiler := range filers {
  195. for _, targetFiler := range filers {
  196. fmt.Fprintf(writer, "checking filer %s to %s ... ", string(sourceFiler), string(targetFiler))
  197. err := pb.WithFilerClient(false, sourceFiler, commandEnv.option.GrpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
  198. _, err := client.Ping(context.Background(), &filer_pb.PingRequest{
  199. Target: string(targetFiler),
  200. TargetType: cluster.FilerType,
  201. })
  202. return err
  203. })
  204. if err == nil {
  205. fmt.Fprintf(writer, "ok\n")
  206. } else {
  207. fmt.Fprintf(writer, "%v\n", err)
  208. }
  209. }
  210. }
  211. return nil
  212. }