aliecs.go 6.3 KB

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