hprest.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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 hprest
  15. import (
  16. "context"
  17. "fmt"
  18. "strings"
  19. "time"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/log"
  22. "yunion.io/x/pkg/errors"
  23. "yunion.io/x/pkg/util/netutils"
  24. "yunion.io/x/pkg/utils"
  25. "yunion.io/x/onecloud/pkg/httperrors"
  26. "yunion.io/x/onecloud/pkg/util/redfish"
  27. )
  28. const (
  29. basePath = "/rest/v1"
  30. linkKey = "href"
  31. memberKey = "Member"
  32. versionKey = "ServiceVersion"
  33. )
  34. type SHpRestApiFactory struct {
  35. }
  36. func (f *SHpRestApiFactory) Name() string {
  37. return "HpRest"
  38. }
  39. func (f *SHpRestApiFactory) NewApi(endpoint, username, password string, debug bool) redfish.IRedfishDriver {
  40. return NewHpRestApi(endpoint, username, password, debug)
  41. }
  42. func init() {
  43. redfish.RegisterApiFactory(&SHpRestApiFactory{})
  44. }
  45. type SHpRestApi struct {
  46. redfish.SBaseRedfishClient
  47. }
  48. func NewHpRestApi(endpoint, username, password string, debug bool) redfish.IRedfishDriver {
  49. api := &SHpRestApi{
  50. SBaseRedfishClient: redfish.NewBaseRedfishClient(endpoint, username, password, debug),
  51. }
  52. api.SetVirtualObject(api)
  53. return api
  54. }
  55. func (r *SHpRestApi) BasePath() string {
  56. return basePath
  57. }
  58. func (r *SHpRestApi) GetParent(parent jsonutils.JSONObject) jsonutils.JSONObject {
  59. obj, _ := parent.Get("links")
  60. if obj != nil {
  61. return obj
  62. }
  63. return jsonutils.NewDict()
  64. }
  65. func (r *SHpRestApi) VersionKey() string {
  66. return versionKey
  67. }
  68. func (r *SHpRestApi) LinkKey() string {
  69. return linkKey
  70. }
  71. func (r *SHpRestApi) MemberKey() string {
  72. return memberKey
  73. }
  74. func (r *SHpRestApi) LogItemsKey() string {
  75. return "Items"
  76. }
  77. func (r *SHpRestApi) Probe(ctx context.Context) error {
  78. err := r.SBaseRedfishClient.Probe(ctx)
  79. if err != nil {
  80. return errors.Wrap(err, "r.SBaseRedfishClient.Probe")
  81. }
  82. resp, err := r.Get(ctx, "/rest/v1/resourcedirectory")
  83. if err != nil {
  84. return errors.Wrap(err, "Get /rest/v1/resourcedirectory")
  85. }
  86. if r.IsDebug {
  87. log.Debugf("%s", resp.PrettyString())
  88. }
  89. return nil
  90. }
  91. func (r *SHpRestApi) GetVirtualCdromInfo(ctx context.Context) (string, redfish.SCdromInfo, error) {
  92. path, cdInfo, err := r.SBaseRedfishClient.GetVirtualCdromInfo(ctx)
  93. if err == nil {
  94. cdInfo.SupportAction = true
  95. }
  96. return path, cdInfo, err
  97. }
  98. func (r *SHpRestApi) GetSystemInfo(ctx context.Context) (string, redfish.SSystemInfo, error) {
  99. sysInfo := redfish.SSystemInfo{}
  100. path, resp, err := r.GetResource(ctx, "Systems", "0")
  101. if err != nil {
  102. return path, sysInfo, errors.Wrap(err, "r.GetResource Systems")
  103. }
  104. err = resp.Unmarshal(&sysInfo)
  105. if err != nil {
  106. return path, sysInfo, errors.Wrap(err, "resp.Unmarshal")
  107. }
  108. memGB, _ := resp.Int("Memory", "TotalSystemMemoryGB")
  109. sysInfo.MemoryGB = int(memGB)
  110. cpuCnt, _ := resp.Int("Processors", "Count")
  111. cpuDesc, _ := resp.GetString("Processors", "ProcessorFamily")
  112. sysInfo.NodeCount = int(cpuCnt)
  113. sysInfo.CpuDesc = strings.TrimSpace(cpuDesc)
  114. power, _ := resp.GetString("Power")
  115. sysInfo.PowerState = strings.TrimSpace(power)
  116. sysInfo.SerialNumber = strings.TrimSpace(sysInfo.SerialNumber)
  117. sysInfo.SKU = strings.TrimSpace(sysInfo.SKU)
  118. sysInfo.Model = strings.TrimSpace(sysInfo.Model)
  119. sysInfo.Manufacturer = strings.TrimSpace(sysInfo.Manufacturer)
  120. nextBootDev, _ := resp.GetString("Boot", "BootSourceOverrideTarget")
  121. sysInfo.NextBootDev = strings.TrimSpace(nextBootDev)
  122. nextBootDevSupports, _ := resp.GetArray("Boot", "BootSourceOverrideSupported")
  123. sysInfo.NextBootDevSupported = make([]string, len(nextBootDevSupports))
  124. for i := range nextBootDevSupports {
  125. devStr, _ := nextBootDevSupports[i].GetString()
  126. sysInfo.NextBootDevSupported[i] = devStr
  127. }
  128. AvailableActions, _ := resp.GetArray("AvailableActions")
  129. if AvailableActions != nil {
  130. resetCapabilities, _ := AvailableActions[0].GetArray("Capabilities")
  131. if resetCapabilities != nil {
  132. resetTypeValues, _ := resetCapabilities[0].GetArray("AllowableValues")
  133. sysInfo.ResetTypeSupported = make([]string, len(resetTypeValues))
  134. for i := range resetTypeValues {
  135. resetTypeStr, _ := resetTypeValues[i].GetString()
  136. sysInfo.ResetTypeSupported[i] = resetTypeStr
  137. }
  138. }
  139. }
  140. macArray, _ := resp.GetArray("HostCorrelation", "HostMACAddress")
  141. if len(macArray) > 0 {
  142. sysInfo.EthernetNICs = make([]string, len(macArray))
  143. for i := range macArray {
  144. macAddr, _ := macArray[i].GetString()
  145. sysInfo.EthernetNICs[i] = netutils.FormatMacAddr(macAddr)
  146. }
  147. }
  148. return path, sysInfo, nil
  149. }
  150. func (r *SHpRestApi) Reset(ctx context.Context, action string) error {
  151. path, sysInfo, err := r.IRedfishDriver().GetSystemInfo(ctx)
  152. if err != nil {
  153. return errors.Wrap(err, "r.GetSystemInfo")
  154. }
  155. if !utils.IsInStringArray(action, sysInfo.ResetTypeSupported) {
  156. return errors.Wrapf(httperrors.ErrBadRequest, "%s not supported: %s", action, sysInfo.ResetTypeSupported)
  157. }
  158. params := jsonutils.NewDict()
  159. params.Add(jsonutils.NewString(action), "ResetType")
  160. params.Add(jsonutils.NewString("Reset"), "Action")
  161. _, resp, err := r.Post(ctx, path, params)
  162. if err != nil {
  163. return errors.Wrap(err, "Action.Reset")
  164. }
  165. if r.IsDebug {
  166. log.Debugf("%s", resp)
  167. }
  168. return nil
  169. }
  170. func (r *SHpRestApi) BmcReset(ctx context.Context) error {
  171. path, _, err := r.GetResource(ctx, "Managers", "0")
  172. if err != nil {
  173. return errors.Wrap(err, "r.GetSystemInfo")
  174. }
  175. params := jsonutils.NewDict()
  176. params.Add(jsonutils.NewString("Reset"), "Action")
  177. _, resp, err := r.Post(ctx, path, params)
  178. if err != nil {
  179. return errors.Wrap(err, "Actions/Manager.Reset")
  180. }
  181. log.Debugf("%s", resp)
  182. return nil
  183. }
  184. func (r *SHpRestApi) readLogs(ctx context.Context, subsys string, since time.Time) ([]redfish.SEvent, error) {
  185. _, manager, err := r.GetResource(ctx, subsys, "0", "Logs", "0")
  186. if err != nil {
  187. return nil, errors.Wrap(err, "GetResource Managers 0")
  188. }
  189. manager = r.IRedfishDriver().GetParent(manager)
  190. entries, _ := manager.GetArray("Entries")
  191. if len(entries) == 0 {
  192. return nil, errors.Error("no log entries")
  193. }
  194. path, _ := entries[0].GetString(r.IRedfishDriver().LinkKey())
  195. if len(path) == 0 {
  196. return nil, errors.Wrap(err, "no valid url???")
  197. }
  198. nextPath := path
  199. events := make([]redfish.SEvent, 0)
  200. for {
  201. resp, err := r.Get(ctx, nextPath)
  202. if err != nil {
  203. return nil, errors.Wrap(err, nextPath)
  204. }
  205. tmpEvents := make([]redfish.SEvent, 0)
  206. err = resp.Unmarshal(&tmpEvents, "Items")
  207. if err != nil {
  208. return nil, errors.Wrap(err, "resp.Unmarshal")
  209. }
  210. timeBreak := false
  211. for i := range tmpEvents {
  212. if !since.IsZero() && tmpEvents[i].Created.Before(since) {
  213. timeBreak = true
  214. break
  215. }
  216. events = append(events, tmpEvents[i])
  217. }
  218. if timeBreak {
  219. break
  220. }
  221. nextPage, _ := resp.Int("links", "NextPage", "page")
  222. if nextPage > 0 {
  223. nextPath = fmt.Sprintf("%s?page=%d", path, nextPage)
  224. } else {
  225. break
  226. }
  227. }
  228. return events, nil
  229. }
  230. func (r *SHpRestApi) ReadSystemLogs(ctx context.Context, since time.Time) ([]redfish.SEvent, error) {
  231. return r.readLogs(ctx, "Systems", since)
  232. }
  233. func (r *SHpRestApi) ReadManagerLogs(ctx context.Context, since time.Time) ([]redfish.SEvent, error) {
  234. return r.readLogs(ctx, "Managers", since)
  235. }
  236. func (r *SHpRestApi) clearLogs(ctx context.Context, subsys string) error {
  237. path, _, err := r.GetResource(ctx, subsys, "0", "Logs", "0")
  238. if err != nil {
  239. return errors.Wrap(err, "GetResource Managers 0")
  240. }
  241. params := jsonutils.NewDict()
  242. params.Add(jsonutils.NewString("ClearLog"), "Action")
  243. _, resp, err := r.Post(ctx, path, params)
  244. if err != nil {
  245. return errors.Wrap(err, "r.Post")
  246. }
  247. if r.IsDebug {
  248. log.Debugf("%s", resp.PrettyString())
  249. }
  250. return nil
  251. }
  252. func (r *SHpRestApi) ClearSystemLogs(ctx context.Context) error {
  253. return r.clearLogs(ctx, "Systems")
  254. }
  255. func (r *SHpRestApi) ClearManagerLogs(ctx context.Context) error {
  256. return r.clearLogs(ctx, "Managers")
  257. }