/pkg/glusterutils/exporterd.go

https://github.com/gluster/gluster-prometheus · Go · 179 lines · 148 code · 15 blank · 16 comment · 41 complexity · 15e2fad4c7241d55a695348454d21ce4 MD5 · raw file

  1. package glusterutils
  2. import (
  3. "bufio"
  4. "errors"
  5. "io"
  6. "os"
  7. "os/exec"
  8. "path/filepath"
  9. "regexp"
  10. "strings"
  11. "time"
  12. "github.com/gluster/gluster-prometheus/gluster-exporter/conf"
  13. "github.com/gluster/gluster-prometheus/pkg/glusterutils/glusterconsts"
  14. )
  15. var (
  16. peerIDPattern = regexp.MustCompile("[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}")
  17. )
  18. // IsLeader returns true or false based on whether the node is the leader of the cluster or not
  19. func (g *GD1) IsLeader() (bool, error) {
  20. setDefaultConfig(g.config)
  21. peerList, err := g.Peers()
  22. if err != nil {
  23. return false, err
  24. }
  25. peerID, err := g.LocalPeerID()
  26. if err != nil {
  27. return false, err
  28. }
  29. var maxPeerID string
  30. //This for loop iterates among all the peers and finds the peer with the maximum UUID (lexicographically)
  31. for i, pr := range peerList {
  32. if pr.Online {
  33. if peerList[i].ID > maxPeerID {
  34. maxPeerID = peerList[i].ID
  35. }
  36. }
  37. }
  38. //Checks and returns true if maximum peerID is equal to the local peerID
  39. if maxPeerID == peerID {
  40. return true, nil
  41. }
  42. return false, nil
  43. }
  44. // IsLeader returns true or false based on whether the node is the leader of the cluster or not
  45. func (g *GD2) IsLeader() (bool, error) {
  46. peerList, err := g.Peers()
  47. if err != nil {
  48. return false, err
  49. }
  50. peerID, err := g.LocalPeerID()
  51. if err != nil {
  52. return false, err
  53. }
  54. for _, pr := range peerList {
  55. if pr.Online {
  56. if peerID == pr.ID {
  57. return true, nil
  58. }
  59. return false, nil
  60. }
  61. }
  62. // This would imply none of the peers are online and return false
  63. return false, nil
  64. }
  65. // MakeGluster returns respective gluster obj based on configuration
  66. func MakeGluster(expConf *conf.Config) (gi GInterface) {
  67. gConfig := expConf.GConfig()
  68. if gConfig == nil {
  69. return nil
  70. }
  71. setDefaultConfig(gConfig)
  72. gi = &GD2{config: gConfig}
  73. if gConfig.GlusterMgmt == "" || gConfig.GlusterMgmt == glusterconsts.MgmtGlusterd {
  74. gi = &GD1{config: gConfig}
  75. }
  76. cacheTTL := time.Duration(expConf.CacheTTL) * time.Second
  77. cachedGI := NewGCacheWithTTL(gi, cacheTTL)
  78. cachedGI.EnableCacheForFuncs(expConf.CacheEnabledFuncs)
  79. return cachedGI
  80. }
  81. func readPeerID(fileStream io.ReadCloser, keywordID string) (string, error) {
  82. defer func() {
  83. err := fileStream.Close()
  84. if err != nil {
  85. // TODO: Log here
  86. return
  87. }
  88. }()
  89. scanner := bufio.NewScanner(fileStream)
  90. for scanner.Scan() {
  91. lines := strings.Split(scanner.Text(), "\n")
  92. for _, line := range lines {
  93. if strings.Contains(line, keywordID) {
  94. parts := strings.Split(line, "=")
  95. unformattedPeerID := parts[1]
  96. peerID := peerIDPattern.FindString(unformattedPeerID)
  97. if peerID == "" {
  98. return "", errors.New("unable to find peer address")
  99. }
  100. return peerID, nil
  101. }
  102. }
  103. }
  104. return "", errors.New("unable to find peer address")
  105. }
  106. // LocalPeerID returns local peer ID of glusterd
  107. func (g *GD1) LocalPeerID() (string, error) {
  108. keywordID := "UUID"
  109. peeridFile := g.config.GlusterdWorkdir + "/glusterd.info"
  110. fileStream, err := os.Open(filepath.Clean(peeridFile))
  111. if err != nil {
  112. return "", err
  113. }
  114. return readPeerID(fileStream, keywordID)
  115. }
  116. // LocalPeerID returns local peer ID of glusterd2
  117. func (g *GD2) LocalPeerID() (string, error) {
  118. keywordID := "peer-id"
  119. peeridFile := g.config.GlusterdWorkdir + "/uuid.toml"
  120. fileStream, err := os.Open(filepath.Clean(peeridFile))
  121. if err != nil {
  122. return "", err
  123. }
  124. return readPeerID(fileStream, keywordID)
  125. }
  126. // GetClusterID returns local clusterd ID
  127. func GetClusterID() (clusterID string) {
  128. if clusterID = os.Getenv(glusterconsts.EnvGlusterClusterID); clusterID == "" {
  129. clusterID = glusterconsts.DefaultGlusterClusterID
  130. }
  131. return
  132. }
  133. // GConfig method returns the configuration
  134. // this implements the 'conf.GConfigInterface'
  135. func (g *GD1) GConfig() *conf.GConfig {
  136. return g.config
  137. }
  138. // GConfig method returns the configuration
  139. // this implements the 'conf.GConfigInterface'
  140. func (g *GD2) GConfig() *conf.GConfig {
  141. return g.config
  142. }
  143. // GetGlusterVersion gets the glusterfs version
  144. func GetGlusterVersion() (string, error) {
  145. cmd := "glusterfs --version | head -1"
  146. bytes, err := ExecuteCmd(cmd)
  147. if err != nil {
  148. return "", err
  149. }
  150. stdout := string(bytes[:])
  151. fields := strings.Fields(stdout)
  152. return fields[1], err
  153. }
  154. // ExecuteCmd enables to execute system cmds and returns stdout, err
  155. func ExecuteCmd(cmd string) ([]byte, error) {
  156. cmdfields := strings.Fields(cmd)
  157. cmdstr := cmdfields[0]
  158. if fullcmd, err := exec.LookPath(cmdfields[0]); err == nil {
  159. cmdstr = fullcmd
  160. }
  161. args := cmdfields[1:]
  162. out, err := exec.Command(cmdstr, args...).Output() // #nosec
  163. return out, err
  164. }