aliecs.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /**
  2. 阿里云ecs实例自动申请、部署、释放
  3. **/
  4. package cluster
  5. import (
  6. "bytes"
  7. "config"
  8. "crypto/hmac"
  9. "crypto/sha1"
  10. "encoding/base64"
  11. "encoding/json"
  12. "fmt"
  13. "hash"
  14. "io"
  15. "io/ioutil"
  16. "log"
  17. "net/http"
  18. "net/url"
  19. qu "qfw/util"
  20. "qfw/util/mongodb"
  21. "sort"
  22. "strings"
  23. "sync"
  24. "time"
  25. )
  26. const (
  27. Password = "Jy_ExtractBid_2019"
  28. URL = "https://ecs.aliyuncs.com"
  29. UseFor = "ocr_task_arr"
  30. )
  31. //批量创建实例
  32. func RunInstances(taskName, computer, flow string, num, hours int) {
  33. if esconfig, ok := config.Sysconfig["esconfig"].(map[string]interface{}); ok {
  34. widthOut := "0"
  35. if flow == "true" {
  36. widthOut = "10"
  37. }
  38. //log.Println(esconfig["LaunchTemplateId"+computer], widthOut)
  39. if b, ok := esconfig["available"].(bool); ok && b {
  40. if zoneIds, _ := esconfig["ZoneIds"].([]interface{}); ok {
  41. pernum := num / len(zoneIds)
  42. if pernum < 1 {
  43. kv, _ := zoneIds[len(zoneIds)-1].(map[string]interface{})
  44. runInstances(kv, taskName, widthOut, computer, num, hours)
  45. } else {
  46. for k, v := range zoneIds {
  47. if (k == len(zoneIds)-1) && (num%len(zoneIds) != 0) {
  48. pernum = num - pernum*(len(zoneIds)-1)
  49. }
  50. kv, _ := v.(map[string]interface{})
  51. runInstances(kv, taskName, widthOut, computer, pernum, hours)
  52. }
  53. }
  54. }
  55. }
  56. }
  57. }
  58. func runInstances(kv map[string]interface{}, taskName, widthOut, computer string, pernum, hours int) {
  59. log.Println(kv, taskName, widthOut, computer, pernum, hours)
  60. res := GET("RunInstances", [][]string{
  61. []string{"RegionId", "cn-beijing"},
  62. []string{"ZoneId", qu.ObjToString(kv["zoneid"])},
  63. []string{"VSwitchId", qu.ObjToString(kv["vswitchid"])},
  64. []string{"LaunchTemplateId", qu.ObjToString(kv["LaunchTemplateId"+computer])},
  65. //[]string{"ImageId", "centos_7_06_64_20G_alibase_20181212.vhd"},
  66. //[]string{"InstanceType", "ecs.ic5.large"},
  67. //[]string{"SecurityGroupId", "sg-bp16x3td2evrejhkshp7"},[]string{"InternetMaxBandwidthIn", "50"},
  68. []string{"InternetMaxBandwidthOut", widthOut},
  69. []string{"InstanceChargeType", "PostPaid"},
  70. []string{"SpotStrategy", "SpotWithPriceLimit"},
  71. []string{"SpotPriceLimit", "4.99"},
  72. []string{"InstanceName", UseFor},
  73. []string{"UniqueSuffix", "true"},
  74. []string{"Password", Password},
  75. []string{"Amount", fmt.Sprint(pernum)},
  76. []string{"AutoReleaseTime", time.Now().Add(time.Duration(hours) * time.Hour).Local().Format("2006-01-02T15:04:05Z")},
  77. })
  78. if tmp, ok := res["InstanceIdSets"].(map[string]interface{}); ok {
  79. if t, ok := tmp["InstanceIdSet"].([]interface{}); ok {
  80. //实例id持久化
  81. for _, v := range t {
  82. mongodb.Save("ocr_ecs", map[string]interface{}{
  83. "InstanceId": v,
  84. "TaskName": taskName,
  85. "UseFor": UseFor,
  86. "OcrTaskStatus": "none",
  87. })
  88. mongodb.Save("ocr_ecs_bak", map[string]interface{}{
  89. "InstanceId": v,
  90. "TaskName": taskName,
  91. "UseFor": UseFor,
  92. "OcrTaskStatus": "none",
  93. })
  94. }
  95. }
  96. }
  97. //log.Println(res)
  98. }
  99. //var CID = map[string]string{}
  100. var CID sync.Map
  101. //查询多台实例的详细信息
  102. func DescribeInstances() {
  103. res := GET("DescribeInstances", [][]string{
  104. []string{"RegionId", "cn-beijing"},
  105. []string{"InstanceChargeType", "PostPaid"},
  106. []string{"PageSize", "100"},
  107. })
  108. //CID = make(map[string]string)
  109. for _, ins := range res["Instances"].(map[string]interface{}) {
  110. for _, val := range ins.([]interface{}) {
  111. if tmp, ok := val.(map[string]interface{}); ok {
  112. if t, ok := tmp["VpcAttributes"].(map[string]interface{}); ok {
  113. if tt, ok := t["PrivateIpAddress"].(map[string]interface{}); ok {
  114. ttt := tt["IpAddress"].([]interface{})
  115. tmp["ip_nw"] = ttt[0]
  116. }
  117. }
  118. if t, ok := tmp["PublicIpAddress"].(map[string]interface{}); ok {
  119. if tt, ok := t["IpAddress"].([]interface{}); ok && len(tt) > 0 {
  120. tmp["ip_ww"] = tt[0]
  121. }
  122. }
  123. if strings.Contains(qu.ObjToString(tmp["InstanceName"]), "ocr_task") {
  124. log.Println("更新申请实例", tmp["InstanceId"], "内网ip", tmp["ip_nw"])
  125. //config.Sys.Lock()
  126. //CID[qu.ObjToString(tmp["InstanceId"])] = qu.ObjToString(tmp["ip_nw"])
  127. //config.Sys.Unlock()
  128. CID.Store(qu.ObjToString(tmp["InstanceId"]),qu.ObjToString(tmp["ip_nw"]))
  129. //更新实例信息
  130. mongodb.Update("ocr_ecs", `{"InstanceId":"`+qu.ObjToString(tmp["InstanceId"])+`"}`, map[string]interface{}{"$set": tmp}, true, false)
  131. mongodb.Update("ocr_ecs_bak", `{"InstanceId":"`+qu.ObjToString(tmp["InstanceId"])+`"}`, map[string]interface{}{"$set": tmp}, true, false)
  132. }
  133. }
  134. }
  135. }
  136. }
  137. //停止实例
  138. func StopInstance(InstanceId string) {
  139. res := GET("StopInstance", [][]string{
  140. []string{"InstanceId", InstanceId},
  141. })
  142. mongodb.Update("ocr_ecs", `{"InstanceId":"`+InstanceId+`"}`, map[string]interface{}{"$set": map[string]interface{}{"Status": "Released"}}, true, false)
  143. log.Println("StopInstance", res)
  144. }
  145. //释放实例
  146. func DeleteInstance(InstanceId string) {
  147. res := GET("DeleteInstance", [][]string{
  148. []string{"InstanceId", InstanceId},
  149. []string{"Force", "true"},
  150. })
  151. mongodb.Del("ocr_ecs", `{"InstanceId":"`+InstanceId+`"}`)
  152. log.Println("DeleteInstance", res)
  153. }
  154. //实例自动释放时间
  155. func ModifyInstanceAutoReleaseTime(InstanceId string, hours int) {
  156. res := GET("ModifyInstanceAutoReleaseTime", [][]string{
  157. []string{"InstanceId", InstanceId},
  158. []string{"AutoReleaseTime", time.Now().Add(time.Duration(hours) * time.Hour).UTC().Format("2006-01-02T15:04:05Z")},
  159. })
  160. log.Println("ModifyInstanceAutoReleaseTime", res)
  161. }
  162. //GET请求
  163. func GET(action string, param [][]string) (mres map[string]interface{}) {
  164. esconfig, _ := config.Sysconfig["esconfig"].(map[string]interface{})
  165. ps := &paramSorter{[]string{
  166. "Format",
  167. "Version",
  168. "SignatureMethod",
  169. "SignatureNonce",
  170. "SignatureVersion",
  171. "AccessKeyId",
  172. "Timestamp",
  173. }, []string{
  174. "JSON",
  175. "2014-05-26",
  176. "HMAC-SHA1",
  177. fmt.Sprintf("%d", time.Now().UnixNano()/1000),
  178. "1.0",
  179. qu.ObjToString(esconfig["AccessID"]),
  180. time.Now().UTC().Format("2006-01-02T15:04:05Z"),
  181. }}
  182. ps.Keys = append(ps.Keys, "Action")
  183. ps.Vals = append(ps.Vals, action)
  184. if len(param) > 0 {
  185. for _, v := range param {
  186. ps.Keys = append(ps.Keys, v[0])
  187. ps.Vals = append(ps.Vals, v[1])
  188. }
  189. }
  190. ps.Sort()
  191. reqStr := ps.String()
  192. str := "GET&" +
  193. percentEncode("/") + "&" +
  194. percentEncode(reqStr)
  195. str = SP(str, "%3A", "%253A", -1)
  196. h := hmac.New(func() hash.Hash { return sha1.New() }, []byte(qu.ObjToString(esconfig["AccessSecret"])+"&"))
  197. io.WriteString(h, str)
  198. signedStr := base64.StdEncoding.EncodeToString(h.Sum(nil))
  199. ps.Keys = append(ps.Keys, "Signature")
  200. ps.Vals = append(ps.Vals, signedStr)
  201. reqStr = ps.Query()
  202. res, err := http.Get(fmt.Sprintf("%s?%s", URL, reqStr))
  203. if err != nil {
  204. log.Println(err.Error())
  205. } else {
  206. defer res.Body.Close()
  207. bt, err := ioutil.ReadAll(res.Body)
  208. if err == nil {
  209. //log.Println(string(bt))
  210. err := json.Unmarshal(bt, &mres)
  211. if err != nil {
  212. log.Println(err.Error())
  213. }
  214. }
  215. }
  216. return
  217. }
  218. var SP = strings.Replace
  219. func percentEncode(str string) string {
  220. str = url.QueryEscape(str)
  221. str = SP(SP(SP(str, "+", "%20", -1), "*", "%2A", -1), "%7E", "~", -1)
  222. return str
  223. }
  224. type paramSorter struct {
  225. Keys []string
  226. Vals []string
  227. }
  228. func (ps *paramSorter) String() string {
  229. str := ""
  230. for n, k := range ps.Keys {
  231. str += k + "=" + ps.Vals[n]
  232. if n < len(ps.Keys)-1 {
  233. str += "&"
  234. }
  235. }
  236. return str
  237. }
  238. func (ps *paramSorter) Query() string {
  239. str := ""
  240. for n, k := range ps.Keys {
  241. str += k + "=" + url.QueryEscape(ps.Vals[n])
  242. if n < len(ps.Keys)-1 {
  243. str += "&"
  244. }
  245. }
  246. return str
  247. }
  248. func (ps *paramSorter) Sort() {
  249. sort.Sort(ps)
  250. }
  251. func (ps *paramSorter) Len() int {
  252. return len(ps.Vals)
  253. }
  254. func (ps *paramSorter) Less(i, j int) bool {
  255. return bytes.Compare([]byte(ps.Keys[i]), []byte(ps.Keys[j])) < 0
  256. }
  257. func (ps *paramSorter) Swap(i, j int) {
  258. ps.Vals[i], ps.Vals[j] = ps.Vals[j], ps.Vals[i]
  259. ps.Keys[i], ps.Keys[j] = ps.Keys[j], ps.Keys[i]
  260. }