aliecs.go 7.2 KB

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