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:
Zexi Li
2020-04-11 13:12:18 +08:00
committed by GitHub
10 changed files with 247 additions and 15 deletions
+5 -4
View File
@@ -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
}
+12 -1
View File
@@ -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
}
+3 -1
View File
@@ -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 {
+1 -1
View File
@@ -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"`
+70
View File
@@ -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
}
+30 -4
View File
@@ -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")
+15
View File
@@ -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"
+104
View File
@@ -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"
}
+1
View File
@@ -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"
)
+6 -4
View File
@@ -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())