xugu_deploy.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. package auto
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "os"
  7. "reflect"
  8. "strconv"
  9. "strings"
  10. "sync"
  11. "xg_auto_deploy/internal/config"
  12. "xg_auto_deploy/internal/global"
  13. "xg_auto_deploy/internal/models"
  14. "xg_auto_deploy/internal/remote"
  15. "xg_auto_deploy/internal/utils"
  16. "golang.org/x/crypto/ssh"
  17. )
  18. var wg sync.WaitGroup
  19. func AutoDeployALL() {
  20. global.Logs.Infoln("----------------开始部署----------------------------")
  21. for NodeId, nodeTemp := range global.ServerNodeConfigs {
  22. wg.Add(1)
  23. func(serverNodeConfig models.ServerNodeConfig, serverNodeId string) {
  24. //检查环境
  25. CheckSysEnv(&serverNodeConfig)
  26. CheckAppEnv(&serverNodeConfig)
  27. //上传文件到目标服务器
  28. UploadFileOrDir(serverNodeId, &serverNodeConfig)
  29. //设置xugu.ini
  30. AutoXuguini(&serverNodeConfig)
  31. //设置cluster
  32. if global.ClusterConfigMap["local_file"] != "" || global.ClusterConfigMap["template"] != "" {
  33. AutoCluster(&serverNodeConfig, true)
  34. } else {
  35. global.Logs.Printf("%s节点未设置cluser.ini文件\n", serverNodeConfig.NodeId)
  36. }
  37. defer wg.Done()
  38. }(nodeTemp, NodeId)
  39. }
  40. wg.Wait()
  41. for _, serverNodeConfig := range global.ServerNodeConfigs {
  42. PrintServerNodeEnv(&serverNodeConfig)
  43. }
  44. }
  45. // 上传cluster到目标服务器
  46. func AutoCluster(nodeTemp *models.ServerNodeConfig, onOFF bool) {
  47. if !onOFF {
  48. //获取节点 ,节点ip ,
  49. //获取集群配置文件
  50. return
  51. }
  52. id, err := strconv.Atoi(nodeTemp.NodeId)
  53. if err != nil {
  54. global.Logs.Errorf("%s节点修改cluster文件失败:%s\n", nodeTemp.NodeId, err)
  55. return
  56. }
  57. var ids string
  58. if id < 10 {
  59. ids = fmt.Sprintf("000%s", strconv.Itoa(id))
  60. } else {
  61. ids = fmt.Sprintf("00%s", strconv.Itoa(id))
  62. }
  63. clusterTemp := config.SaveClusterConfigBuffer(global.ClusterInfo, ids)
  64. err = remote.UploadFileBuffer(nodeTemp, clusterTemp, fmt.Sprintf(nodeTemp.XuguAddr+"/SETUP/cluster.ini"))
  65. if err != nil {
  66. global.Logs.Errorf("%s节点上传cluster文件失败:%s\n", nodeTemp.NodeId, err)
  67. }
  68. }
  69. // 上传xugu.ini到目标服务器
  70. func AutoXuguini(nodeTemp *models.ServerNodeConfig) {
  71. xginiLocal := global.XginiConfigMap["local_file"]
  72. // 创建一个 bytes.Buffer
  73. xuguIniBuf := new(bytes.Buffer)
  74. //设置xuguini内存相关优化
  75. setxginiMemory(nodeTemp, false)
  76. //指定上传本地文件xugu.ini,
  77. if xginiLocal != "" {
  78. // 打开文件
  79. file, err := os.Open(xginiLocal)
  80. if err != nil {
  81. global.Logs.Errorf("%s节点打开xugu.ini文件失败:%s\n", nodeTemp.NodeId, err)
  82. panic(err)
  83. }
  84. defer file.Close()
  85. // 将文件内容复制到 buf 中
  86. if _, err := io.Copy(xuguIniBuf, file); err != nil {
  87. global.Logs.Errorf("%s节点修改xugu.ini文件失败:%s\n", nodeTemp.NodeId, err)
  88. panic(err)
  89. }
  90. //将配置文件里[xugu]组下的参数替换xugu.ini文件里的参数
  91. config.SetXginiBuffer(xuguIniBuf, global.XginiConfigMap)
  92. //上传到目标节点
  93. err = remote.UploadFileBuffer(nodeTemp, xuguIniBuf, fmt.Sprintf(nodeTemp.XuguAddr+"/SETUP/xugu.ini"))
  94. if err != nil {
  95. global.Logs.Errorf("%s节点上传xugu.ini文件失败:%s\n", nodeTemp.NodeId, err)
  96. }
  97. } else {
  98. xuguIniDownloadTempbuf := remote.DownloadFileBuffer(nodeTemp, fmt.Sprintf(nodeTemp.XuguAddr+"/SETUP/xugu.ini"))
  99. //将配置文件里[xugu]组下的参数替换xugu.ini文件里的参数
  100. config.SetXginiBuffer(xuguIniDownloadTempbuf, global.XginiConfigMap)
  101. err := remote.UploadFileBuffer(nodeTemp, xuguIniDownloadTempbuf, fmt.Sprintf(nodeTemp.XuguAddr+"/SETUP/xugu.ini"))
  102. if err != nil {
  103. global.Logs.Errorf("%s节点上传xugu.ini文件失败:%s\n", nodeTemp.NodeId, err)
  104. }
  105. }
  106. }
  107. // 设置xugu.ini配置文件中的内存相关
  108. func setxginiMemory(nodeTemp *models.ServerNodeConfig, onOff bool) {
  109. if !onOff {
  110. return
  111. }
  112. // 检测系统内存大小 free -h | awk 'NR==2{print $2}'
  113. memoryTemp, err := remote.SingleCmd(nodeTemp, "free -m | awk 'NR==2{print $4}'")
  114. if err != nil {
  115. global.Logs.Errorf("%s节点系统内存查询失败,取消自动配置xugu.ini:%s\n", nodeTemp.NodeId, err)
  116. }
  117. //分配到XginiMap
  118. memoryTemp = strings.TrimSpace(memoryTemp)
  119. memorySize, err := strconv.Atoi(memoryTemp)
  120. if err != nil {
  121. // 处理转换错误
  122. global.Logs.Errorf("%s节点程序内部计算远端内存大小转换错误::%s\n", nodeTemp.NodeId, err)
  123. return
  124. }
  125. setXgMem := func(memorySize int, para string, fls ...float64) {
  126. if memorySize < 8*1024 {
  127. } else if memorySize <= 32*1024 {
  128. global.XginiConfigMap[para] = strconv.Itoa(int((float64(memorySize) * fls[0] / 1024) * 1024))
  129. } else if memorySize <= 64*1024 {
  130. global.XginiConfigMap[para] = strconv.Itoa(int((float64(memorySize) * fls[1] / 1024) * 1024))
  131. } else if memorySize <= 256*1024 {
  132. global.XginiConfigMap[para] = strconv.Itoa(int((float64(memorySize) * fls[2] / 1024) * 1024))
  133. } else if memorySize <= 1000*1024 {
  134. global.XginiConfigMap[para] = strconv.Itoa(int((float64(memorySize) * fls[3] / 1024) * 1024))
  135. }
  136. }
  137. //判断配置文件是否有该参数
  138. //data_buff_mem
  139. if global.XginiConfigMap["data_buff_mem"] == "" {
  140. setXgMem(memorySize, "data_buff_mem", 0.5, 0.6, 0.7, 0.8)
  141. }
  142. //system_sga_mem
  143. if global.XginiConfigMap["system_sga_mem"] == "" {
  144. setXgMem(memorySize, "system_sga_mem", 0.1, 0.1, 0.1, 0.05)
  145. }
  146. }
  147. // 上传文件到目标服务器
  148. func UploadFileOrDir(serverNodeId string, serverNodeConfig *models.ServerNodeConfig) {
  149. //传送文件
  150. upFiles := func(serverNodeConfig *models.ServerNodeConfig, LocalFile string) {
  151. //检测上传为文件还是文件夹
  152. ret, _ := utils.IsFileOrFolder(LocalFile)
  153. switch ret {
  154. case "file":
  155. err := remote.UploadFile(serverNodeConfig, LocalFile, serverNodeConfig.XuguAddr)
  156. if err != nil {
  157. global.Logs.Fatalf("----- %s节点上传文件失败: %s\n", serverNodeId, err)
  158. return
  159. }
  160. global.Logs.Printf("----- %s节点上传文件成功\n", serverNodeId)
  161. remote.SingleCmd(serverNodeConfig, fmt.Sprintf(`chmod -R +x %s`, serverNodeConfig.XuguAddr))
  162. case "folder":
  163. // 连接到远程主机
  164. client, err := ssh.Dial("tcp", serverNodeConfig.IpPort, serverNodeConfig.SSHClient)
  165. if err != nil {
  166. panic(err)
  167. }
  168. defer client.Close()
  169. // 检测远端文件夹是否存在,不存在则创建 [ ! -d "/DATA2/GT/test" ] && mkdir -p /DATA2/GT/test
  170. remote.SingleCmd(serverNodeConfig, fmt.Sprintf(`[ ! -d "%s" ] && mkdir -p %s`, serverNodeConfig.XuguAddr, serverNodeConfig.XuguAddr))
  171. // 上传文件夹
  172. err = remote.UploadDir(serverNodeConfig, LocalFile, serverNodeConfig.XuguAddr)
  173. if err != nil {
  174. global.Logs.Errorf("----- %s节点上传文件夹错误\n", serverNodeId)
  175. panic(err)
  176. }
  177. global.Logs.Printf("----- %s节点上传文件成功\n", serverNodeId)
  178. remote.SingleCmd(serverNodeConfig, fmt.Sprintf(`chmod -R +x %s`, serverNodeConfig.XuguAddr))
  179. }
  180. }
  181. //检测服务器是什么架构
  182. architecture, err := remote.SingleCmd(serverNodeConfig, "uname -m")
  183. if err != nil {
  184. global.Logs.Printf("检测节点%s 服务器架构失败\n", serverNodeId)
  185. panic(err)
  186. }
  187. if strings.TrimSpace(architecture) == "aarch64" {
  188. fileLocal, err := utils.FindDirWithSubstring("./file/xugu", "aarch64")
  189. if err != nil {
  190. global.Logs.Printf("未查找到虚谷安装包\n")
  191. panic(err)
  192. }
  193. // 传送文件
  194. upFiles(serverNodeConfig, fileLocal)
  195. } else if strings.TrimSpace(architecture) == "x86" || strings.TrimSpace(architecture) == "64" {
  196. fileLocal, err := utils.FindDirWithSubstring("./file/xugu", "aarch64")
  197. if err != nil {
  198. global.Logs.Printf("未查找到虚谷安装包\n")
  199. panic(err)
  200. }
  201. upFiles(serverNodeConfig, fileLocal)
  202. }
  203. }
  204. // 打印节点基础环境
  205. func PrintServerNodeEnv(nodeTemp *models.ServerNodeConfig) {
  206. printFieldNames := func(i interface{}) {
  207. t := reflect.TypeOf(i)
  208. if t.Kind() == reflect.Ptr {
  209. t = t.Elem()
  210. }
  211. for i := 0; i < t.NumField(); i++ {
  212. field := t.Field(i)
  213. //fmt.Println("Field Name:", field.Name)
  214. selectNodeEnvInfo(nodeTemp.SysInfo, field.Name)
  215. }
  216. for i := 0; i < t.NumField(); i++ {
  217. field := t.Field(i)
  218. //fmt.Println("Field Name:", field.Name)
  219. selectNodeEnvInfo(nodeTemp.AppInfo, field.Name)
  220. }
  221. }
  222. //fmt.Printf("节点%s : %s\n", nodeTemp.NodeId, nodeTemp.SysInfo)
  223. global.Logs.Printf("--------------------%s节点--------------------------------------:\n", nodeTemp.NodeId)
  224. // 使用反射打印字段
  225. printFieldNames(nodeTemp.SysInfo)
  226. printFieldNames(nodeTemp.AppInfo)
  227. global.Logs.Printf("--------------------------------------------------------------:\n")
  228. }
  229. func selectNodeEnvInfo(target interface{}, key string) {
  230. switch t := target.(type) {
  231. case *models.SysInfo:
  232. switch key {
  233. case "OsStackSize":
  234. global.Logs.Printf("系统环境Stack size :%s\n", t.OsStackSize)
  235. case "OsOpenFiles":
  236. global.Logs.Printf("系统环境Open files :%s\n", t.OsOpenFiles)
  237. case "CoreWmemDefault":
  238. global.Logs.Printf("系统环境Wmem Default :%s\n", t.CoreWmemDefault)
  239. case "CoreRmemDefault":
  240. global.Logs.Printf("系统环境Rmem Default :%s\n", t.CoreRmemDefault)
  241. case "CoreWmemMax":
  242. global.Logs.Printf("系统环境Wmem Max :%s\n", t.CoreWmemMax)
  243. }
  244. case *models.AppInfo:
  245. // 根据key设置对应字段的值
  246. switch key {
  247. case "Gcc":
  248. global.Logs.Printf("基础包 GCC :%s\n", t.Gcc)
  249. case "Libaio":
  250. global.Logs.Printf("基础包 Libaio :%s\n", t.Libaio)
  251. case "Snmpd":
  252. global.Logs.Printf("基础包 Snmpd :%s\n", t.Snmpd)
  253. case "Ntpd":
  254. global.Logs.Printf("基础包 Ntpd :%s\n", t.Ntpd)
  255. }
  256. }
  257. }