idrac.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package bmconsole
  15. import (
  16. "context"
  17. "fmt"
  18. "net/http"
  19. "net/url"
  20. "regexp"
  21. "strings"
  22. "time"
  23. "yunion.io/x/log"
  24. "yunion.io/x/pkg/errors"
  25. "yunion.io/x/pkg/util/httputils"
  26. "yunion.io/x/onecloud/pkg/httperrors"
  27. )
  28. func (r *SBMCConsole) GetIdracConsoleJNLP(ctx context.Context, sku, model string) (string, error) {
  29. if len(model) > 0 {
  30. parts := strings.Split(model, " ")
  31. if len(parts) > 1 && parts[1][0] == 'R' && len(parts[1]) >= 4 {
  32. // PownerEdge R730
  33. switch parts[1][2] {
  34. case '1':
  35. return r.GetIdrac6ConsoleJNLP(ctx, sku, model)
  36. case '2', '3':
  37. return r.GetIdrac7ConsoleJNLP(ctx, sku, model)
  38. default:
  39. return r.GetIdrac9ConsoleJNLP(ctx)
  40. }
  41. }
  42. }
  43. jnlp, err := r.GetIdrac7ConsoleJNLP(ctx, sku, model)
  44. if err == nil {
  45. return jnlp, nil
  46. }
  47. jnlp, err = r.GetIdrac9ConsoleJNLP(ctx)
  48. if err == nil {
  49. return jnlp, nil
  50. }
  51. return r.GetIdrac6ConsoleJNLP(ctx, sku, model)
  52. }
  53. func (r *SBMCConsole) GetIdrac7ConsoleJNLP(ctx context.Context, sku, model string) (string, error) {
  54. loginData := strings.Join([]string{
  55. "user=" + url.QueryEscape(r.username),
  56. "password=" + url.QueryEscape(r.password),
  57. }, "&")
  58. // cookie:
  59. // -http-session-=::http.session::0103fd02ceac2d642361b6fdcd4a5994;
  60. // sysidledicon=ledIcon%20grayLed;
  61. // tokenvalue=478be97abdaeb4d454c0418fcca9094d
  62. cookies := make(map[string]string)
  63. // cookies["-http-session-"] = ""
  64. // first do html login
  65. postHdr := http.Header{}
  66. postHdr.Set("Content-Type", "application/x-www-form-urlencoded")
  67. setCookieHeader(postHdr, cookies)
  68. hdr, loginResp, err := r.RawRequest(ctx, httputils.POST, "/data/login", postHdr, []byte(loginData))
  69. if err != nil {
  70. return "", errors.Wrap(err, "r.FormPost Login")
  71. }
  72. log.Debugf("Header: %s %s", hdr, loginResp)
  73. if setCookies, ok := hdr["Set-Cookie"]; ok {
  74. for _, cookieHdr := range setCookies {
  75. parts := strings.Split(cookieHdr, ";")
  76. if len(parts) > 0 {
  77. pparts := strings.Split(parts[0], "=")
  78. if len(pparts) > 1 {
  79. cookies[pparts[0]] = pparts[1]
  80. }
  81. }
  82. }
  83. } else {
  84. // find no cookie
  85. }
  86. forwardUrlPattern := regexp.MustCompile(`<forwardUrl>(.*)</forwardUrl>`)
  87. matched := forwardUrlPattern.FindAllStringSubmatch(string(loginResp), -1)
  88. indexUrlStr := ""
  89. if len(matched) > 0 && len(matched[0]) > 1 {
  90. indexUrlStr = matched[0][1]
  91. }
  92. if len(indexUrlStr) == 0 {
  93. return "", errors.Wrapf(httperrors.ErrBadRequest, "no valid forwardUrl")
  94. }
  95. tokenPattern := regexp.MustCompile(`ST1=(\w+),ST2=`)
  96. matched = tokenPattern.FindAllStringSubmatch(indexUrlStr, -1)
  97. log.Debugf("%s", matched)
  98. token := ""
  99. if len(matched) > 0 && len(matched[0]) > 1 {
  100. token = matched[0][1]
  101. }
  102. log.Debugf("token: %s", token)
  103. cookies["tokenvalue"] = token
  104. cookies["batteriesIcon"] = "status_ok"
  105. cookies["fansIcon"] = "status_ok"
  106. cookies["intrusionIcon"] = "status_ok"
  107. cookies["removableFlashMediaIcon"] = "status_ok"
  108. cookies["temperaturesIcon"] = "status_ok"
  109. cookies["voltagesIcon"] = "status_ok"
  110. cookies["powerSuppliesIcon"] = "status_ok"
  111. cookies["sysidledicon"] = "ledIcon grayLed"
  112. getHdr := http.Header{}
  113. setCookieHeader(getHdr, cookies)
  114. getHdr.Set("Referer", fmt.Sprintf("https://%s/sysSummaryData.html", r.host))
  115. getHdr.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
  116. getHdr.Set("Accept-Encoding", "gzip, deflate, br")
  117. getHdr.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
  118. sysStr := url.QueryEscape(fmt.Sprintf("idrac-%s, %s, slot , User: %s", sku, model, r.username))
  119. // sysStr := url.QueryEscape(fmt.Sprintf("idrac-%s, %s, slot , &#29992;&#25143;&#65306; %s", sku, model, r.username))
  120. var path string
  121. if len(token) > 0 {
  122. path = fmt.Sprintf("viewer.jnlp(%s@0@%s@%d@ST1=%s)", r.host, sysStr, time.Now().UnixNano()/1000000, token)
  123. } else {
  124. path = fmt.Sprintf("viewer.jnlp(%s@0@%s@%d)", r.host, sysStr, time.Now().UnixNano()/1000000)
  125. }
  126. _, rspBody, err := r.RawRequest(ctx, httputils.GET, path, getHdr, nil)
  127. if err != nil {
  128. return "", errors.Wrapf(err, "r.RawGet %s", path)
  129. }
  130. return string(rspBody), nil
  131. }