| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package hprest
- import (
- "context"
- "fmt"
- "strings"
- "time"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/netutils"
- "yunion.io/x/pkg/utils"
- "yunion.io/x/onecloud/pkg/httperrors"
- "yunion.io/x/onecloud/pkg/util/redfish"
- )
- const (
- basePath = "/rest/v1"
- linkKey = "href"
- memberKey = "Member"
- versionKey = "ServiceVersion"
- )
- type SHpRestApiFactory struct {
- }
- func (f *SHpRestApiFactory) Name() string {
- return "HpRest"
- }
- func (f *SHpRestApiFactory) NewApi(endpoint, username, password string, debug bool) redfish.IRedfishDriver {
- return NewHpRestApi(endpoint, username, password, debug)
- }
- func init() {
- redfish.RegisterApiFactory(&SHpRestApiFactory{})
- }
- type SHpRestApi struct {
- redfish.SBaseRedfishClient
- }
- func NewHpRestApi(endpoint, username, password string, debug bool) redfish.IRedfishDriver {
- api := &SHpRestApi{
- SBaseRedfishClient: redfish.NewBaseRedfishClient(endpoint, username, password, debug),
- }
- api.SetVirtualObject(api)
- return api
- }
- func (r *SHpRestApi) BasePath() string {
- return basePath
- }
- func (r *SHpRestApi) GetParent(parent jsonutils.JSONObject) jsonutils.JSONObject {
- obj, _ := parent.Get("links")
- if obj != nil {
- return obj
- }
- return jsonutils.NewDict()
- }
- func (r *SHpRestApi) VersionKey() string {
- return versionKey
- }
- func (r *SHpRestApi) LinkKey() string {
- return linkKey
- }
- func (r *SHpRestApi) MemberKey() string {
- return memberKey
- }
- func (r *SHpRestApi) LogItemsKey() string {
- return "Items"
- }
- func (r *SHpRestApi) Probe(ctx context.Context) error {
- err := r.SBaseRedfishClient.Probe(ctx)
- if err != nil {
- return errors.Wrap(err, "r.SBaseRedfishClient.Probe")
- }
- resp, err := r.Get(ctx, "/rest/v1/resourcedirectory")
- if err != nil {
- return errors.Wrap(err, "Get /rest/v1/resourcedirectory")
- }
- if r.IsDebug {
- log.Debugf("%s", resp.PrettyString())
- }
- return nil
- }
- func (r *SHpRestApi) GetVirtualCdromInfo(ctx context.Context) (string, redfish.SCdromInfo, error) {
- path, cdInfo, err := r.SBaseRedfishClient.GetVirtualCdromInfo(ctx)
- if err == nil {
- cdInfo.SupportAction = true
- }
- return path, cdInfo, err
- }
- func (r *SHpRestApi) GetSystemInfo(ctx context.Context) (string, redfish.SSystemInfo, error) {
- sysInfo := redfish.SSystemInfo{}
- path, resp, err := r.GetResource(ctx, "Systems", "0")
- if err != nil {
- return path, sysInfo, errors.Wrap(err, "r.GetResource Systems")
- }
- err = resp.Unmarshal(&sysInfo)
- if err != nil {
- return path, sysInfo, errors.Wrap(err, "resp.Unmarshal")
- }
- memGB, _ := resp.Int("Memory", "TotalSystemMemoryGB")
- sysInfo.MemoryGB = int(memGB)
- cpuCnt, _ := resp.Int("Processors", "Count")
- cpuDesc, _ := resp.GetString("Processors", "ProcessorFamily")
- sysInfo.NodeCount = int(cpuCnt)
- sysInfo.CpuDesc = strings.TrimSpace(cpuDesc)
- power, _ := resp.GetString("Power")
- sysInfo.PowerState = strings.TrimSpace(power)
- sysInfo.SerialNumber = strings.TrimSpace(sysInfo.SerialNumber)
- sysInfo.SKU = strings.TrimSpace(sysInfo.SKU)
- sysInfo.Model = strings.TrimSpace(sysInfo.Model)
- sysInfo.Manufacturer = strings.TrimSpace(sysInfo.Manufacturer)
- nextBootDev, _ := resp.GetString("Boot", "BootSourceOverrideTarget")
- sysInfo.NextBootDev = strings.TrimSpace(nextBootDev)
- nextBootDevSupports, _ := resp.GetArray("Boot", "BootSourceOverrideSupported")
- sysInfo.NextBootDevSupported = make([]string, len(nextBootDevSupports))
- for i := range nextBootDevSupports {
- devStr, _ := nextBootDevSupports[i].GetString()
- sysInfo.NextBootDevSupported[i] = devStr
- }
- AvailableActions, _ := resp.GetArray("AvailableActions")
- if AvailableActions != nil {
- resetCapabilities, _ := AvailableActions[0].GetArray("Capabilities")
- if resetCapabilities != nil {
- resetTypeValues, _ := resetCapabilities[0].GetArray("AllowableValues")
- sysInfo.ResetTypeSupported = make([]string, len(resetTypeValues))
- for i := range resetTypeValues {
- resetTypeStr, _ := resetTypeValues[i].GetString()
- sysInfo.ResetTypeSupported[i] = resetTypeStr
- }
- }
- }
- macArray, _ := resp.GetArray("HostCorrelation", "HostMACAddress")
- if len(macArray) > 0 {
- sysInfo.EthernetNICs = make([]string, len(macArray))
- for i := range macArray {
- macAddr, _ := macArray[i].GetString()
- sysInfo.EthernetNICs[i] = netutils.FormatMacAddr(macAddr)
- }
- }
- return path, sysInfo, nil
- }
- func (r *SHpRestApi) Reset(ctx context.Context, action string) error {
- path, sysInfo, err := r.IRedfishDriver().GetSystemInfo(ctx)
- if err != nil {
- return errors.Wrap(err, "r.GetSystemInfo")
- }
- if !utils.IsInStringArray(action, sysInfo.ResetTypeSupported) {
- return errors.Wrapf(httperrors.ErrBadRequest, "%s not supported: %s", action, sysInfo.ResetTypeSupported)
- }
- params := jsonutils.NewDict()
- params.Add(jsonutils.NewString(action), "ResetType")
- params.Add(jsonutils.NewString("Reset"), "Action")
- _, resp, err := r.Post(ctx, path, params)
- if err != nil {
- return errors.Wrap(err, "Action.Reset")
- }
- if r.IsDebug {
- log.Debugf("%s", resp)
- }
- return nil
- }
- func (r *SHpRestApi) BmcReset(ctx context.Context) error {
- path, _, err := r.GetResource(ctx, "Managers", "0")
- if err != nil {
- return errors.Wrap(err, "r.GetSystemInfo")
- }
- params := jsonutils.NewDict()
- params.Add(jsonutils.NewString("Reset"), "Action")
- _, resp, err := r.Post(ctx, path, params)
- if err != nil {
- return errors.Wrap(err, "Actions/Manager.Reset")
- }
- log.Debugf("%s", resp)
- return nil
- }
- func (r *SHpRestApi) readLogs(ctx context.Context, subsys string, since time.Time) ([]redfish.SEvent, error) {
- _, manager, err := r.GetResource(ctx, subsys, "0", "Logs", "0")
- if err != nil {
- return nil, errors.Wrap(err, "GetResource Managers 0")
- }
- manager = r.IRedfishDriver().GetParent(manager)
- entries, _ := manager.GetArray("Entries")
- if len(entries) == 0 {
- return nil, errors.Error("no log entries")
- }
- path, _ := entries[0].GetString(r.IRedfishDriver().LinkKey())
- if len(path) == 0 {
- return nil, errors.Wrap(err, "no valid url???")
- }
- nextPath := path
- events := make([]redfish.SEvent, 0)
- for {
- resp, err := r.Get(ctx, nextPath)
- if err != nil {
- return nil, errors.Wrap(err, nextPath)
- }
- tmpEvents := make([]redfish.SEvent, 0)
- err = resp.Unmarshal(&tmpEvents, "Items")
- if err != nil {
- return nil, errors.Wrap(err, "resp.Unmarshal")
- }
- timeBreak := false
- for i := range tmpEvents {
- if !since.IsZero() && tmpEvents[i].Created.Before(since) {
- timeBreak = true
- break
- }
- events = append(events, tmpEvents[i])
- }
- if timeBreak {
- break
- }
- nextPage, _ := resp.Int("links", "NextPage", "page")
- if nextPage > 0 {
- nextPath = fmt.Sprintf("%s?page=%d", path, nextPage)
- } else {
- break
- }
- }
- return events, nil
- }
- func (r *SHpRestApi) ReadSystemLogs(ctx context.Context, since time.Time) ([]redfish.SEvent, error) {
- return r.readLogs(ctx, "Systems", since)
- }
- func (r *SHpRestApi) ReadManagerLogs(ctx context.Context, since time.Time) ([]redfish.SEvent, error) {
- return r.readLogs(ctx, "Managers", since)
- }
- func (r *SHpRestApi) clearLogs(ctx context.Context, subsys string) error {
- path, _, err := r.GetResource(ctx, subsys, "0", "Logs", "0")
- if err != nil {
- return errors.Wrap(err, "GetResource Managers 0")
- }
- params := jsonutils.NewDict()
- params.Add(jsonutils.NewString("ClearLog"), "Action")
- _, resp, err := r.Post(ctx, path, params)
- if err != nil {
- return errors.Wrap(err, "r.Post")
- }
- if r.IsDebug {
- log.Debugf("%s", resp.PrettyString())
- }
- return nil
- }
- func (r *SHpRestApi) ClearSystemLogs(ctx context.Context) error {
- return r.clearLogs(ctx, "Systems")
- }
- func (r *SHpRestApi) ClearManagerLogs(ctx context.Context) error {
- return r.clearLogs(ctx, "Managers")
- }
|