mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-21 14:19:49 +08:00
Merge pull request #5753 from swordqiu/automated-cherry-pick-of-#5745-upstream-release-3.1
Automated cherry pick of #5745: feature: redfish support IDRAC9 baremetal
This commit is contained in:
@@ -189,10 +189,11 @@ func (job *SLogFetchJob) Do(ctx context.Context, now time.Time) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetchLogs api.EVENT_TYPE_SYSTEM")
|
||||
}
|
||||
err = fetchLogs(job.baremetal, ctx, redfish.EVENT_TYPE_MANAGER)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetchLogs api.EVENT_TYPE_MANAGER")
|
||||
}
|
||||
// no longer fetch management logs
|
||||
// err = fetchLogs(job.baremetal, ctx, redfish.EVENT_TYPE_MANAGER)
|
||||
// if err != nil {
|
||||
// return errors.Wrap(err, "fetchLogs api.EVENT_TYPE_MANAGER")
|
||||
// }
|
||||
job.lastTime = now
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1235,7 +1235,12 @@ func (b *SBaremetalInstance) enableWire(mac net.HardwareAddr, ipAddr string, nic
|
||||
|
||||
func (b *SBaremetalInstance) GetIPMIConfig() *types.SIPMIInfo {
|
||||
conf := b.GetRawIPMIConfig()
|
||||
if conf == nil || conf.Password == "" {
|
||||
if conf == nil {
|
||||
log.Debugf("GetIPMIConfig conf is nil")
|
||||
return nil
|
||||
}
|
||||
if conf.Password == "" {
|
||||
log.Debugf("GetIPMIConfig password is nil")
|
||||
return nil
|
||||
}
|
||||
if conf.Username == "" {
|
||||
@@ -1254,6 +1259,7 @@ func (b *SBaremetalInstance) GetIPMIConfig() *types.SIPMIInfo {
|
||||
}
|
||||
conf.Password = utils.Unquote(conf.Password) // XXX: remove quotes!!!
|
||||
if conf.IpAddr == "" {
|
||||
log.Debugf("GetIPMIConfig ipaddr s nil")
|
||||
return nil
|
||||
}
|
||||
return conf
|
||||
@@ -1336,6 +1342,7 @@ func (b *SBaremetalInstance) SetExistingIPMIIPAddr(ipAddr string) {
|
||||
func (b *SBaremetalInstance) GetIPMITool() *ipmitool.LanPlusIPMI {
|
||||
conf := b.GetIPMIConfig()
|
||||
if conf == nil {
|
||||
log.Debugf("GetIPMIConfig is nil")
|
||||
return nil
|
||||
}
|
||||
return ipmitool.NewLanPlusIPMI(conf.IpAddr, conf.Username, conf.Password)
|
||||
@@ -1632,6 +1639,10 @@ func (b *SBaremetalInstance) DelayedSyncIPMIInfo(data jsonutils.JSONObject) (jso
|
||||
}
|
||||
|
||||
func (b *SBaremetalInstance) DelayedSyncDesc(data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if data == nil {
|
||||
session := b.manager.GetClientSession()
|
||||
data, _ = b.manager.fetchBaremetal(session, b.GetId())
|
||||
}
|
||||
err := b.SaveDesc(data)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -108,7 +108,9 @@ func (task *sBaremetalPrepareTask) prepareBaremetalInfo(cli *ssh.Client) (*barem
|
||||
if len(raidDiskInfo) > 0 {
|
||||
raidDrivers := []string{}
|
||||
for _, drv := range raidDiskInfo {
|
||||
raidDrivers = append(raidDrivers, drv.Driver)
|
||||
if !utils.IsInStringArray(drv.Driver, raidDrivers) {
|
||||
raidDrivers = append(raidDrivers, drv.Driver)
|
||||
}
|
||||
}
|
||||
storageDriver = strings.Join(raidDrivers, ",")
|
||||
} else {
|
||||
|
||||
@@ -99,7 +99,7 @@ type SHost struct {
|
||||
// SN信息
|
||||
SN string `width:"128" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
|
||||
// CPU大小
|
||||
// CPU核数
|
||||
CpuCount int `nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
// 物理CPU颗数
|
||||
NodeCount int8 `nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// 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 bmconsole
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/httputils"
|
||||
)
|
||||
|
||||
const (
|
||||
IDRAC9_LOGIN_URL = "/sysmgmt/2015/bmc/session"
|
||||
IDRAC9_VCONSOLE_JAVA = "/sysmgmt/2015/server/vconsole?type=Java"
|
||||
)
|
||||
|
||||
func (r *SBMCConsole) GetIdrac9ConsoleJNLP(ctx context.Context) (string, error) {
|
||||
cookies := make(map[string]string)
|
||||
cookies["-http-session-"] = ""
|
||||
|
||||
// first do html login
|
||||
postHdr := http.Header{}
|
||||
postHdr.Set("password", r.password)
|
||||
postHdr.Set("user", r.username)
|
||||
postHdr.Set("Content-Length", "0")
|
||||
setCookieHeader(postHdr, cookies)
|
||||
hdr, _, err := r.RawRequest(ctx, httputils.POST, IDRAC9_LOGIN_URL, postHdr, nil)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "r.FormPost Login")
|
||||
}
|
||||
for _, cookieHdr := range hdr["Set-Cookie"] {
|
||||
parts := strings.Split(cookieHdr, ";")
|
||||
if len(parts) > 0 {
|
||||
pparts := strings.Split(parts[0], "=")
|
||||
if len(pparts) > 1 {
|
||||
cookies[pparts[0]] = pparts[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
// XSRF-TOKEN: a636651fcc8841a3c146cea89730389c
|
||||
xsrfToken := hdr.Get("Xsrf-Token")
|
||||
|
||||
getHdr := http.Header{}
|
||||
setCookieHeader(getHdr, cookies)
|
||||
getHdr.Set("Xsrf-Token", xsrfToken)
|
||||
getHdr.Set("Sec-Fetch-Dest", "empty")
|
||||
getHdr.Set("Sec-Fetch-Mode", "cors")
|
||||
getHdr.Set("Sec-Fetch-Site", "same-origin")
|
||||
_, rspBody, err := r.RawRequest(ctx, httputils.GET, IDRAC9_VCONSOLE_JAVA, getHdr, nil)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "r.RawGet")
|
||||
}
|
||||
|
||||
return string(rspBody), nil
|
||||
}
|
||||
@@ -253,9 +253,22 @@ func (r *SIDracRefishApi) fetchExportConfig(ctx context.Context, target string)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetResource")
|
||||
}
|
||||
urlPath, err := manager.GetString("Actions", "Oem", "OemManager.v1_1_0#OemManager.ExportSystemConfiguration", "target")
|
||||
oemJson, err := manager.GetMap("Actions", "Oem")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "OemManager.v1_1_0#OemManager.ExportSystemConfiguration")
|
||||
return nil, errors.Wrap(err, "GetMap Actions Oem")
|
||||
}
|
||||
var urlPath string
|
||||
for k, conf := range oemJson {
|
||||
if strings.HasSuffix(k, "OemManager.ExportSystemConfiguration") {
|
||||
urlPath, err = conf.GetString("target")
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "find OemManager.ExportSystemConfiguration target")
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(urlPath) == 0 {
|
||||
return nil, errors.Wrap(httperrors.ErrNotFound, "Key OemManager.ExportSystemConfiguration not found")
|
||||
}
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString("JSON"), "ExportFormat")
|
||||
@@ -299,9 +312,22 @@ func (r *SIDracRefishApi) doImportConfig(ctx context.Context, conf iDRACConfig)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetResource")
|
||||
}
|
||||
urlPath, err := manager.GetString("Actions", "Oem", "OemManager.v1_1_0#OemManager.ImportSystemConfiguration", "target")
|
||||
oemJson, err := manager.GetMap("Actions", "Oem")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "OemManager.v1_1_0#OemManager.ImportSystemConfiguration")
|
||||
return errors.Wrap(err, "GetMap Actions Oem")
|
||||
}
|
||||
var urlPath string
|
||||
for k, conf := range oemJson {
|
||||
if strings.HasSuffix(k, "OemManager.ImportSystemConfiguration") {
|
||||
urlPath, err = conf.GetString("target")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "OemManager.ImportSystemConfiguration target")
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(urlPath) == 0 {
|
||||
return errors.Wrap(httperrors.ErrNotFound, "Key OemManager.ImportSystemConfiguration not found")
|
||||
}
|
||||
payload := jsonutils.NewDict()
|
||||
payload.Add(jsonutils.NewString(conf.toXml()), "ImportBuffer")
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// 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 idrac9 // import "yunion.io/x/onecloud/pkg/util/redfish/idrac9"
|
||||
@@ -0,0 +1,104 @@
|
||||
// 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 idrac9
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/redfish"
|
||||
"yunion.io/x/onecloud/pkg/util/redfish/bmconsole"
|
||||
"yunion.io/x/onecloud/pkg/util/redfish/generic"
|
||||
"yunion.io/x/onecloud/pkg/util/redfish/idrac"
|
||||
)
|
||||
|
||||
type SIDrac9RedfishApiFactory struct {
|
||||
}
|
||||
|
||||
func (f *SIDrac9RedfishApiFactory) Name() string {
|
||||
return "iDRAC9"
|
||||
}
|
||||
|
||||
func (f *SIDrac9RedfishApiFactory) NewApi(endpoint, username, password string, debug bool) redfish.IRedfishDriver {
|
||||
return NewIDrac9RedfishApi(endpoint, username, password, debug)
|
||||
}
|
||||
|
||||
func init() {
|
||||
redfish.RegisterApiFactory(&SIDrac9RedfishApiFactory{})
|
||||
}
|
||||
|
||||
type SIDrac9RefishApi struct {
|
||||
idrac.SIDracRefishApi
|
||||
}
|
||||
|
||||
func NewIDrac9RedfishApi(endpoint, username, password string, debug bool) redfish.IRedfishDriver {
|
||||
api := &SIDrac9RefishApi{
|
||||
SIDracRefishApi: idrac.SIDracRefishApi{
|
||||
SGenericRefishApi: generic.SGenericRefishApi{
|
||||
SBaseRedfishClient: redfish.NewBaseRedfishClient(endpoint, username, password, debug),
|
||||
},
|
||||
},
|
||||
}
|
||||
api.SetVirtualObject(api)
|
||||
return api
|
||||
}
|
||||
|
||||
func (r *SIDrac9RefishApi) ParseRoot(root jsonutils.JSONObject) error {
|
||||
// log.Debugf("ParseRoot %s", root.PrettyString())
|
||||
oem, _ := root.Get("Oem", "Dell")
|
||||
if oem != nil {
|
||||
return nil
|
||||
}
|
||||
return errors.Error("not iDrac")
|
||||
}
|
||||
|
||||
func (r *SIDrac9RefishApi) GetNTPConf(ctx context.Context) (redfish.SNTPConf, error) {
|
||||
return r.SGenericRefishApi.GetNTPConf(ctx)
|
||||
}
|
||||
|
||||
func (r *SIDrac9RefishApi) SetNTPConf(ctx context.Context, conf redfish.SNTPConf) error {
|
||||
return r.SGenericRefishApi.SetNTPConf(ctx, conf)
|
||||
}
|
||||
|
||||
func (r *SIDrac9RefishApi) GetConsoleJNLP(ctx context.Context) (string, error) {
|
||||
bmc := bmconsole.NewBMCConsole(r.GetHost(), r.GetUsername(), r.GetPassword(), r.IsDebug)
|
||||
return bmc.GetIdrac9ConsoleJNLP(ctx)
|
||||
}
|
||||
|
||||
func (r *SIDrac9RefishApi) GetSystemLogsPath() string {
|
||||
return "/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Sel/Entries"
|
||||
}
|
||||
|
||||
func (r *SIDrac9RefishApi) GetManagerLogsPath() string {
|
||||
return "/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries"
|
||||
}
|
||||
|
||||
func (r *SIDrac9RefishApi) GetClearSystemLogsPath() string {
|
||||
return "/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Sel/Actions/LogService.ClearLog"
|
||||
}
|
||||
|
||||
func (r *SIDrac9RefishApi) GetClearManagerLogsPath() string {
|
||||
return "/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Actions/LogService.ClearLog"
|
||||
}
|
||||
|
||||
func (r *SIDrac9RefishApi) GetPowerPath() string {
|
||||
return "/redfish/v1/Chassis/System.Embedded.1/Power"
|
||||
}
|
||||
|
||||
func (r *SIDrac9RefishApi) GetThermalPath() string {
|
||||
return "/redfish/v1/Chassis/System.Embedded.1/Thermal"
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
_ "yunion.io/x/onecloud/pkg/util/redfish/generic"
|
||||
_ "yunion.io/x/onecloud/pkg/util/redfish/idrac"
|
||||
_ "yunion.io/x/onecloud/pkg/util/redfish/idrac9"
|
||||
_ "yunion.io/x/onecloud/pkg/util/redfish/ilo"
|
||||
)
|
||||
|
||||
|
||||
@@ -535,10 +535,12 @@ func (r *SBaseRedfishClient) readLogs(ctx context.Context, path string, subsys s
|
||||
for {
|
||||
resp, err := r.Get(ctx, path)
|
||||
if err != nil {
|
||||
if httputils.ErrorCode(err) == 404 {
|
||||
break
|
||||
}
|
||||
return nil, errors.Wrap(err, path)
|
||||
log.Errorf("Get %s fail %s", path, err)
|
||||
break
|
||||
// if httputils.ErrorCode(err) == 404 {
|
||||
// break
|
||||
// }
|
||||
// return nil, errors.Wrap(err, path)
|
||||
}
|
||||
tmpEvents := make([]SEvent, 0)
|
||||
err = resp.Unmarshal(&tmpEvents, r.IRedfishDriver().LogItemsKey())
|
||||
|
||||
Reference in New Issue
Block a user