From 44183fb021fb48934b72acbde9bfe6668f249d6f Mon Sep 17 00:00:00 2001 From: Jian Qiu Date: Sun, 30 Jun 2024 22:22:45 +0800 Subject: [PATCH] feature: support baremetal profile (#20687) Co-authored-by: Qiu Jian --- cmd/climc/shell/compute/baremetal_profiles.go | 50 ++++ pkg/apis/compute/baremetal/doc.go | 15 ++ pkg/apis/compute/baremetal/profiles.go | 165 +++++++++++++ .../compute/baremetal/zz_generated.model.go | 36 +++ pkg/apis/compute/host.go | 2 +- pkg/apis/compute/zz_generated.model.go | 2 + pkg/baremetal/agent.go | 4 +- pkg/baremetal/cronjobs.go | 2 +- pkg/baremetal/handler/delay.go | 6 +- pkg/baremetal/handler/handlers.go | 8 +- pkg/baremetal/handler/middleware.go | 2 +- pkg/baremetal/manager.go | 195 ++++++++------- pkg/baremetal/profiles/profiles.go | 135 ++++------- pkg/baremetal/pxe/dhcp.go | 19 +- pkg/baremetal/pxe/pxe.go | 7 +- pkg/baremetal/tasks/base.go | 10 +- pkg/baremetal/tasks/basedeploy.go | 8 +- pkg/baremetal/tasks/baseprepare.go | 58 +++-- pkg/baremetal/tasks/bm_register.go | 62 ++--- pkg/baremetal/tasks/cdrom.go | 4 +- pkg/baremetal/tasks/create.go | 17 +- pkg/baremetal/tasks/interface.go | 21 +- pkg/baremetal/tasks/ipmiprobe.go | 30 ++- pkg/baremetal/tasks/maintenance.go | 2 +- pkg/baremetal/tasks/prepare.go | 6 +- pkg/baremetal/tasks/reprepare.go | 10 +- pkg/baremetal/tasks/start.go | 4 +- pkg/baremetal/tasks/unmaintenance.go | 6 +- pkg/baremetal/utils/ipmitool/ipmitool.go | 28 +-- pkg/cloudcommon/types/ipmi.go | 2 +- pkg/compute/models/baremetal/doc.go | 15 ++ pkg/compute/models/baremetal/profiles.go | 227 ++++++++++++++++++ pkg/compute/models/initdb.go | 3 + pkg/compute/service/handlers.go | 3 + pkg/hostman/hostinfo/hostdhcp/dhcprelay.go | 3 +- pkg/hostman/hostinfo/hostdhcp/dhcpserver.go | 3 +- pkg/mcclient/modules/compute/baremetal/doc.go | 15 ++ .../baremetal/mod_baremeetalprofile.go | 78 ++++++ pkg/mcclient/options/compute/baremetal/doc.go | 15 ++ .../options/compute/baremetal/profile.go | 36 +++ pkg/util/dhcp/server.go | 6 +- pkg/util/ipmitool/shell/lan.go | 2 +- scripts/codegen.py | 1 + 43 files changed, 995 insertions(+), 328 deletions(-) create mode 100644 cmd/climc/shell/compute/baremetal_profiles.go create mode 100644 pkg/apis/compute/baremetal/doc.go create mode 100644 pkg/apis/compute/baremetal/profiles.go create mode 100644 pkg/apis/compute/baremetal/zz_generated.model.go create mode 100644 pkg/compute/models/baremetal/doc.go create mode 100644 pkg/compute/models/baremetal/profiles.go create mode 100644 pkg/mcclient/modules/compute/baremetal/doc.go create mode 100644 pkg/mcclient/modules/compute/baremetal/mod_baremeetalprofile.go create mode 100644 pkg/mcclient/options/compute/baremetal/doc.go create mode 100644 pkg/mcclient/options/compute/baremetal/profile.go diff --git a/cmd/climc/shell/compute/baremetal_profiles.go b/cmd/climc/shell/compute/baremetal_profiles.go new file mode 100644 index 0000000000..cff8271251 --- /dev/null +++ b/cmd/climc/shell/compute/baremetal_profiles.go @@ -0,0 +1,50 @@ +// 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 compute + +import ( + "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" + "yunion.io/x/pkg/util/printutils" + + "yunion.io/x/onecloud/cmd/climc/shell" + "yunion.io/x/onecloud/pkg/mcclient" + baremetalmodules "yunion.io/x/onecloud/pkg/mcclient/modules/compute/baremetal" + baremetaloptions "yunion.io/x/onecloud/pkg/mcclient/options/compute/baremetal" +) + +func init() { + cmd := shell.NewResourceCmd(&baremetalmodules.BaremetalProfiles) + cmd.List(new(baremetaloptions.BaremetalProfileListOptions)) + cmd.Show(new(baremetaloptions.BaremetalProfileIdOptions)) + cmd.Delete(new(baremetaloptions.BaremetalProfileIdOptions)) + + type BaremetalProfileMatchOpts struct { + OEMNAME string + MODEL string + } + R(&BaremetalProfileMatchOpts{}, "baremetal-profile-match", "find match baremetal profile by oemname and model", func(s *mcclient.ClientSession, args *BaremetalProfileMatchOpts) error { + specs, err := baremetalmodules.BaremetalProfiles.GetMatchProfiles(s, args.OEMNAME, args.MODEL) + if err != nil { + return errors.Wrap(err, "GetMatchProfiles") + } + listResults := printutils.ListResult{} + for _, spec := range specs { + listResults.Data = append(listResults.Data, jsonutils.Marshal(spec)) + } + printList(&listResults, nil) + return nil + }) +} diff --git a/pkg/apis/compute/baremetal/doc.go b/pkg/apis/compute/baremetal/doc.go new file mode 100644 index 0000000000..e2746dc14a --- /dev/null +++ b/pkg/apis/compute/baremetal/doc.go @@ -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 baremetal // import "yunion.io/x/onecloud/pkg/apis/compute/baremetal" diff --git a/pkg/apis/compute/baremetal/profiles.go b/pkg/apis/compute/baremetal/profiles.go new file mode 100644 index 0000000000..285dcad715 --- /dev/null +++ b/pkg/apis/compute/baremetal/profiles.go @@ -0,0 +1,165 @@ +// 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 baremetal + +import ( + "strings" + + "yunion.io/x/onecloud/pkg/apis" + "yunion.io/x/onecloud/pkg/cloudcommon/types" +) + +const ( + DefaultBaremetalProfileId = "default" +) + +type BaremetalProfileListInput struct { + apis.StandaloneAnonResourceListInput + + OemName []string `json:"oem_name"` + Model []string `json:"model"` +} + +func (input *BaremetalProfileListInput) Normalize() { + for i := range input.OemName { + input.OemName[i] = strings.TrimSpace(input.OemName[i]) + } + for i := range input.Model { + input.Model[i] = strings.TrimSpace(input.Model[i]) + } +} + +type BaremetalProfileCreateInput struct { + apis.StandaloneAnonResourceCreateInput + + OemName string + Model string + LanChannel uint8 + RootId int + RootName string + StrongPass bool +} + +type BaremetalProfileUpdateInput struct { + apis.StandaloneAnonResourceBaseUpdateInput + + LanChannel uint8 + RootId *int + RootName string + StrongPass *bool +} + +type BaremetalProfileDetails struct { + SBaremetalProfile +} + +func (detail BaremetalProfileDetails) ToSpec() BaremetalProfileSpec { + channels := make([]uint8, 0) + if detail.LanChannel > 0 { + channels = append(channels, detail.LanChannel) + } + if detail.LanChannel2 > 0 { + channels = append(channels, detail.LanChannel2) + } + if detail.LanChannel3 > 0 { + channels = append(channels, detail.LanChannel3) + } + return BaremetalProfileSpec{ + OemName: detail.OemName, + Model: detail.Model, + LanChannels: channels, + RootName: detail.RootName, + RootId: detail.RootId, + StrongPass: detail.StrongPass, + } +} + +type BaremetalProfileSpec struct { + OemName string + Model string + LanChannels []uint8 + RootName string + RootId int + StrongPass bool +} + +type BaremetalProfileSpecs []BaremetalProfileSpec + +func (a BaremetalProfileSpecs) Len() int { return len(a) } +func (a BaremetalProfileSpecs) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a BaremetalProfileSpecs) Less(i, j int) bool { + if a[i].OemName != a[j].OemName { + return a[i].OemName < a[j].OemName + } + if a[i].Model != a[j].Model { + return a[i].Model < a[j].Model + } + return false +} + +var PredefinedProfiles = []BaremetalProfileSpec{ + { + OemName: "", + LanChannels: []uint8{1, 2, 8}, + RootName: "root", + RootId: 2, + }, + { + OemName: types.OEM_NAME_INSPUR, + LanChannels: []uint8{8, 1}, + RootName: "admin", + RootId: 2, + }, + { + OemName: types.OEM_NAME_LENOVO, + LanChannels: []uint8{1, 8}, + RootName: "root", + RootId: 2, + }, + { + OemName: types.OEM_NAME_HP, + LanChannels: []uint8{1, 2}, + RootName: "root", + RootId: 1, + }, + { + OemName: types.OEM_NAME_HUAWEI, + LanChannels: []uint8{1}, + RootName: "root", + RootId: 2, + StrongPass: true, + }, + { + OemName: types.OEM_NAME_FOXCONN, + LanChannels: []uint8{1}, + RootName: "root", + RootId: 2, + StrongPass: true, + }, + { + OemName: types.OEM_NAME_QEMU, + LanChannels: []uint8{8, 1}, + RootName: "root", + RootId: 2, + StrongPass: true, + }, + { + OemName: types.OEM_NAME_H3C, + LanChannels: []uint8{1}, + RootName: "root", + RootId: 2, + StrongPass: true, + }, +} diff --git a/pkg/apis/compute/baremetal/zz_generated.model.go b/pkg/apis/compute/baremetal/zz_generated.model.go new file mode 100644 index 0000000000..32e0adfb89 --- /dev/null +++ b/pkg/apis/compute/baremetal/zz_generated.model.go @@ -0,0 +1,36 @@ +// 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. + +// Code generated by model-api-gen. DO NOT EDIT. + +package baremetal + +import ( + "yunion.io/x/onecloud/pkg/apis" +) + +// SBaremetalProfile is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models/baremetal.SBaremetalProfile. +type SBaremetalProfile struct { + apis.SStandaloneAnonResourceBase + // 品牌名称(English) + OemName string `json:"oem_name"` + Model string `json:"model"` + LanChannel byte `json:"lan_channel"` + LanChannel2 byte `json:"lan_channel2"` + LanChannel3 byte `json:"lan_channel3"` + // BMC Root账号名称,默认为 root + RootName string `json:"root_name"` + // BMC Root账号ID,默认为 2 + RootId int `json:"root_id"` + // 是否要求强密码 + StrongPass bool `json:"strong_pass"` +} diff --git a/pkg/apis/compute/host.go b/pkg/apis/compute/host.go index ceb5a56232..6fce028069 100644 --- a/pkg/apis/compute/host.go +++ b/pkg/apis/compute/host.go @@ -414,7 +414,7 @@ type HostIpmiAttributes struct { // presence IpmiPresent *bool `json:"ipmi_present"` // lan channel - IpmiLanChannel *int `json:"ipmi_lan_channel"` + IpmiLanChannel *uint8 `json:"ipmi_lan_channel"` // verified IpmiVerified *bool `json:"ipmi_verified"` // Redfish API support diff --git a/pkg/apis/compute/zz_generated.model.go b/pkg/apis/compute/zz_generated.model.go index a54b83e815..67fa8778d3 100644 --- a/pkg/apis/compute/zz_generated.model.go +++ b/pkg/apis/compute/zz_generated.model.go @@ -269,6 +269,8 @@ type SCloudaccount struct { // 跳过部分资源同步 SkipSyncResources *SkipSyncResources `json:"skip_sync_resources"` EnableAutoSyncResource *bool `json:"enable_auto_sync_resource,omitempty"` + // 云平台默认区域id + RegionId string `json:"region_id"` } // SCloudimage is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SCloudimage. diff --git a/pkg/baremetal/agent.go b/pkg/baremetal/agent.go index ba078cad9b..4372bfdfda 100644 --- a/pkg/baremetal/agent.go +++ b/pkg/baremetal/agent.go @@ -134,7 +134,9 @@ func (agent *SBaremetalAgent) StartService() error { if err != nil { return fmt.Errorf("Baremetal manager load config error: %v", err) } - if err := manager.initBaremetals(files); err != nil { + + ctx := context.Background() + if err := manager.initBaremetals(ctx, files); err != nil { log.Warningf("init baremetals by files err: %v", err) } diff --git a/pkg/baremetal/cronjobs.go b/pkg/baremetal/cronjobs.go index cd9ab8bf84..78cf49c6ac 100644 --- a/pkg/baremetal/cronjobs.go +++ b/pkg/baremetal/cronjobs.go @@ -107,7 +107,7 @@ func (job *SStatusProbeJob) Do(ctx context.Context, now time.Time) error { pps := PowerStatusToBaremetalStatus(ps) if pps != bStatus { log.Debugf("Detected baremetal status change!") - job.baremetal.SyncAllStatus(ps) + job.baremetal.SyncAllStatus(ctx, ps) return nil } } diff --git a/pkg/baremetal/handler/delay.go b/pkg/baremetal/handler/delay.go index 728f95d0ad..ee3a7aa911 100644 --- a/pkg/baremetal/handler/delay.go +++ b/pkg/baremetal/handler/delay.go @@ -15,6 +15,7 @@ package handler import ( + "context" "fmt" "yunion.io/x/jsonutils" @@ -30,9 +31,10 @@ func init() { delayTaskWorkerMan = appsrv.NewWorkerManager("DelayTaskWorkerManager", 8, 1024, false) } -type ProcessFunc func(data jsonutils.JSONObject) (jsonutils.JSONObject, error) +type ProcessFunc func(ctx context.Context, data jsonutils.JSONObject) (jsonutils.JSONObject, error) type delayTask struct { + ctx context.Context process ProcessFunc taskId string session *mcclient.ClientSession @@ -40,7 +42,7 @@ type delayTask struct { } func (t *delayTask) Run() { - ret, err := t.process(t.data) + ret, err := t.process(t.ctx, t.data) if err != nil { modules.ComputeTasks.TaskFailed(t.session, t.taskId, err) return diff --git a/pkg/baremetal/handler/handlers.go b/pkg/baremetal/handler/handlers.go index 5d40136528..e4061507cf 100644 --- a/pkg/baremetal/handler/handlers.go +++ b/pkg/baremetal/handler/handlers.go @@ -109,7 +109,7 @@ func handleBaremetalNotify(ctx *Context, bm *baremetal.SBaremetalInstance) { task := bm.GetTask() if task == nil { task = tasks.NewBaremetalServerPrepareTask(bm) - bm.SyncStatus(baremetalstatus.PREPARE, "") + bm.SyncStatus(ctx, baremetalstatus.PREPARE, "") } log.Infof("Get notify from pxe rom os, start exec task: %s", task.GetName()) task.SSHExecute(remoteAddr, key, nil) @@ -157,7 +157,7 @@ func handleBaremetalResetBMC(ctx *Context, bm *baremetal.SBaremetalInstance) { } func handleBaremetalIpmiProbe(ctx *Context, bm *baremetal.SBaremetalInstance) { - bm.StartBaremetalIpmiProbeTask(ctx.UserCred(), ctx.TaskId(), ctx.Data()) + bm.StartBaremetalIpmiProbeTask(ctx, ctx.UserCred(), ctx.TaskId(), ctx.Data()) ctx.ResponseOk() } @@ -178,7 +178,7 @@ func handleBaremetalJnlpTask(ctx *Context, bm *baremetal.SBaremetalInstance) { } func handleServerCreate(ctx *Context, bm *baremetal.SBaremetalInstance) { - err := bm.StartServerCreateTask(ctx.UserCred(), ctx.TaskId(), ctx.Data()) + err := bm.StartServerCreateTask(ctx, ctx.UserCred(), ctx.TaskId(), ctx.Data()) if err != nil { ctx.ResponseError(httperrors.NewGeneralError(err)) return @@ -238,7 +238,7 @@ func handleServerStatus(ctx *Context, bm *baremetal.SBaremetalInstance, _ bareme } func handleBaremetalRegister(ctx *Context, input *baremetal.BmRegisterInput) { - ctx.DelayProcess(func(data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + ctx.DelayProcess(func(_ context.Context, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { baremetal.GetBaremetalManager().RegisterBaremetal(ctx, ctx.userCred, input) return nil, nil }, nil) diff --git a/pkg/baremetal/handler/middleware.go b/pkg/baremetal/handler/middleware.go index 7eb3e049ff..df52b3b957 100644 --- a/pkg/baremetal/handler/middleware.go +++ b/pkg/baremetal/handler/middleware.go @@ -88,7 +88,7 @@ func bmObjMiddlewareWithFetch(h bmObjHandlerFunc, fetch bool) appsrv.FilterHandl baremetal := newCtx.GetBaremetalManager().GetBaremetalById(bmId) if baremetal == nil { if fetch { - err := newCtx.GetBaremetalManager().InitBaremetal(bmId, false) + err := newCtx.GetBaremetalManager().InitBaremetal(newCtx, bmId, false) if err != nil { newCtx.ResponseError(err) return diff --git a/pkg/baremetal/manager.go b/pkg/baremetal/manager.go index 5fcfd3b8c0..1ecbfa00be 100644 --- a/pkg/baremetal/manager.go +++ b/pkg/baremetal/manager.go @@ -17,6 +17,7 @@ package baremetal import ( "context" "fmt" + "io/fs" "io/ioutil" "net" "net/http" @@ -43,6 +44,7 @@ import ( "yunion.io/x/onecloud/pkg/apis" api "yunion.io/x/onecloud/pkg/apis/compute" + baremetalapi "yunion.io/x/onecloud/pkg/apis/compute/baremetal" apiidenty "yunion.io/x/onecloud/pkg/apis/identity" o "yunion.io/x/onecloud/pkg/baremetal/options" "yunion.io/x/onecloud/pkg/baremetal/profiles" @@ -114,16 +116,16 @@ func (m *SBaremetalManager) GetZoneName() string { return m.Agent.Zone.Name } -func (m *SBaremetalManager) loadConfigs() ([]os.FileInfo, error) { +func (m *SBaremetalManager) loadConfigs() ([]fs.DirEntry, error) { m.killAllIPMITool() - files, err := ioutil.ReadDir(m.configPath) + files, err := os.ReadDir(m.configPath) if err != nil { return nil, err } return files, nil } -func (m *SBaremetalManager) initBaremetals(files []os.FileInfo) error { +func (m *SBaremetalManager) initBaremetals(ctx context.Context, files []fs.DirEntry) error { bmIds := make([]string, 0) for _, file := range files { if file.IsDir() && regutils.MatchUUID(file.Name()) { @@ -134,7 +136,7 @@ func (m *SBaremetalManager) initBaremetals(files []os.FileInfo) error { errsChannel := make(chan error, len(bmIds)) initBaremetal := func(i int) { bmId := bmIds[i] - err := m.InitBaremetal(bmId, true) + err := m.InitBaremetal(ctx, bmId, true) if err != nil { errsChannel <- err return @@ -151,7 +153,7 @@ func (m *SBaremetalManager) initBaremetals(files []os.FileInfo) error { return errors.NewAggregate(errs) } -func (m *SBaremetalManager) InitBaremetal(bmId string, update bool) error { +func (m *SBaremetalManager) InitBaremetal(ctx context.Context, bmId string, update bool) error { session := m.GetClientSession() var err error var desc jsonutils.JSONObject @@ -167,7 +169,7 @@ func (m *SBaremetalManager) InitBaremetal(bmId string, update bool) error { if !isBaremetal { return errors.Error("not a baremetal???") } - bmInstance, err := m.AddBaremetal(desc) + bmInstance, err := m.AddBaremetal(ctx, desc) if err != nil { return err } @@ -213,15 +215,15 @@ func (m *SBaremetalManager) fetchBaremetal(session *mcclient.ClientSession, bmId return obj, nil } -func (m *SBaremetalManager) AddBaremetal(desc jsonutils.JSONObject) (pxe.IBaremetalInstance, error) { +func (m *SBaremetalManager) AddBaremetal(ctx context.Context, desc jsonutils.JSONObject) (pxe.IBaremetalInstance, error) { id, err := desc.GetString("id") if err != nil { return nil, fmt.Errorf("Not found baremetal id in desc %s", desc) } if instance, ok := m.baremetals.Get(id); ok { - return instance, instance.SaveDesc(desc) + return instance, instance.SaveDesc(ctx, desc) } - bm, err := newBaremetalInstance(m, desc) + bm, err := newBaremetalInstance(ctx, m, desc) if err != nil { return nil, err } @@ -337,7 +339,7 @@ func (m *SBaremetalManager) RegisterBaremetal(ctx context.Context, userCred mccl return } - ipmiLanChannel, ipmiMac, err := m.checkIpmiInfo(input.Username, input.Password, input.IpAddr) + ipmiLanChannel, ipmiMac, err := m.checkIpmiInfo(ctx, input.Username, input.Password, input.IpAddr) if input.isTimeout() { return } else if err != nil { @@ -360,9 +362,9 @@ func (m *SBaremetalManager) RegisterBaremetal(ctx context.Context, userCred mccl ) var bmId string if !registered { - bmId, err = registerTask.CreateBaremetal() + bmId, err = registerTask.CreateBaremetal(ctx) } else { - bmId, err = registerTask.UpdateBaremetal() + bmId, err = registerTask.UpdateBaremetal(ctx) } if err != nil { input.responseErr(ctx, httperrors.NewInternalServerError("%v", err)) @@ -452,14 +454,18 @@ func (m *SBaremetalManager) checkSshInfo(input *BmRegisterInput) (*ssh.Client, e return sshCLi, nil } -func (m *SBaremetalManager) checkIpmiInfo(username, password, ipAddr string) (int, net.HardwareAddr, error) { +func (m *SBaremetalManager) checkIpmiInfo(ctx context.Context, username, password, ipAddr string) (uint8, net.HardwareAddr, error) { lanPlusTool := ipmitool.NewLanPlusIPMI(ipAddr, username, password) sysInfo, err := ipmitool.GetSysInfo(lanPlusTool) if err != nil { - return -1, nil, err + return 0, nil, errors.Wrap(err, "GetSysInfo") + } + profile, err := profiles.GetProfile(ctx, sysInfo) + if err != nil { + return 0, nil, errors.Wrap(err, "GetProfile") } - for _, lanChannel := range ipmitool.GetLanChannels(sysInfo) { + for _, lanChannel := range profile.LanChannels { config, err := ipmitool.GetLanConfig(lanPlusTool, lanChannel) if err != nil { log.Errorf("GetLanConfig failed %s", err) @@ -470,7 +476,7 @@ func (m *SBaremetalManager) checkIpmiInfo(username, password, ipAddr string) (in } return lanChannel, config.Mac, nil } - return -1, nil, fmt.Errorf("Ipmi can't fetch lan config") + return 0, nil, fmt.Errorf("Ipmi can't fetch lan config") } func (m *SBaremetalManager) Stop() { @@ -521,10 +527,12 @@ type SBaremetalInstance struct { server baremetaltypes.IBaremetalServer serverLock *sync.Mutex + profile *baremetalapi.BaremetalProfileSpec + cronJobs []IBaremetalCronJob } -func newBaremetalInstance(man *SBaremetalManager, desc jsonutils.JSONObject) (*SBaremetalInstance, error) { +func newBaremetalInstance(ctx context.Context, man *SBaremetalManager, desc jsonutils.JSONObject) (*SBaremetalInstance, error) { bm := &SBaremetalInstance{ manager: man, desc: desc.(*jsonutils.JSONDict), @@ -541,7 +549,7 @@ func newBaremetalInstance(man *SBaremetalManager, desc jsonutils.JSONObject) (*S if err != nil { return nil, err } - err = bm.SaveDesc(desc) + err = bm.SaveDesc(ctx, desc) if err != nil { return nil, err } @@ -614,17 +622,29 @@ func (b *SBaremetalInstance) GetStatus() string { return status } -func (b *SBaremetalInstance) AutoSaveDesc() error { - return b.SaveDesc(nil) +func (b *SBaremetalInstance) AutoSaveDesc(ctx context.Context) error { + return b.SaveDesc(ctx, nil) } -func (b *SBaremetalInstance) SaveDesc(desc jsonutils.JSONObject) error { +func (b *SBaremetalInstance) SaveDesc(ctx context.Context, desc jsonutils.JSONObject) error { b.descLock.Lock() defer b.descLock.Unlock() if desc != nil { b.desc = desc.(*jsonutils.JSONDict) + + if b.desc.Contains("sys_info") { + sysInfo := types.SSystemInfo{} + err := b.desc.Unmarshal(&sysInfo, "sys_info") + if err != nil { + return errors.Wrap(err, "Unmarshal sys_info") + } + b.profile, err = profiles.GetProfile(ctx, &sysInfo) + if err != nil { + return errors.Wrap(err, "GetProfile") + } + } } - return ioutil.WriteFile(b.GetDescFilePath(), []byte(b.desc.String()), 0644) + return os.WriteFile(b.GetDescFilePath(), []byte(b.desc.String()), 0644) } func (b *SBaremetalInstance) loadServer() { @@ -634,7 +654,7 @@ func (b *SBaremetalInstance) loadServer() { return } descPath := b.GetServerDescFilePath() - desc, err := ioutil.ReadFile(descPath) + desc, err := os.ReadFile(descPath) if err != nil { log.Errorf("Failed to read server desc %s: %v", descPath, err) return @@ -668,7 +688,7 @@ func (b *SBaremetalInstance) SaveSSHConfig(remoteAddr string, key string) error RemoteIP: remoteAddr, } conf := jsonutils.Marshal(sshConf) - err = ioutil.WriteFile(b.GetSSHConfigFilePath(), []byte(conf.String()), 0644) + err = os.WriteFile(b.GetSSHConfigFilePath(), []byte(conf.String()), 0644) if err != nil { return err } @@ -679,7 +699,7 @@ func (b *SBaremetalInstance) SaveSSHConfig(remoteAddr string, key string) error func (b *SBaremetalInstance) GetSSHConfig() (*types.SSHConfig, error) { path := b.GetSSHConfigFilePath() - content, err := ioutil.ReadFile(path) + content, err := os.ReadFile(path) if err != nil { if os.IsNotExist(err) { return nil, nil @@ -774,7 +794,7 @@ func (b *SBaremetalInstance) SyncSSHConfig(conf types.SSHConfig) error { func (b *SBaremetalInstance) SyncStatusBackground() { go func() { - b.AutoSyncAllStatus() + b.AutoSyncAllStatus(context.Background()) }() } @@ -785,12 +805,12 @@ func (b *SBaremetalInstance) InitializeServer(s *mcclient.ClientSession, name st return err } -func (b *SBaremetalInstance) ServerLoadDesc() error { +func (b *SBaremetalInstance) ServerLoadDesc(ctx context.Context) error { res, err := modules.Hosts.Get(b.manager.GetClientSession(), b.GetId(), nil) if err != nil { return err } - b.SaveDesc(res) + b.SaveDesc(ctx, res) sid, err := res.GetString("server_id") if err == nil { sDesc := jsonutils.NewDict() @@ -830,11 +850,11 @@ func PowerStatusToServerStatus(bm *SBaremetalInstance, status string) string { return baremetalstatus.UNKNOWN } -func (b *SBaremetalInstance) AutoSyncStatus() { - b.SyncStatus("", "") +func (b *SBaremetalInstance) AutoSyncStatus(ctx context.Context) { + b.SyncStatus(ctx, "", "") } -func (b *SBaremetalInstance) SyncStatus(status string, reason string) { +func (b *SBaremetalInstance) SyncStatus(ctx context.Context, status string, reason string) { if status == "" { powerStatus, err := b.GetPowerStatus() if err != nil { @@ -843,7 +863,7 @@ func (b *SBaremetalInstance) SyncStatus(status string, reason string) { status = PowerStatusToBaremetalStatus(powerStatus) } b.desc.Set("status", jsonutils.NewString(status)) - b.AutoSaveDesc() + b.AutoSaveDesc(ctx) params := jsonutils.NewDict() params.Add(jsonutils.NewString(status), "status") if reason != "" { @@ -857,16 +877,16 @@ func (b *SBaremetalInstance) SyncStatus(status string, reason string) { log.Infof("Update baremetal %s to status %s", b.GetId(), status) } -func (b *SBaremetalInstance) AutoSyncAllStatus() { - b.SyncAllStatus("") +func (b *SBaremetalInstance) AutoSyncAllStatus(ctx context.Context) { + b.SyncAllStatus(ctx, "") } -func (b *SBaremetalInstance) DelayedSyncStatus(_ jsonutils.JSONObject) (jsonutils.JSONObject, error) { - b.AutoSyncAllStatus() +func (b *SBaremetalInstance) DelayedSyncStatus(ctx context.Context, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + b.AutoSyncAllStatus(ctx) return nil, nil } -func (b *SBaremetalInstance) SyncAllStatus(status string) { +func (b *SBaremetalInstance) SyncAllStatus(ctx context.Context, status string) { var err error if status == "" { status, err = b.GetPowerStatus() @@ -874,7 +894,7 @@ func (b *SBaremetalInstance) SyncAllStatus(status string) { log.Errorf("Get power status error: %v", err) } } - b.SyncStatus(PowerStatusToBaremetalStatus(status), "") + b.SyncStatus(ctx, PowerStatusToBaremetalStatus(status), "") b.SyncServerStatus(PowerStatusToServerStatus(b, status)) } @@ -1295,6 +1315,7 @@ func (b *SBaremetalInstance) SetTask(task tasks.ITask) { } func (b *SBaremetalInstance) InitAdminNetif( + ctx context.Context, cliMac net.HardwareAddr, wireId string, nicType compute.TNicType, @@ -1312,7 +1333,7 @@ func (b *SBaremetalInstance) InitAdminNetif( baremetalstatus.UNKNOWN}) && b.GetTask() == nil && b.GetServer() == nil { b.SetTask(tasks.NewBaremetalServerPrepareTask(b)) - b.SyncStatus(baremetalstatus.PREPARE, "") + b.SyncStatus(ctx, baremetalstatus.PREPARE, "") } nic := b.GetNicByMac(cliMac) @@ -1321,14 +1342,14 @@ func (b *SBaremetalInstance) InitAdminNetif( if err != nil { return err } - return b.postAttachWire(cliMac, nicType, netType, importIpAddr) + return b.postAttachWire(ctx, cliMac, nicType, netType, importIpAddr) } else if nic.IpAddr == "" { - return b.postAttachWire(cliMac, nicType, netType, importIpAddr) + return b.postAttachWire(ctx, cliMac, nicType, netType, importIpAddr) } return nil } -func (b *SBaremetalInstance) RegisterNetif(cliMac net.HardwareAddr, wireId string) error { +func (b *SBaremetalInstance) RegisterNetif(ctx context.Context, cliMac net.HardwareAddr, wireId string) error { var nicType compute.TNicType nic := b.GetNicByMac(cliMac) if nic != nil { @@ -1339,7 +1360,7 @@ func (b *SBaremetalInstance) RegisterNetif(cliMac net.HardwareAddr, wireId strin if err != nil { return err } - return b.SaveDesc(desc) + return b.SaveDesc(ctx, desc) } return nil } @@ -1357,7 +1378,7 @@ func (b *SBaremetalInstance) attachWire(mac net.HardwareAddr, wireId string, nic return modules.Hosts.PerformAction(session, b.GetId(), "add-netif", params) } -func (b *SBaremetalInstance) postAttachWire(mac net.HardwareAddr, nicType compute.TNicType, netType api.TNetworkType, ipAddr string) error { +func (b *SBaremetalInstance) postAttachWire(ctx context.Context, mac net.HardwareAddr, nicType compute.TNicType, netType api.TNetworkType, ipAddr string) error { if ipAddr == "" { switch nicType { case api.NIC_TYPE_IPMI: @@ -1376,7 +1397,7 @@ func (b *SBaremetalInstance) postAttachWire(mac net.HardwareAddr, nicType comput if err != nil { return err } - return b.SaveDesc(desc) + return b.SaveDesc(ctx, desc) } func (b *SBaremetalInstance) enableWire(mac net.HardwareAddr, ipAddr string, nicType compute.TNicType, netType api.TNetworkType) (jsonutils.JSONObject, error) { @@ -1410,13 +1431,8 @@ func (b *SBaremetalInstance) GetIPMIConfig() *types.SIPMIInfo { log.Debugf("GetIPMIConfig password is nil") return nil } - if conf.Username == "" { - sysInfo := types.SSystemInfo{} - err := b.desc.Unmarshal(&sysInfo, "sys_info") - if err != nil { - log.Errorf("Unmarshal get sys_info error: %v", err) - } - conf.Username = profiles.GetRootName(&sysInfo) + if conf.Username == "" && b.profile != nil { + conf.Username = b.profile.RootName } if conf.IpAddr == "" { nicIPAddr := b.GetIPMINicIPAddr() @@ -1628,19 +1644,19 @@ func (b *SBaremetalInstance) sshRun(hostCmd string, serverCmd string) ([]string, ) } -func (b *SBaremetalInstance) adjustUEFIWrapper(cli *ssh.Client, f func() error) error { +func (b *SBaremetalInstance) adjustUEFIWrapper(ctx context.Context, cli *ssh.Client, f func() error) error { isUEFI, err := uefi.RemoteIsUEFIBoot(cli) if err != nil { return errors.Wrap(err, "Check is uefi boot") } if !isUEFI { - return b.CleanUEFIInfo() + return b.CleanUEFIInfo(ctx) } return f() } -func (b *SBaremetalInstance) AdjustUEFICurrentBootOrder(hostCli *ssh.Client) error { - return b.adjustUEFIWrapper(hostCli, func() error { +func (b *SBaremetalInstance) AdjustUEFICurrentBootOrder(ctx context.Context, hostCli *ssh.Client) error { + return b.adjustUEFIWrapper(ctx, hostCli, func() error { mgr, err := uefi.NewEFIBootMgrFromRemote(hostCli, false) if err != nil { return errors.Wrap(err, "NewEFIBootMgrFromRemote") @@ -1648,14 +1664,14 @@ func (b *SBaremetalInstance) AdjustUEFICurrentBootOrder(hostCli *ssh.Client) err if err := uefi.RemoteSetCurrentBootAtFirst(hostCli, mgr); err != nil { return errors.Wrap(err, "Set current boot order at first") } - return b.SendUEFIInfo(mgr) + return b.SendUEFIInfo(ctx, mgr) }) } -func (b *SBaremetalInstance) updateUEFIInfo(uefiData jsonutils.JSONObject) error { +func (b *SBaremetalInstance) updateUEFIInfo(ctx context.Context, uefiData jsonutils.JSONObject) error { desc := b.desc desc.Add(uefiData, "uefi_info") - if err := b.SaveDesc(desc); err != nil { + if err := b.SaveDesc(ctx, desc); err != nil { return errors.Wrap(err, "Save uefi_info") } updateData := jsonutils.NewDict() @@ -1666,26 +1682,26 @@ func (b *SBaremetalInstance) updateUEFIInfo(uefiData jsonutils.JSONObject) error return nil } -func (b *SBaremetalInstance) CleanUEFIInfo() error { - if err := b.updateUEFIInfo(jsonutils.NewDict()); err != nil { +func (b *SBaremetalInstance) CleanUEFIInfo(ctx context.Context) error { + if err := b.updateUEFIInfo(ctx, jsonutils.NewDict()); err != nil { return errors.Wrap(err, "CleanUEFIInfo") } return nil } -func (b *SBaremetalInstance) SendUEFIInfo(mgr *uefi.BootMgr) error { +func (b *SBaremetalInstance) SendUEFIInfo(ctx context.Context, mgr *uefi.BootMgr) error { info, err := mgr.ToEFIBootMgrInfo() if err != nil { return err } - if err := b.updateUEFIInfo(jsonutils.Marshal(info)); err != nil { + if err := b.updateUEFIInfo(ctx, jsonutils.Marshal(info)); err != nil { return errors.Wrap(err, "SendUEFIInfo") } return nil } -func (b *SBaremetalInstance) adjustServerUEFIBootOrder(srvCli *ssh.Client) error { - return b.adjustUEFIWrapper(srvCli, func() error { +func (b *SBaremetalInstance) adjustServerUEFIBootOrder(ctx context.Context, srvCli *ssh.Client) error { + return b.adjustUEFIWrapper(ctx, srvCli, func() error { info, err := b.GetUEFIInfo() if err != nil { return errors.Wrap(err, "GetUEFIInfo from local desc") @@ -1701,22 +1717,22 @@ func (b *SBaremetalInstance) adjustServerUEFIBootOrder(srvCli *ssh.Client) error }) } -func (b *SBaremetalInstance) AdjustUEFIBootOrder() error { +func (b *SBaremetalInstance) AdjustUEFIBootOrder(ctx context.Context) error { _, err := b.sshRunWrapper( func(hostCli *ssh.Client) ([]string, error) { - return nil, b.AdjustUEFICurrentBootOrder(hostCli) + return nil, b.AdjustUEFICurrentBootOrder(ctx, hostCli) }, func(srvCli *ssh.Client) ([]string, error) { - return nil, b.adjustServerUEFIBootOrder(srvCli) + return nil, b.adjustServerUEFIBootOrder(ctx, srvCli) }, ) return err } -func (b *SBaremetalInstance) SSHReboot() error { +func (b *SBaremetalInstance) SSHReboot(ctx context.Context) error { if !b.HasBMC() { // try adjust uefi boot order before reboot - if err := b.AdjustUEFIBootOrder(); err != nil { + if err := b.AdjustUEFIBootOrder(ctx); err != nil { return errors.Wrap(err, "Adjust uefi boot order") } } @@ -1771,7 +1787,7 @@ func (b *SBaremetalInstance) GetRedfishCli(ctx context.Context) redfish.IRedfish conf.Username, conf.Password, false) } -func (b *SBaremetalInstance) GetIPMILanChannel() int { +func (b *SBaremetalInstance) GetIPMILanChannel() uint8 { conf := b.GetIPMIConfig() if conf == nil { return 0 @@ -1941,7 +1957,7 @@ func (b *SBaremetalInstance) GetMemGb() string { return strconv.FormatInt(memMb/1024, 10) } -func (b *SBaremetalInstance) DelayedRemove(_ jsonutils.JSONObject) (jsonutils.JSONObject, error) { +func (b *SBaremetalInstance) DelayedRemove(_ context.Context, _ jsonutils.JSONObject) (jsonutils.JSONObject, error) { b.remove() return nil, nil } @@ -1982,10 +1998,10 @@ func (b *SBaremetalInstance) StartBaremetalResetBMCTask(userCred mcclient.TokenC return nil } -func (b *SBaremetalInstance) StartBaremetalIpmiProbeTask(userCred mcclient.TokenCredential, taskId string, data jsonutils.JSONObject) error { +func (b *SBaremetalInstance) StartBaremetalIpmiProbeTask(ctx context.Context, userCred mcclient.TokenCredential, taskId string, data jsonutils.JSONObject) error { session := b.manager.GetClientSession() data, _ = b.manager.fetchBaremetal(session, b.GetId()) - if err := b.SaveDesc(data); err != nil { + if err := b.SaveDesc(ctx, data); err != nil { return err } b.StartNewTask(tasks.NewBaremetalIpmiProbeTask, userCred, taskId, data) @@ -1997,12 +2013,12 @@ func (b *SBaremetalInstance) StartBaremetalCdromTask(userCred mcclient.TokenCred return nil } -func (b *SBaremetalInstance) DelayedServerReset(_ jsonutils.JSONObject) (jsonutils.JSONObject, error) { +func (b *SBaremetalInstance) DelayedServerReset(ctx context.Context, _ jsonutils.JSONObject) (jsonutils.JSONObject, error) { err := b.DoPXEBoot() return nil, err } -func (b *SBaremetalInstance) StartServerCreateTask(userCred mcclient.TokenCredential, taskId string, data jsonutils.JSONObject) error { +func (b *SBaremetalInstance) StartServerCreateTask(ctx context.Context, userCred mcclient.TokenCredential, taskId string, data jsonutils.JSONObject) error { b.serverLock.Lock() defer b.serverLock.Unlock() if b.server != nil { @@ -2018,7 +2034,7 @@ func (b *SBaremetalInstance) StartServerCreateTask(userCred mcclient.TokenCreden } b.server = server b.desc.Set("server_id", jsonutils.NewString(b.server.GetId())) - if err := b.AutoSaveDesc(); err != nil { + if err := b.AutoSaveDesc(ctx); err != nil { return err } b.StartNewTask(tasks.NewBaremetalServerCreateTask, userCred, taskId, data) @@ -2063,15 +2079,22 @@ func (b *SBaremetalInstance) StartServerDestroyTask(userCred mcclient.TokenCrede b.StartNewTask(tasks.NewBaremetalServerDestroyTask, userCred, taskId, data) } -func (b *SBaremetalInstance) DelayedSyncIPMIInfo(data jsonutils.JSONObject) (jsonutils.JSONObject, error) { +func (b *SBaremetalInstance) DelayedSyncIPMIInfo(ctx context.Context, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { ipmiCli := b.GetIPMITool() lanChannel := b.GetIPMILanChannel() sysInfo, err := ipmitool.GetSysInfo(ipmiCli) if err != nil { - return nil, err + return nil, errors.Wrap(err, "GetSysInfo") + } + profile, err := profiles.GetProfile(ctx, sysInfo) + if err != nil { + return nil, errors.Wrap(err, "GetProfile") } if lanChannel <= 0 { - lanChannel = ipmitool.GetDefaultLanChannel(sysInfo) + if len(profile.LanChannels) == 0 { + return nil, errors.Wrap(errors.ErrInvalidStatus, "baremetal profile not valid lan channel?") + } + lanChannel = profile.LanChannels[0] } retObj := make(map[string]string) if ipAddr, _ := data.GetString("ip_addr"); ipAddr != "" { @@ -2083,7 +2106,7 @@ func (b *SBaremetalInstance) DelayedSyncIPMIInfo(data jsonutils.JSONObject) (jso retObj["ipmi_ip_addr"] = ipAddr } if passwd, _ := data.GetString("password"); passwd != "" { - err = ipmitool.SetLanPasswd(ipmiCli, ipmitool.GetRootId(sysInfo), passwd) + err = ipmitool.SetLanPasswd(ipmiCli, profile.RootId, passwd) if err != nil { return nil, err } @@ -2092,16 +2115,16 @@ func (b *SBaremetalInstance) DelayedSyncIPMIInfo(data jsonutils.JSONObject) (jso return jsonutils.Marshal(retObj), nil } -func (b *SBaremetalInstance) DelayedSyncDesc(data jsonutils.JSONObject) (jsonutils.JSONObject, error) { +func (b *SBaremetalInstance) DelayedSyncDesc(ctx context.Context, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { if data == nil { session := b.manager.GetClientSession() data, _ = b.manager.fetchBaremetal(session, b.GetId()) } - err := b.SaveDesc(data) + err := b.SaveDesc(ctx, data) return nil, err } -func (b *SBaremetalInstance) DelayedServerStatus(data jsonutils.JSONObject) (jsonutils.JSONObject, error) { +func (b *SBaremetalInstance) DelayedServerStatus(ctx context.Context, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { ps, err := b.GetPowerStatus() if err != nil { return nil, err @@ -2112,7 +2135,7 @@ func (b *SBaremetalInstance) DelayedServerStatus(data jsonutils.JSONObject) (jso return resp, err } -func (b *SBaremetalInstance) SendNicInfo(nic *types.SNicDevInfo, idx int, nicType compute.TNicType, reset bool, ipAddr string, reserve bool) error { +func (b *SBaremetalInstance) SendNicInfo(ctx context.Context, nic *types.SNicDevInfo, idx int, nicType compute.TNicType, reset bool, ipAddr string, reserve bool) error { params := jsonutils.NewDict() params.Add(jsonutils.NewString(nic.Mac.String()), "mac") params.Add(jsonutils.NewInt(int64(nic.Speed)), "rate") @@ -2149,7 +2172,7 @@ func (b *SBaremetalInstance) SendNicInfo(nic *types.SNicDevInfo, idx int, nicTyp if err != nil { return err } - return b.SaveDesc(resp) + return b.SaveDesc(ctx, resp) } func bindMount(src, dst string) error { diff --git a/pkg/baremetal/profiles/profiles.go b/pkg/baremetal/profiles/profiles.go index f9ac1dc9ea..5a1c6d7962 100644 --- a/pkg/baremetal/profiles/profiles.go +++ b/pkg/baremetal/profiles/profiles.go @@ -15,117 +15,68 @@ package profiles import ( + "context" + + "yunion.io/x/pkg/errors" + + baremetalapi "yunion.io/x/onecloud/pkg/apis/compute/baremetal" + "yunion.io/x/onecloud/pkg/baremetal/options" "yunion.io/x/onecloud/pkg/cloudcommon/types" + "yunion.io/x/onecloud/pkg/mcclient/auth" + baremetalmodules "yunion.io/x/onecloud/pkg/mcclient/modules/compute/baremetal" ) -type IPMIProfile struct { - LanChannel []int - RootName string - RootId int - StrongPass bool -} - -func DefaultProfile() IPMIProfile { - return IPMIProfile{ - LanChannel: []int{1, 2, 8}, - RootName: "root", - RootId: 2, +func GetProfile(ctx context.Context, sysinfo *types.SSystemInfo) (*baremetalapi.BaremetalProfileSpec, error) { + adminSession := auth.GetAdminSession(ctx, options.Options.Region) + specs, err := baremetalmodules.BaremetalProfiles.GetMatchProfiles(adminSession, sysinfo.OemName, sysinfo.Model) + if err != nil { + return nil, errors.Wrapf(err, "GetMatchProfile %s %s", sysinfo.OemName, sysinfo.Model) } -} - -func InspurProfile() IPMIProfile { - return IPMIProfile{ - LanChannel: []int{8, 1}, - RootName: "admin", - RootId: 2, + if len(specs) > 0 { + return &specs[len(specs)-1], nil } + return nil, errors.ErrNotFound } -func LenovoProfile() IPMIProfile { - return IPMIProfile{ - LanChannel: []int{1, 8}, - RootName: "root", - RootId: 2, +func GetLanChannels(ctx context.Context, sysinfo *types.SSystemInfo) ([]uint8, error) { + profile, err := GetProfile(ctx, sysinfo) + if err != nil { + return nil, errors.Wrap(err, "GetProfile") } + return profile.LanChannels, nil } -func HpProfile() IPMIProfile { - return IPMIProfile{ - LanChannel: []int{1, 2}, - RootName: "root", - RootId: 1, +func GetDefaultLanChannel(ctx context.Context, sysinfo *types.SSystemInfo) (uint8, error) { + channels, err := GetLanChannels(ctx, sysinfo) + if err != nil { + return 0, errors.Wrap(err, "GetLanChannels") } -} - -func HuaweiProfile() IPMIProfile { - return IPMIProfile{ - LanChannel: []int{1}, - RootName: "root", - RootId: 2, - StrongPass: true, + if len(channels) > 0 { + return channels[0], nil } + return 0, errors.ErrNotFound } -func FoxconnProfile() IPMIProfile { - return IPMIProfile{ - LanChannel: []int{1}, - RootName: "root", - RootId: 2, - StrongPass: true, +func GetRootId(ctx context.Context, sysinfo *types.SSystemInfo) (int, error) { + profile, err := GetProfile(ctx, sysinfo) + if err != nil { + return 0, errors.Wrap(err, "GetProfile") } + return profile.RootId, nil } -func QemuProfile() IPMIProfile { - return IPMIProfile{ - LanChannel: []int{8, 1}, - RootName: "root", - RootId: 2, - StrongPass: true, +func GetRootName(ctx context.Context, sysinfo *types.SSystemInfo) (string, error) { + profile, err := GetProfile(ctx, sysinfo) + if err != nil { + return "", errors.Wrap(err, "GetProfile") } + return profile.RootName, nil } -func H3CProfile() IPMIProfile { - return IPMIProfile{ - // LanChannel: []int{8, 1}, - LanChannel: []int{1}, - RootName: "root", - RootId: 2, - StrongPass: true, +func IsStrongPass(ctx context.Context, sysinfo *types.SSystemInfo) (bool, error) { + profile, err := GetProfile(ctx, sysinfo) + if err != nil { + return false, errors.Wrap(err, "GetProfile") } -} - -var ( - PROFILES map[string]IPMIProfile = map[string]IPMIProfile{ - types.OEM_NAME_INSPUR: InspurProfile(), - types.OEM_NAME_LENOVO: LenovoProfile(), - types.OEM_NAME_HP: HpProfile(), - types.OEM_NAME_HUAWEI: HuaweiProfile(), - types.OEM_NAME_FOXCONN: FoxconnProfile(), - types.OEM_NAME_QEMU: QemuProfile(), - types.OEM_NAME_H3C: H3CProfile(), - } -) - -func GetProfile(sysinfo *types.SSystemInfo) IPMIProfile { - profile, ok := PROFILES[sysinfo.OemName] - if ok { - return profile - } - return DefaultProfile() -} - -func GetLanChannel(sysinfo *types.SSystemInfo) []int { - return GetProfile(sysinfo).LanChannel -} - -func GetRootId(sysinfo *types.SSystemInfo) int { - return GetProfile(sysinfo).RootId -} - -func GetRootName(sysinfo *types.SSystemInfo) string { - return GetProfile(sysinfo).RootName -} - -func IsStrongPass(sysinfo *types.SSystemInfo) bool { - return GetProfile(sysinfo).StrongPass + return profile.StrongPass, nil } diff --git a/pkg/baremetal/pxe/dhcp.go b/pkg/baremetal/pxe/dhcp.go index f87115a19b..876f987db7 100644 --- a/pkg/baremetal/pxe/dhcp.go +++ b/pkg/baremetal/pxe/dhcp.go @@ -15,6 +15,7 @@ package pxe import ( + "context" "encoding/hex" "fmt" "net" @@ -69,7 +70,7 @@ type dhcpRequest struct { netConfig *types.SNetworkConfig } -func (h *DHCPHandler) ServeDHCP(pkt dhcp.Packet, _ *net.UDPAddr, _ *net.Interface) (dhcp.Packet, []string, error) { +func (h *DHCPHandler) ServeDHCP(ctx context.Context, pkt dhcp.Packet, _ *net.UDPAddr, _ *net.Interface) (dhcp.Packet, []string, error) { req, err := h.newRequest(pkt, h.baremetalManager) if err != nil { log.Errorf("[DHCP] new request by packet error: %v", err) @@ -81,7 +82,7 @@ func (h *DHCPHandler) ServeDHCP(pkt dhcp.Packet, _ *net.UDPAddr, _ *net.Interfac return nil, nil, fmt.Errorf("Request not from a DHCP relay, ignore mac: %s", req.ClientMac) } log.Infof("[DHCP] from relay %s packet, mac: %s", req.RelayAddr, req.ClientMac) - conf, targets, err := req.fetchConfig(h.baremetalManager.GetClientSession()) + conf, targets, err := req.fetchConfig(ctx, h.baremetalManager.GetClientSession()) if err != nil { return nil, nil, errors.Wrapf(err, "fetchConfig for %s", req.ClientMac.String()) } @@ -185,7 +186,7 @@ func formatUuidString(uuidBytes []byte) string { }, "-") } -func (req *dhcpRequest) fetchConfig(session *mcclient.ClientSession) (*dhcp.ResponseConfig, []string, error) { +func (req *dhcpRequest) fetchConfig(ctx context.Context, session *mcclient.ClientSession) (*dhcp.ResponseConfig, []string, error) { // 1. find_network_conf netConf, err := req.findNetworkConf(session, false) if err != nil { @@ -209,7 +210,7 @@ func (req *dhcpRequest) fetchConfig(session *mcclient.ClientSession) (*dhcp.Resp if err != nil { return nil, nil, errors.Wrapf(err, "createOrUpdateBaremetal for %s", req.ClientMac.String()) } - err = req.doInitBaremetalAdminNetif(bmDesc) + err = req.doInitBaremetalAdminNetif(ctx, bmDesc) if err != nil { return nil, nil, errors.Wrapf(err, "doInitBaremetalAdminNetif for %s", req.ClientMac.String()) } @@ -241,13 +242,13 @@ func (req *dhcpRequest) fetchConfig(session *mcclient.ClientSession) (*dhcp.Resp req.baremetalInstance = bmInstance ipmiNic := req.baremetalInstance.GetIPMINic(req.ClientMac) if ipmiNic != nil && ipmiNic.Mac == req.ClientMac.String() { - err = req.baremetalInstance.InitAdminNetif( + err = req.baremetalInstance.InitAdminNetif(ctx, req.ClientMac, req.netConfig.WireId, api.NIC_TYPE_IPMI, api.NETWORK_TYPE_IPMI, false, "") if err != nil { return nil, nil, errors.Wrapf(err, "InitAdminNetif for %s", req.ClientMac.String()) } } else { - err = req.baremetalInstance.RegisterNetif(req.ClientMac, req.netConfig.WireId) + err = req.baremetalInstance.RegisterNetif(ctx, req.ClientMac, req.netConfig.WireId) if err != nil { log.Errorf("RegisterNetif %s error: %v", req.ClientMac.String(), err) return nil, nil, errors.Wrapf(err, "RegisterNetif for %s", req.ClientMac.String()) @@ -424,13 +425,13 @@ func (req *dhcpRequest) updateBaremetal(session *mcclient.ClientSession, id stri return desc, nil } -func (req *dhcpRequest) doInitBaremetalAdminNetif(desc jsonutils.JSONObject) error { +func (req *dhcpRequest) doInitBaremetalAdminNetif(ctx context.Context, desc jsonutils.JSONObject) error { var err error - req.baremetalInstance, err = req.baremetalManager.AddBaremetal(desc) + req.baremetalInstance, err = req.baremetalManager.AddBaremetal(ctx, desc) if err != nil { return err } - err = req.baremetalInstance.InitAdminNetif( + err = req.baremetalInstance.InitAdminNetif(ctx, req.ClientMac, req.netConfig.WireId, api.NIC_TYPE_ADMIN, api.NETWORK_TYPE_PXE, false, "") return err } diff --git a/pkg/baremetal/pxe/pxe.go b/pkg/baremetal/pxe/pxe.go index dc328c2539..3e81f9fe01 100644 --- a/pkg/baremetal/pxe/pxe.go +++ b/pkg/baremetal/pxe/pxe.go @@ -15,6 +15,7 @@ package pxe import ( + "context" "fmt" "net" @@ -85,7 +86,7 @@ const ( type IBaremetalManager interface { GetZoneId() string GetBaremetalByMac(mac net.HardwareAddr) IBaremetalInstance - AddBaremetal(desc jsonutils.JSONObject) (IBaremetalInstance, error) + AddBaremetal(ctx context.Context, desc jsonutils.JSONObject) (IBaremetalInstance, error) GetClientSession() *mcclient.ClientSession } @@ -94,8 +95,8 @@ type IBaremetalInstance interface { GetIPMINic(cliMac net.HardwareAddr) *types.SNic GetPXEDHCPConfig(arch uint16) (*dhcp.ResponseConfig, error) GetDHCPConfig(cliMac net.HardwareAddr) (*dhcp.ResponseConfig, error) - InitAdminNetif(cliMac net.HardwareAddr, wireId string, nicType compute.TNicType, netType computeapi.TNetworkType, isDoImport bool, ipAddr string) error - RegisterNetif(cliMac net.HardwareAddr, wireId string) error + InitAdminNetif(ctx context.Context, cliMac net.HardwareAddr, wireId string, nicType compute.TNicType, netType computeapi.TNetworkType, isDoImport bool, ipAddr string) error + RegisterNetif(ctx context.Context, cliMac net.HardwareAddr, wireId string) error GetTFTPResponse() string } diff --git a/pkg/baremetal/tasks/base.go b/pkg/baremetal/tasks/base.go index 26a79234cb..8662327569 100644 --- a/pkg/baremetal/tasks/base.go +++ b/pkg/baremetal/tasks/base.go @@ -342,8 +342,8 @@ func (self *SBaremetalTaskBase) EnsurePowerUp() error { return nil } -func (self *SBaremetalTaskBase) EnsureSSHReboot() error { - if err := self.Baremetal.SSHReboot(); err != nil { +func (self *SBaremetalTaskBase) EnsureSSHReboot(ctx context.Context) error { + if err := self.Baremetal.SSHReboot(ctx); err != nil { return errors.Wrap(err, "Ensure ssh reboot") } @@ -425,7 +425,7 @@ func (self *SBaremetalPXEBootTaskBase) InitPXEBootTask(ctx context.Context, args if !self.Baremetal.HasBMC() { // Try remote ssh reboot - if err := self.Baremetal.SSHReboot(); err != nil { + if err := self.Baremetal.SSHReboot(ctx); err != nil { return errors.Wrap(err, "Try ssh reboot") } } else { @@ -491,6 +491,6 @@ func (self *SBaremetalPXEBootTaskBase) GetName() string { return "BaremetalPXEBootTaskBase" } -func AdjustUEFIBootOrder(term *ssh.Client, bm IBaremetal) error { - return bm.AdjustUEFICurrentBootOrder(term) +func AdjustUEFIBootOrder(ctx context.Context, term *ssh.Client, bm IBaremetal) error { + return bm.AdjustUEFICurrentBootOrder(ctx, term) } diff --git a/pkg/baremetal/tasks/basedeploy.go b/pkg/baremetal/tasks/basedeploy.go index 63bf7f0afb..d81dd6afb3 100644 --- a/pkg/baremetal/tasks/basedeploy.go +++ b/pkg/baremetal/tasks/basedeploy.go @@ -107,7 +107,7 @@ func (self *SBaremetalServerBaseDeployTask) OnPXEBoot(ctx context.Context, term return errors.Wrap(err, "Do deploy") } - if err := AdjustUEFIBootOrder(term, self.Baremetal); err != nil { + if err := AdjustUEFIBootOrder(ctx, term, self.Baremetal); err != nil { return errors.Wrap(err, "Adjust UEFI boot order") } @@ -134,7 +134,7 @@ func (self *SBaremetalServerBaseDeployTask) OnPXEBoot(ctx context.Context, term return errors.Wrap(err, "Ensure power up") } } - self.Baremetal.AutoSyncAllStatus() + self.Baremetal.AutoSyncAllStatus(ctx) } else { if onFinishAction == "shutdown" { log.Infof("None BMC baremetal can't shutdown when deploying") @@ -147,12 +147,12 @@ func (self *SBaremetalServerBaseDeployTask) OnPXEBoot(ctx context.Context, term // do restart // hack: ssh reboot to disk self.needPXEBoot = false - if err := self.EnsureSSHReboot(); err != nil { + if err := self.EnsureSSHReboot(ctx); err != nil { return errors.Wrap(err, "Try ssh reboot") } } } - self.Baremetal.SyncAllStatus(types.POWER_STATUS_ON) + self.Baremetal.SyncAllStatus(ctx, types.POWER_STATUS_ON) } SetTaskComplete(self, result) return nil diff --git a/pkg/baremetal/tasks/baseprepare.go b/pkg/baremetal/tasks/baseprepare.go index 9e4f0abf86..0dd0248f77 100644 --- a/pkg/baremetal/tasks/baseprepare.go +++ b/pkg/baremetal/tasks/baseprepare.go @@ -15,6 +15,7 @@ package tasks import ( + "context" "fmt" "net" "strings" @@ -30,6 +31,7 @@ import ( "yunion.io/x/onecloud/pkg/apis" api "yunion.io/x/onecloud/pkg/apis/compute" + baremetalapi "yunion.io/x/onecloud/pkg/apis/compute/baremetal" o "yunion.io/x/onecloud/pkg/baremetal/options" "yunion.io/x/onecloud/pkg/baremetal/profiles" "yunion.io/x/onecloud/pkg/baremetal/utils/detect_storages" @@ -169,7 +171,7 @@ func (task *sBaremetalPrepareTask) prepareBaremetalInfo(cli *ssh.Client) (*barem return prepareInfo, nil } -func (task *sBaremetalPrepareTask) configIPMISetting(cli *ssh.Client, i *baremetalPrepareInfo) error { +func (task *sBaremetalPrepareTask) configIPMISetting(ctx context.Context, cli *ssh.Client, i *baremetalPrepareInfo) error { if !i.ipmiInfo.Present { return nil } @@ -185,12 +187,16 @@ func (task *sBaremetalPrepareTask) configIPMISetting(cli *ssh.Client, i *baremet ) sshIPMI := ipmitool.NewSSHIPMI(cli) setIPMILanPortShared(sshIPMI, sysInfo) - ipmiUser, ipmiPasswd, ipmiIpAddr := task.getIPMIUserPasswd(i.ipmiInfo, sysInfo) + profile, err := profiles.GetProfile(ctx, sysInfo) + if err != nil { + return errors.Wrap(err, "GetProfile") + } + ipmiUser, ipmiPasswd, ipmiIpAddr := task.getIPMIUserPasswd(i.ipmiInfo, profile) ipmiInfo.Username = ipmiUser ipmiInfo.Password = ipmiPasswd - var ipmiLanChannel int = -1 - for _, lanChannel := range ipmitool.GetLanChannels(sysInfo) { + var ipmiLanChannel uint8 = 0 + for _, lanChannel := range profile.LanChannels { log.Infof("Try lan channel %d ...", lanChannel) conf, err := ipmitool.GetLanConfig(sshIPMI, lanChannel) if err != nil { @@ -207,11 +213,11 @@ func (task *sBaremetalPrepareTask) configIPMISetting(cli *ssh.Client, i *baremet Speed: 100, Mtu: 1500, } - if err := task.sendNicInfo(ipmiNic, -1, api.NIC_TYPE_IPMI, true, "", false); err != nil { + if err := task.sendNicInfo(ctx, ipmiNic, -1, api.NIC_TYPE_IPMI, true, "", false); err != nil { // ignore the error log.Errorf("Send IPMI nic %#v info: %v", ipmiNic, err) } - rootId := ipmitool.GetRootId(sysInfo) + rootId := profile.RootId err = ipmitool.CreateOrSetAdminUser(sshIPMI, lanChannel, rootId, ipmiUser, ipmiPasswd) if err != nil { // ignore the error @@ -232,7 +238,7 @@ func (task *sBaremetalPrepareTask) configIPMISetting(cli *ssh.Client, i *baremet } if len(tryAddrs) > 0 && !o.Options.ForceDhcpProbeIpmi { for _, tryAddr := range tryAddrs { - tryResult := task.tryLocalIpmiAddr(sshIPMI, ipmiNic, lanChannel, + tryResult := task.tryLocalIpmiAddr(ctx, sshIPMI, ipmiNic, lanChannel, ipmiUser, ipmiPasswd, tryAddr) if tryResult { ipmiInfo.IpAddr = tryAddr @@ -240,7 +246,7 @@ func (task *sBaremetalPrepareTask) configIPMISetting(cli *ssh.Client, i *baremet break } } - if ipmiLanChannel >= 0 { + if ipmiLanChannel > 0 { // found and set config on lanChannel break } @@ -309,7 +315,7 @@ func (task *sBaremetalPrepareTask) configIPMISetting(cli *ssh.Client, i *baremet ipmiInfo.IpAddr = nic.IpAddr ipmiLanChannel = lanChannel } - if ipmiLanChannel == -1 { + if ipmiLanChannel == 0 { return fmt.Errorf("Fail to get IPMI address from DHCP") } ipmiInfo.LanChannel = ipmiLanChannel @@ -317,7 +323,7 @@ func (task *sBaremetalPrepareTask) configIPMISetting(cli *ssh.Client, i *baremet return nil } -func (task *sBaremetalPrepareTask) DoPrepare(cli *ssh.Client) error { +func (task *sBaremetalPrepareTask) DoPrepare(ctx context.Context, cli *ssh.Client) error { infos, err := task.prepareBaremetalInfo(cli) if err != nil { logclient.AddActionLogWithStartable(task, task.baremetal, logclient.ACT_PREPARE, err, task.userCred, false) @@ -325,12 +331,12 @@ func (task *sBaremetalPrepareTask) DoPrepare(cli *ssh.Client) error { } // set ipmi nic address and user password - if err = task.configIPMISetting(cli, infos); err != nil { + if err = task.configIPMISetting(ctx, cli, infos); err != nil { logclient.AddActionLogWithStartable(task, task.baremetal, logclient.ACT_PREPARE, err, task.userCred, false) return errors.Wrap(err, "Config IPMI setting") } - if err = task.updateBmInfo(cli, infos); err != nil { + if err = task.updateBmInfo(ctx, cli, infos); err != nil { logclient.AddActionLogWithStartable(task, task.baremetal, logclient.ACT_PREPARE, err, task.userCred, false) return err } @@ -341,7 +347,7 @@ func (task *sBaremetalPrepareTask) DoPrepare(cli *ssh.Client) error { log.Errorf("SetNTP fail: %s", err) } - if err = AdjustUEFIBootOrder(cli, task.baremetal); err != nil { + if err = AdjustUEFIBootOrder(ctx, cli, task.baremetal); err != nil { logclient.AddActionLogWithStartable(task, task.baremetal, logclient.ACT_PREPARE, err, task.userCred, false) return errors.Wrap(err, "Adjust UEFI boot order") } @@ -375,7 +381,7 @@ func (task *sBaremetalPrepareTask) findAdminNic(cli *ssh.Client, nicsInfo []*typ return -1, nil, errors.Error("admin nic not found???") } -func (task *sBaremetalPrepareTask) updateBmInfo(cli *ssh.Client, i *baremetalPrepareInfo) error { +func (task *sBaremetalPrepareTask) updateBmInfo(ctx context.Context, cli *ssh.Client, i *baremetalPrepareInfo) error { adminNic := task.baremetal.GetAdminNic() if adminNic == nil || (adminNic != nil && !adminNic.LinkUp) { adminIdx, adminNicDev, err := task.findAdminNic(cli, i.nicsInfo) @@ -383,7 +389,7 @@ func (task *sBaremetalPrepareTask) updateBmInfo(cli *ssh.Client, i *baremetalPre return errors.Wrap(err, "task.findAdminNic") } accessIp := cli.GetConfig().Host - err = task.sendNicInfo(adminNicDev, adminIdx, api.NIC_TYPE_ADMIN, false, accessIp, true) + err = task.sendNicInfo(ctx, adminNicDev, adminIdx, api.NIC_TYPE_ADMIN, false, accessIp, true) if err != nil { return errors.Wrap(err, "send Admin Nic Info") } @@ -445,14 +451,14 @@ func (task *sBaremetalPrepareTask) updateBmInfo(cli *ssh.Client, i *baremetalPre // } removedMacs := task.removeObsoleteNics(i) for idx := range removedMacs { - err = task.removeNicInfo(removedMacs[idx]) + err = task.removeNicInfo(ctx, removedMacs[idx]) if err != nil { log.Errorf("Fail to remove Netif %s: %s", removedMacs[idx], err) return errors.Wrap(err, "task.removeNicInfo") } } for idx := range i.nicsInfo { - err = task.sendNicInfo(i.nicsInfo[idx], idx, "", false, "", false) + err = task.sendNicInfo(ctx, i.nicsInfo[idx], idx, "", false, "", false) if err != nil { log.Errorf("Send nicinfo idx: %d, %#v error: %v", idx, i.nicsInfo[idx], err) return errors.Wrap(err, "task.sendNicInfo") @@ -494,7 +500,7 @@ func (task *sBaremetalPrepareTask) removeObsoleteNics(i *baremetalPrepareInfo) [ return removes } -func (task *sBaremetalPrepareTask) tryLocalIpmiAddr(sshIPMI *ipmitool.SSHIPMI, ipmiNic *types.SNicDevInfo, lanChannel int, ipmiUser, ipmiPasswd, tryAddr string) bool { +func (task *sBaremetalPrepareTask) tryLocalIpmiAddr(ctx context.Context, sshIPMI *ipmitool.SSHIPMI, ipmiNic *types.SNicDevInfo, lanChannel uint8, ipmiUser, ipmiPasswd, tryAddr string) bool { log.Infof("IP addr found in IPMI config, try use %s as IPMI address", tryAddr) ipConf, err := task.getIPMIIPConfig(tryAddr) if err != nil { @@ -548,7 +554,7 @@ func (task *sBaremetalPrepareTask) tryLocalIpmiAddr(sshIPMI *ipmitool.SSHIPMI, i if tried < maxTries { // make sure the ipaddr is a IPMI address // enable the netif - err := task.sendNicInfo(ipmiNic, -1, api.NIC_TYPE_IPMI, false, tryAddr, true) + err := task.sendNicInfo(ctx, ipmiNic, -1, api.NIC_TYPE_IPMI, false, tryAddr, true) if err != nil { log.Errorf("Fail to set existing BMC IP address to %s", tryAddr) } else { @@ -558,14 +564,14 @@ func (task *sBaremetalPrepareTask) tryLocalIpmiAddr(sshIPMI *ipmitool.SSHIPMI, i return false } -func (task *sBaremetalPrepareTask) getIPMIUserPasswd(oldIPMIConf *types.SIPMIInfo, sysInfo *types.SSystemInfo) (string, string, string) { +func (task *sBaremetalPrepareTask) getIPMIUserPasswd(oldIPMIConf *types.SIPMIInfo, profile *baremetalapi.BaremetalProfileSpec) (string, string, string) { var ( ipmiUser string ipmiPasswd string ipmiIpAddr string ) - ipmiUser = profiles.GetRootName(sysInfo) - isStrongPass := profiles.IsStrongPass(sysInfo) + ipmiUser = profile.RootName + isStrongPass := profile.StrongPass if !isStrongPass && o.Options.DefaultIpmiPassword != "" { ipmiPasswd = o.Options.DefaultIpmiPassword } else if isStrongPass && o.Options.DefaultStrongIpmiPassword != "" { @@ -785,7 +791,7 @@ func isIPMIEnable(cli *ssh.Client) (bool, error) { return sysutils.ParseDMIIPMIInfo(ret), nil } -func (task *sBaremetalPrepareTask) removeNicInfo(mac string) error { +func (task *sBaremetalPrepareTask) removeNicInfo(ctx context.Context, mac string) error { params := jsonutils.NewDict() params.Add(jsonutils.NewString(mac), "mac") resp, err := modules.Hosts.PerformAction( @@ -797,13 +803,13 @@ func (task *sBaremetalPrepareTask) removeNicInfo(mac string) error { if err != nil { return err } - return task.baremetal.SaveDesc(resp) + return task.baremetal.SaveDesc(ctx, resp) } -func (task *sBaremetalPrepareTask) sendNicInfo( +func (task *sBaremetalPrepareTask) sendNicInfo(ctx context.Context, nic *types.SNicDevInfo, idx int, nicType compute.TNicType, reset bool, ipAddr string, reserve bool, ) error { - return task.baremetal.SendNicInfo(nic, idx, nicType, reset, ipAddr, reserve) + return task.baremetal.SendNicInfo(ctx, nic, idx, nicType, reset, ipAddr, reserve) } func (task *sBaremetalPrepareTask) sendStorageInfo(size int64) error { diff --git a/pkg/baremetal/tasks/bm_register.go b/pkg/baremetal/tasks/bm_register.go index 7f6bc933ed..7801bffe21 100644 --- a/pkg/baremetal/tasks/bm_register.go +++ b/pkg/baremetal/tasks/bm_register.go @@ -22,9 +22,11 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" + "yunion.io/x/pkg/errors" api "yunion.io/x/onecloud/pkg/apis/compute" o "yunion.io/x/onecloud/pkg/baremetal/options" + "yunion.io/x/onecloud/pkg/baremetal/profiles" "yunion.io/x/onecloud/pkg/baremetal/utils/ipmitool" "yunion.io/x/onecloud/pkg/cloudcommon/types" "yunion.io/x/onecloud/pkg/mcclient" @@ -49,7 +51,7 @@ type sBaremetalRegisterTask struct { IpmiIpAddr string IpmiMac net.HardwareAddr - IpmiLanChannel int + IpmiLanChannel uint8 AdminWire string IpmiWire string @@ -60,7 +62,7 @@ type sBaremetalRegisterTask struct { func NewBaremetalRegisterTask( userCred mcclient.TokenCredential, bmManager IBmManager, sshCli *ssh.Client, hostname, remoteIp, ipmiUsername, ipmiPassword, ipmiIpAddr string, - ipmiMac net.HardwareAddr, ipmiLanChannel int, adminWire, ipmiWire string) *sBaremetalRegisterTask { + ipmiMac net.HardwareAddr, ipmiLanChannel uint8, adminWire, ipmiWire string) *sBaremetalRegisterTask { return &sBaremetalRegisterTask{ sBaremetalPrepareTask: sBaremetalPrepareTask{userCred: userCred}, BmManager: bmManager, @@ -112,7 +114,7 @@ func (s *sBaremetalRegisterTask) getAccessDevMacAddr(ip string) (string, error) return segs[1], nil } -func (s *sBaremetalRegisterTask) CreateBaremetal() (string, error) { +func (s *sBaremetalRegisterTask) CreateBaremetal(ctx context.Context) (string, error) { zoneId := s.BmManager.GetZoneId() ret, err := s.SshCli.Run("/lib/mos/lsnic") if err != nil { @@ -148,24 +150,24 @@ func (s *sBaremetalRegisterTask) CreateBaremetal() (string, error) { if err != nil { return "", fmt.Errorf("Create baremetal failed: %s", err) } - pxeBm, err := s.BmManager.AddBaremetal(res) + pxeBm, err := s.BmManager.AddBaremetal(ctx, res) if err != nil { return "", fmt.Errorf("BmManager add baremetal failed: %s", err) } - err = pxeBm.InitAdminNetif( + err = pxeBm.InitAdminNetif(ctx, s.accessNic.Mac, s.AdminWire, api.NIC_TYPE_ADMIN, api.NETWORK_TYPE_PXE, true, s.RemoteIp) if err != nil { return "", fmt.Errorf("BmManager add admin netif failed: %s", err) } - err = pxeBm.InitAdminNetif( + err = pxeBm.InitAdminNetif(ctx, s.IpmiMac, s.IpmiWire, api.NIC_TYPE_IPMI, api.NETWORK_TYPE_IPMI, true, s.IpmiIpAddr) if err != nil { return "", fmt.Errorf("BmManager add ipmi netif failed: %s", err) } for _, nic := range nicinfo { if nic.Dev != s.accessNic.Dev { - pxeBm.RegisterNetif(nic.Mac, s.AdminWire) + pxeBm.RegisterNetif(ctx, nic.Mac, s.AdminWire) } } s.baremetal = pxeBm.(IBaremetal) @@ -173,14 +175,14 @@ func (s *sBaremetalRegisterTask) CreateBaremetal() (string, error) { return bmInstanceId, nil } -func (s *sBaremetalRegisterTask) UpdateBaremetal() (string, error) { +func (s *sBaremetalRegisterTask) UpdateBaremetal(ctx context.Context) (string, error) { accessMac, err := s.getAccessDevMacAddr(s.RemoteIp) if err != nil { - return "", err + return "", errors.Wrap(err, "getAccessDevMacAddr") } accessMacAddr, err := net.ParseMAC(accessMac) if err != nil { - return "", fmt.Errorf("Failed parse access mac %s", accessMac) + return "", errors.Wrapf(err, "Failed parse access mac %s", accessMac) } params := jsonutils.NewDict() @@ -188,14 +190,14 @@ func (s *sBaremetalRegisterTask) UpdateBaremetal() (string, error) { params.Set("scope", jsonutils.NewString("system")) res, err := modules.Hosts.List(s.BmManager.GetClientSession(), params) if err != nil { - return "", fmt.Errorf("Fetch baremetal failed %s", err) + return "", errors.Wrap(err, "Fetch baremetal failed") } if len(res.Data) == 0 { - return "", fmt.Errorf("Cann't find baremetal by access mac %s", accessMacAddr) + return "", errors.Wrapf(errors.ErrNotFound, "Cann't find baremetal by access mac %s", accessMacAddr) } - pxeBm, err := s.BmManager.AddBaremetal(res.Data[0]) + pxeBm, err := s.BmManager.AddBaremetal(ctx, res.Data[0]) if err != nil { - return "", fmt.Errorf("BmManager add baremetal failed: %s", err) + return "", errors.Wrap(err, "BmManager add baremetal failed") } s.baremetal = pxeBm.(IBaremetal) @@ -229,12 +231,12 @@ func (s *sBaremetalRegisterTask) DoPrepare(ctx context.Context, cli *ssh.Client, infos.ipmiInfo.RedfishApi = redfishSupport infos.ipmiInfo.CdromBoot = cdromSupport - s.updateIpmiInfo(cli) + s.updateIpmiInfo(ctx, cli) - return s.updateBmInfo(cli, infos, registered) + return s.updateBmInfo(ctx, cli, infos, registered) } -func (s *sBaremetalRegisterTask) updateIpmiInfo(cli *ssh.Client) { +func (s *sBaremetalRegisterTask) updateIpmiInfo(ctx context.Context, cli *ssh.Client) { ipmiTool := ipmitool.NewSSHIPMI(cli) sysInfo, err := ipmitool.GetSysInfo(ipmiTool) if err == nil && o.Options.IpmiLanPortShared { @@ -253,21 +255,25 @@ func (s *sBaremetalRegisterTask) updateIpmiInfo(cli *ssh.Client) { } var conf *types.SIPMILanConfig - for _, lanChannel := range ipmitool.GetLanChannels(sysInfo) { - conf, _ = ipmitool.GetLanConfig(ipmiTool, lanChannel) - if conf == nil || len(conf.Mac) == 0 { - continue + profile, err := profiles.GetProfile(ctx, sysInfo) + if profile != nil { + for _, lanChannel := range profile.LanChannels { + conf, _ = ipmitool.GetLanConfig(ipmiTool, lanChannel) + if conf == nil || len(conf.Mac) == 0 { + continue + } } } + if conf == nil || len(conf.Mac) == 0 { log.Errorln("Fail to get IPMI lan config !!!") } else { nic.Mac = conf.Mac } - s.sendNicInfo(nic, -1, api.NIC_TYPE_IPMI, false, "", false) + s.sendNicInfo(ctx, nic, -1, api.NIC_TYPE_IPMI, false, "", false) } -func (s *sBaremetalRegisterTask) updateBmInfo(cli *ssh.Client, i *baremetalPrepareInfo, registered bool) error { +func (s *sBaremetalRegisterTask) updateBmInfo(ctx context.Context, cli *ssh.Client, i *baremetalPrepareInfo, registered bool) error { updateInfo := make(map[string]interface{}) updateInfo["access_ip"] = s.RemoteIp updateInfo["cpu_count"] = i.cpuInfo.Count @@ -293,7 +299,7 @@ func (s *sBaremetalRegisterTask) updateBmInfo(cli *ssh.Client, i *baremetalPrepa log.Errorf("sendStorageInfo error: %v", err) } for idx := range i.nicsInfo { - err = s.sendNicInfo(i.nicsInfo[idx], idx, "", false, "", false) + err = s.sendNicInfo(ctx, i.nicsInfo[idx], idx, "", false, "", false) if err != nil { log.Errorf("Send nicinfo idx: %d, %#v error: %v", idx, i.nicsInfo[idx], err) } @@ -301,20 +307,20 @@ func (s *sBaremetalRegisterTask) updateBmInfo(cli *ssh.Client, i *baremetalPrepa if registered { return nil } - return s.initBaremetalServer() + return s.initBaremetalServer(ctx) } -func (s *sBaremetalRegisterTask) initBaremetalServer() error { +func (s *sBaremetalRegisterTask) initBaremetalServer(ctx context.Context) error { if err := s.baremetal.InitializeServer(s.getSession(), s.Hostname); err != nil { return fmt.Errorf("Baremteal Create Server Failed %s", err) } // if err := s.baremetal.SaveSSHConfig("", ""); err != nil { // log.Errorf("Save ssh config failed %s", err) // } - if err := s.baremetal.ServerLoadDesc(); err != nil { + if err := s.baremetal.ServerLoadDesc(ctx); err != nil { log.Errorf("Server load desc failed %s", err) } - s.baremetal.SyncStatus("running", "Register success") + s.baremetal.SyncStatus(ctx, "running", "Register success") log.Infof("%s Load baremetal info success ...", s.baremetal.GetId()) return nil } diff --git a/pkg/baremetal/tasks/cdrom.go b/pkg/baremetal/tasks/cdrom.go index bfeaf8cbf3..881df4cd43 100644 --- a/pkg/baremetal/tasks/cdrom.go +++ b/pkg/baremetal/tasks/cdrom.go @@ -106,7 +106,7 @@ func (self *SBaremetalCdromTask) DoInsertISO(ctx context.Context, args interface if err != nil { return errors.Wrap(err, "MountVirtualCdrom") } - self.Baremetal.AutoSyncStatus() + self.Baremetal.AutoSyncStatus(ctx) SetTaskComplete(self, nil) return nil } @@ -120,7 +120,7 @@ func (self *SBaremetalCdromTask) DoEjectISO(ctx context.Context, args interface{ if err != nil { return errors.Wrap(err, "UmountVirtualCdrom") } - self.Baremetal.AutoSyncStatus() + self.Baremetal.AutoSyncStatus(ctx) SetTaskComplete(self, nil) return nil } diff --git a/pkg/baremetal/tasks/create.go b/pkg/baremetal/tasks/create.go index 372785689b..5b944e1f3b 100644 --- a/pkg/baremetal/tasks/create.go +++ b/pkg/baremetal/tasks/create.go @@ -15,6 +15,7 @@ package tasks import ( + "context" "time" "yunion.io/x/jsonutils" @@ -50,32 +51,32 @@ func (self *SBaremetalServerCreateTask) RemoveEFIOSEntry() bool { return true } -func (self *SBaremetalServerCreateTask) DoDeploys(term *ssh.Client) (jsonutils.JSONObject, error) { +func (self *SBaremetalServerCreateTask) DoDeploys(ctx context.Context, term *ssh.Client) (jsonutils.JSONObject, error) { // Build raid tool, err := self.Baremetal.GetServer().DoDiskConfig(term) if err != nil { - return nil, self.onError(term, err) + return nil, self.onError(ctx, term, err) } time.Sleep(2 * time.Second) if err := self.Baremetal.GetServer().DoEraseDisk(term); err != nil { - return nil, self.onError(term, err) + return nil, self.onError(ctx, term, err) } time.Sleep(2 * time.Second) parts, err := self.Baremetal.GetServer().DoPartitionDisk(tool, term, self.IsDisableImageCache()) if err != nil { - return nil, self.onError(term, err) + return nil, self.onError(ctx, term, err) } data := jsonutils.NewDict() disks, err := self.Baremetal.GetServer().SyncPartitionSize(term, parts) if err != nil { - return nil, self.onError(term, err) + return nil, self.onError(ctx, term, err) } data.Add(jsonutils.Marshal(disks), "disks") rootImageId := self.Baremetal.GetServer().GetRootTemplateId() if len(rootImageId) > 0 { deployInfo, err := self.Baremetal.GetServer().DoDeploy(tool, term, self.data, true) if err != nil { - return nil, self.onError(term, err) + return nil, self.onError(ctx, term, err) } if deployInfo != nil { data.Update(deployInfo) @@ -100,11 +101,11 @@ func (self *SBaremetalServerCreateTask) PostDeploys(term *ssh.Client) error { return nil } -func (self *SBaremetalServerCreateTask) onError(term *ssh.Client, err error) error { +func (self *SBaremetalServerCreateTask) onError(ctx context.Context, term *ssh.Client, err error) error { log.Errorf("Create server error: %+v", err) if err1 := self.Baremetal.GetServer().DoEraseDisk(term); err1 != nil { log.Warningf("EraseDisk error: %v", err1) } - self.Baremetal.AutoSyncStatus() + self.Baremetal.AutoSyncStatus(ctx) return err } diff --git a/pkg/baremetal/tasks/interface.go b/pkg/baremetal/tasks/interface.go index 373dfff680..4849511290 100644 --- a/pkg/baremetal/tasks/interface.go +++ b/pkg/baremetal/tasks/interface.go @@ -15,6 +15,7 @@ package tasks import ( + "context" "net" "yunion.io/x/cloudmux/pkg/apis/compute" @@ -39,7 +40,7 @@ type IBaremetal interface { GetAdminNic() *types.SNic GetName() string GetClientSession() *mcclient.ClientSession - SaveDesc(desc jsonutils.JSONObject) error + SaveDesc(ctx context.Context, desc jsonutils.JSONObject) error GetNics() []types.SNic GetNicByMac(net.HardwareAddr) *types.SNic GetRawIPMIConfig() *types.SIPMIInfo @@ -47,10 +48,10 @@ type IBaremetal interface { SetExistingIPMIIPAddr(ipAddr string) GetServer() baremetaltypes.IBaremetalServer - SyncStatus(status, reason string) - AutoSyncStatus() - SyncAllStatus(status string) - AutoSyncAllStatus() + SyncStatus(ctx context.Context, status, reason string) + AutoSyncStatus(ctx context.Context) + SyncAllStatus(ctx context.Context, status string) + AutoSyncAllStatus(ctx context.Context) GetPowerStatus() (string, error) DoPowerShutdown(soft bool) error @@ -61,25 +62,25 @@ type IBaremetal interface { GetAccessIp() string EnablePxeBoot() bool GenerateBootISO() error - SendNicInfo(nic *types.SNicDevInfo, idx int, nicType compute.TNicType, reset bool, ipAddr string, reserve bool) error + SendNicInfo(ctx context.Context, nic *types.SNicDevInfo, idx int, nicType compute.TNicType, reset bool, ipAddr string, reserve bool) error DoNTPConfig() error GetImageUrl(needImageCache bool) string RemoveServer() InitializeServer(session *mcclient.ClientSession, name string) error SaveSSHConfig(remoteAddr string, key string) error - ServerLoadDesc() error + ServerLoadDesc(ctx context.Context) error GetDHCPServerIP() (net.IP, error) HasBMC() bool SSHReachable() (bool, error) - SSHReboot() error + SSHReboot(ctx context.Context) error SSHShutdown() error - AdjustUEFICurrentBootOrder(cli *ssh.Client) error + AdjustUEFICurrentBootOrder(ctx context.Context, cli *ssh.Client) error } type IBmManager interface { GetZoneId() string - AddBaremetal(jsonutils.JSONObject) (pxe.IBaremetalInstance, error) + AddBaremetal(context.Context, jsonutils.JSONObject) (pxe.IBaremetalInstance, error) GetClientSession() *mcclient.ClientSession } diff --git a/pkg/baremetal/tasks/ipmiprobe.go b/pkg/baremetal/tasks/ipmiprobe.go index ae591ea88a..92ade0e797 100644 --- a/pkg/baremetal/tasks/ipmiprobe.go +++ b/pkg/baremetal/tasks/ipmiprobe.go @@ -23,7 +23,9 @@ import ( "yunion.io/x/pkg/errors" api "yunion.io/x/onecloud/pkg/apis/compute" + baremetalapi "yunion.io/x/onecloud/pkg/apis/compute/baremetal" o "yunion.io/x/onecloud/pkg/baremetal/options" + "yunion.io/x/onecloud/pkg/baremetal/profiles" "yunion.io/x/onecloud/pkg/baremetal/utils/ipmitool" "yunion.io/x/onecloud/pkg/cloudcommon/types" "yunion.io/x/onecloud/pkg/httperrors" @@ -97,7 +99,7 @@ func (self *SBaremetalIpmiProbeTask) doRedfishIpmiProbe(ctx context.Context, drv if len(confs) == 0 { return false, errors.Wrap(httperrors.ErrNotFound, "no IPMI lan") } - err = self.sendIpmiNicInfo(&confs[0]) + err = self.sendIpmiNicInfo(ctx, &confs[0]) if err != nil { return false, errors.Wrap(err, "self.sendIpmiNicInfo") } @@ -143,18 +145,18 @@ func (self *SBaremetalIpmiProbeTask) doRedfishIpmiProbe(ctx context.Context, drv for i := range sysInfo.EthernetNICs { mac, err := net.ParseMAC(sysInfo.EthernetNICs[i]) if err == nil { - err = self.sendNicInfo(i, mac) + err = self.sendNicInfo(ctx, i, mac) if err != nil { return true, errors.Wrapf(err, "sendNicInfo %d %s", i, mac) } } } - self.Baremetal.SyncStatus("", "Probe Redfish finished") + self.Baremetal.SyncStatus(ctx, "", "Probe Redfish finished") SetTaskComplete(self, nil) return true, nil } -func (self *SBaremetalIpmiProbeTask) sendIpmiNicInfo(lanConf *types.SIPMILanConfig) error { +func (self *SBaremetalIpmiProbeTask) sendIpmiNicInfo(ctx context.Context, lanConf *types.SIPMILanConfig) error { speed := lanConf.SpeedMbps if speed <= 0 { speed = 100 @@ -166,18 +168,18 @@ func (self *SBaremetalIpmiProbeTask) sendIpmiNicInfo(lanConf *types.SIPMILanConf Speed: speed, Mtu: 1500, } - err := self.Baremetal.SendNicInfo(ipmiNic, -1, api.NIC_TYPE_IPMI, true, lanConf.IPAddr, true) + err := self.Baremetal.SendNicInfo(ctx, ipmiNic, -1, api.NIC_TYPE_IPMI, true, lanConf.IPAddr, true) if err != nil { return errors.Wrap(err, "SendNicInfo") } return nil } -func (self *SBaremetalIpmiProbeTask) sendNicInfo(index int, mac net.HardwareAddr) error { +func (self *SBaremetalIpmiProbeTask) sendNicInfo(ctx context.Context, index int, mac net.HardwareAddr) error { nicInfo := &types.SNicDevInfo{ Mac: mac, } - err := self.Baremetal.SendNicInfo(nicInfo, index, "", false, "", false) + err := self.Baremetal.SendNicInfo(ctx, nicInfo, index, "", false, "", false) if err != nil { return errors.Wrap(err, "SendNicInfo") } @@ -186,14 +188,20 @@ func (self *SBaremetalIpmiProbeTask) sendNicInfo(index int, mac net.HardwareAddr func (self *SBaremetalIpmiProbeTask) doRawIpmiProbe(ctx context.Context, cli ipmitool.IPMIExecutor) error { sysInfo, err := ipmitool.GetSysInfo(cli) + var profile *baremetalapi.BaremetalProfileSpec if err != nil { // ignore error for qemu log.Errorf("ipmitool.GetSysInfo error %s", err) + } else { + profile, err = profiles.GetProfile(ctx, sysInfo) + if err != nil { + return errors.Wrap(err, "GetProfile") + } } guid := ipmitool.GetSysGuid(cli) var conf *types.SIPMILanConfig - var channel int - for _, lanChannel := range ipmitool.GetLanChannels(sysInfo) { + var channel uint8 + for _, lanChannel := range profile.LanChannels { conf, err = ipmitool.GetLanConfig(cli, lanChannel) if err != nil { // ignore error @@ -206,7 +214,7 @@ func (self *SBaremetalIpmiProbeTask) doRawIpmiProbe(ctx context.Context, cli ipm if conf == nil { return errors.Wrap(httperrors.ErrNotFound, "no IPMI lan") } - err = self.sendIpmiNicInfo(conf) + err = self.sendIpmiNicInfo(ctx, conf) if err != nil { return errors.Wrap(err, "self.sendIpmiNicInfo") } @@ -244,7 +252,7 @@ func (self *SBaremetalIpmiProbeTask) doRawIpmiProbe(ctx context.Context, cli ipm if err != nil { return errors.Wrap(err, "modules.Hosts.Update") } - self.Baremetal.SyncStatus("", "Probie IPMI finished") + self.Baremetal.SyncStatus(ctx, "", "Probie IPMI finished") SetTaskComplete(self, nil) return nil } diff --git a/pkg/baremetal/tasks/maintenance.go b/pkg/baremetal/tasks/maintenance.go index 2e4a8cacf1..c41c1404a8 100644 --- a/pkg/baremetal/tasks/maintenance.go +++ b/pkg/baremetal/tasks/maintenance.go @@ -51,7 +51,7 @@ func (self *SBaremetalMaintenanceTask) OnPXEBoot(ctx context.Context, term *ssh. if jsonutils.QueryBoolean(self.data, "guest_running", false) { dataObj["guest_running"] = true } - self.Baremetal.AutoSyncStatus() + self.Baremetal.AutoSyncStatus(ctx) SetTaskComplete(self, jsonutils.Marshal(dataObj)) return nil } diff --git a/pkg/baremetal/tasks/prepare.go b/pkg/baremetal/tasks/prepare.go index 0486b64cb8..84e285bedc 100644 --- a/pkg/baremetal/tasks/prepare.go +++ b/pkg/baremetal/tasks/prepare.go @@ -49,13 +49,13 @@ func (self *SBaremetalServerPrepareTask) GetName() string { // OnPXEBootRequest called by notify api handler func (self *SBaremetalServerPrepareTask) OnPXEBootRequest(ctx context.Context, cli *ssh.Client, args interface{}) error { - err := newBaremetalPrepareTask(self.Baremetal, self.userCred).DoPrepare(cli) + err := newBaremetalPrepareTask(self.Baremetal, self.userCred).DoPrepare(ctx, cli) if err != nil { log.Errorf("Prepare failed: %v", err) - self.Baremetal.SyncStatus(status.PREPARE_FAIL, err.Error()) + self.Baremetal.SyncStatus(ctx, status.PREPARE_FAIL, err.Error()) return err } - self.Baremetal.AutoSyncStatus() + self.Baremetal.AutoSyncStatus(ctx) SetTaskComplete(self, nil) return nil } diff --git a/pkg/baremetal/tasks/reprepare.go b/pkg/baremetal/tasks/reprepare.go index 16643ebddc..ba0635131d 100644 --- a/pkg/baremetal/tasks/reprepare.go +++ b/pkg/baremetal/tasks/reprepare.go @@ -15,6 +15,8 @@ package tasks import ( + "context" + "yunion.io/x/jsonutils" "yunion.io/x/onecloud/pkg/mcclient" @@ -43,13 +45,13 @@ func (self *SBaremetalReprepareTask) GetName() string { return "BaremetalReprepareTask" } -func (self *SBaremetalReprepareTask) DoDeploys(term *ssh.Client) (jsonutils.JSONObject, error) { +func (self *SBaremetalReprepareTask) DoDeploys(ctx context.Context, term *ssh.Client) (jsonutils.JSONObject, error) { task := newBaremetalPrepareTask(self.Baremetal, self.userCred) - err := task.DoPrepare(term) + err := task.DoPrepare(ctx, term) return nil, err } -func (self *SBaremetalReprepareTask) PostDeploys(term *ssh.Client) error { - self.Baremetal.AutoSyncStatus() +func (self *SBaremetalReprepareTask) PostDeploys(ctx context.Context, term *ssh.Client) error { + self.Baremetal.AutoSyncStatus(ctx) return nil } diff --git a/pkg/baremetal/tasks/start.go b/pkg/baremetal/tasks/start.go index 0452eea493..6b01ab5eba 100644 --- a/pkg/baremetal/tasks/start.go +++ b/pkg/baremetal/tasks/start.go @@ -58,7 +58,7 @@ func (self *SBaremetalServerStartTask) DoBoot(ctx context.Context, args interfac } } } else { - if err := self.Baremetal.SSHReboot(); err != nil { + if err := self.Baremetal.SSHReboot(ctx); err != nil { return errors.Wrap(err, "Try reboot") } } @@ -85,7 +85,7 @@ func (self *SBaremetalServerStartTask) WaitForStart(ctx context.Context, args in } func (self *SBaremetalServerStartTask) OnStartComplete(ctx context.Context, args interface{}) error { - self.Baremetal.SyncAllStatus(types.POWER_STATUS_ON) + self.Baremetal.SyncAllStatus(ctx, types.POWER_STATUS_ON) SetTaskComplete(self, nil) return nil } diff --git a/pkg/baremetal/tasks/unmaintenance.go b/pkg/baremetal/tasks/unmaintenance.go index cec48f9cbf..168598bfe4 100644 --- a/pkg/baremetal/tasks/unmaintenance.go +++ b/pkg/baremetal/tasks/unmaintenance.go @@ -58,12 +58,12 @@ func (task *SBaremetalUnmaintenanceTask) DoUnmaintenance(ctx context.Context, ar } } else { if task.Baremetal.GetServer() != nil { - if err := task.EnsureSSHReboot(); err != nil { + if err := task.EnsureSSHReboot(ctx); err != nil { return errors.Wrap(err, "Do unmaintenance for none BMC server") } } } - task.Baremetal.SyncStatus(baremetalstatus.RUNNING, "") + task.Baremetal.SyncStatus(ctx, baremetalstatus.RUNNING, "") SetTaskComplete(task, nil) return nil } @@ -89,7 +89,7 @@ func (self *SBaremetalUnmaintenanceTask) WaitForStop(ctx context.Context, args i } func (self *SBaremetalUnmaintenanceTask) OnStopComplete(ctx context.Context, args interface{}) error { - self.Baremetal.SyncStatus(baremetalstatus.READY, "") + self.Baremetal.SyncStatus(ctx, baremetalstatus.READY, "") SetTaskComplete(self, nil) return nil } diff --git a/pkg/baremetal/utils/ipmitool/ipmitool.go b/pkg/baremetal/utils/ipmitool/ipmitool.go index bba38c7db4..8d1cc3124f 100644 --- a/pkg/baremetal/utils/ipmitool/ipmitool.go +++ b/pkg/baremetal/utils/ipmitool/ipmitool.go @@ -22,15 +22,13 @@ import ( "strings" "time" - "github.com/pkg/errors" - "yunion.io/x/log" + "yunion.io/x/pkg/errors" "yunion.io/x/pkg/tristate" "yunion.io/x/pkg/util/stringutils" "yunion.io/x/pkg/utils" "yunion.io/x/onecloud/pkg/apis/compute" - "yunion.io/x/onecloud/pkg/baremetal/profiles" "yunion.io/x/onecloud/pkg/cloudcommon/types" "yunion.io/x/onecloud/pkg/util/procutils" "yunion.io/x/onecloud/pkg/util/ssh" @@ -197,7 +195,7 @@ func GetSysInfo(exector IPMIExecutor) (*types.SSystemInfo, error) { return &info, err } -func GetLanChannels(sysinfo *types.SSystemInfo) []int { +/*func GetLanChannels(sysinfo *types.SSystemInfo) []int { return profiles.GetLanChannel(sysinfo) } @@ -207,9 +205,9 @@ func GetDefaultLanChannel(sysinfo *types.SSystemInfo) int { func GetRootId(sysinfo *types.SSystemInfo) int { return profiles.GetRootId(sysinfo) -} +}*/ -func GetLanConfig(exector IPMIExecutor, channel int) (*types.SIPMILanConfig, error) { +func GetLanConfig(exector IPMIExecutor, channel uint8) (*types.SIPMILanConfig, error) { args := newArgs("lan", "print", channel) lines, err := ExecuteCommands(exector, args) if err != nil { @@ -278,14 +276,14 @@ func doActions(exector IPMIExecutor, actionName string, args ...Args) error { return nil } -func SetLanDHCP(exector IPMIExecutor, lanChannel int) error { +func SetLanDHCP(exector IPMIExecutor, lanChannel uint8) error { args := newArgs("lan", "set", lanChannel, "ipsrc", "dhcp") return doActions(exector, "set_lan_dhcp", args) } func SetLanStatic( exector IPMIExecutor, - channel int, + channel uint8, ip string, mask string, gateway string, @@ -313,12 +311,12 @@ func SetLanStatic( return doActions(exector, "set_lan_static", argss...) } -func SetLanStaticIP(exector IPMIExecutor, channel int, ip string) error { +func SetLanStaticIP(exector IPMIExecutor, channel uint8, ip string) error { args := newArgs("lan", "set", channel, "ipaddr", ip) return doActions(exector, "set_lan_static_ip", args) } -func setLanAccess(exector IPMIExecutor, channel int, access string) error { +func setLanAccess(exector IPMIExecutor, channel uint8, access string) error { args := []Args{ newArgs("lan", "set", channel, "access", access), // newArgs("lan", "set", channel, "auth", "ADMIN", "MD5"), @@ -326,11 +324,11 @@ func setLanAccess(exector IPMIExecutor, channel int, access string) error { return doActions(exector, "set_lan_access", args...) } -func EnableLanAccess(exector IPMIExecutor, channel int) error { +func EnableLanAccess(exector IPMIExecutor, channel uint8) error { return setLanAccess(exector, channel, "on") } -func ListLanUsers(exector IPMIExecutor, channel int) ([]compute.IPMIUser, error) { +func ListLanUsers(exector IPMIExecutor, channel uint8) ([]compute.IPMIUser, error) { args := newArgs("user", "list", channel) ret, err := ExecuteCommands(exector, args) if err != nil { @@ -339,7 +337,7 @@ func ListLanUsers(exector IPMIExecutor, channel int) ([]compute.IPMIUser, error) return sysutils.ParseIPMIUser(ret), nil } -func CreateOrSetAdminUser(exector IPMIExecutor, channel int, rootId int, username string, password string) error { +func CreateOrSetAdminUser(exector IPMIExecutor, channel uint8, rootId int, username string, password string) error { users, err := ListLanUsers(exector, channel) if err != nil { return errors.Wrap(err, "List users") @@ -372,7 +370,7 @@ func CreateOrSetAdminUser(exector IPMIExecutor, channel int, rootId int, usernam return SetLanUserAdminPasswd(exector, channel, foundUser.Id, password) } -func SetLanUserAdminPasswd(exector IPMIExecutor, channel int, id int, password string) error { +func SetLanUserAdminPasswd(exector IPMIExecutor, channel uint8, id int, password string) error { var err error password, err = stringutils2.EscapeEchoString(password) if err != nil { @@ -403,7 +401,7 @@ func SetLanUserAdminPasswd(exector IPMIExecutor, channel int, id int, password s return doActions(exector, "set_lan_user_password3", args...) } -func SetIdUserPasswd(exector IPMIExecutor, channel int, id int, user string, password string) error { +func SetIdUserPasswd(exector IPMIExecutor, channel uint8, id int, user string, password string) error { args := newArgs("user", "set", "name", id, user) if err := doActions(exector, fmt.Sprintf("set_id%d_name", id), args); err != nil { return errors.Wrapf(err, "change root id %d to name %s", id, user) diff --git a/pkg/cloudcommon/types/ipmi.go b/pkg/cloudcommon/types/ipmi.go index b17095efc0..cb57fe31ca 100644 --- a/pkg/cloudcommon/types/ipmi.go +++ b/pkg/cloudcommon/types/ipmi.go @@ -26,7 +26,7 @@ type SIPMIInfo struct { Password string `json:"password,omitempty"` IpAddr string `json:"ip_addr,omitempty"` Present bool `json:"present,omitempty"` - LanChannel int `json:"lan_channel,omitzero"` + LanChannel uint8 `json:"lan_channel,omitzero"` Verified bool `json:"verified,omitfalse"` RedfishApi bool `json:"redfish_api,omitfalse"` CdromBoot bool `json:"cdrom_boot,omitfalse"` diff --git a/pkg/compute/models/baremetal/doc.go b/pkg/compute/models/baremetal/doc.go new file mode 100644 index 0000000000..7867814b6c --- /dev/null +++ b/pkg/compute/models/baremetal/doc.go @@ -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 baremetal // import "yunion.io/x/onecloud/pkg/compute/models/baremetal" diff --git a/pkg/compute/models/baremetal/profiles.go b/pkg/compute/models/baremetal/profiles.go new file mode 100644 index 0000000000..4921df03d4 --- /dev/null +++ b/pkg/compute/models/baremetal/profiles.go @@ -0,0 +1,227 @@ +// 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 baremetal + +import ( + "context" + "strings" + + "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" + "yunion.io/x/sqlchemy" + + baremetalapi "yunion.io/x/onecloud/pkg/apis/compute/baremetal" + "yunion.io/x/onecloud/pkg/cloudcommon/db" + "yunion.io/x/onecloud/pkg/httperrors" + "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/pkg/util/stringutils2" +) + +type SBaremetalProfileManager struct { + db.SStandaloneAnonResourceBaseManager +} + +type SBaremetalProfile struct { + db.SStandaloneAnonResourceBase + + // 品牌名称(English) + OemName string `width:"64" charset:"ascii" nullable:"false" default:"" index:"true" list:"user" create:"required"` + + Model string `width:"64" charset:"utf8" list:"user" create:"optional"` + + LanChannel uint8 `list:"user" update:"user" create:"optional"` + + LanChannel2 uint8 `list:"user" update:"user" create:"optional"` + + LanChannel3 uint8 `list:"user" update:"user" create:"optional"` + + // BMC Root账号名称,默认为 root + RootName string `width:"64" charset:"ascii" nullable:"false" list:"user" update:"user" create:"required" default:"root"` + // BMC Root账号ID,默认为 2 + RootId int `list:"user" update:"user" create:"optional" default:"2"` + // 是否要求强密码 + StrongPass bool `list:"user" update:"user" create:"optional"` +} + +var BaremetalProfileManager *SBaremetalProfileManager + +func init() { + BaremetalProfileManager = &SBaremetalProfileManager{ + SStandaloneAnonResourceBaseManager: db.NewStandaloneAnonResourceBaseManager( + SBaremetalProfile{}, + "baremetal_profiles_tbl", + "baremetal_profile", + "baremetal_profiles", + ), + } + BaremetalProfileManager.SetVirtualObject(BaremetalProfileManager) +} + +func (bpm *SBaremetalProfileManager) ListItemFilter( + ctx context.Context, + q *sqlchemy.SQuery, + userCred mcclient.TokenCredential, + query baremetalapi.BaremetalProfileListInput, +) (*sqlchemy.SQuery, error) { + q, err := bpm.SStandaloneAnonResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StandaloneAnonResourceListInput) + if err != nil { + return nil, errors.Wrap(err, "SStandaloneAnonResourceBaseManager.ListItemFilter") + } + + query.Normalize() + + if len(query.OemName) > 0 { + q = q.In("oem_name", query.OemName) + } + if len(query.Model) > 0 { + q = q.In("model", query.Model) + } + + return q, nil +} + +func (bpm *SBaremetalProfileManager) OrderByExtraFields( + ctx context.Context, + q *sqlchemy.SQuery, + userCred mcclient.TokenCredential, + query baremetalapi.BaremetalProfileListInput, +) (*sqlchemy.SQuery, error) { + var err error + + q, err = bpm.SStandaloneAnonResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StandaloneAnonResourceListInput) + if err != nil { + return nil, errors.Wrap(err, "SStandaloneAnonResourceBaseManager.OrderByExtraFields") + } + + return q, nil +} + +func (bpm *SBaremetalProfileManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) { + var err error + + q, err = bpm.SStandaloneAnonResourceBaseManager.QueryDistinctExtraField(q, field) + if err == nil { + return q, nil + } + + return q, nil +} + +func (bpm *SBaremetalProfileManager) ListItemExportKeys(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, keys stringutils2.SSortedStrings) (*sqlchemy.SQuery, error) { + var err error + q, err = bpm.SStandaloneAnonResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys) + if err != nil { + return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemExportKeys") + } + return q, nil +} + +func (bpm *SBaremetalProfileManager) InitializeData() error { + for _, spec := range baremetalapi.PredefinedProfiles { + bp := SBaremetalProfile{} + bp.Id = strings.ToLower(spec.OemName) + if len(bp.Id) == 0 { + bp.Id = baremetalapi.DefaultBaremetalProfileId + } + bp.OemName = strings.ToLower(spec.OemName) + if len(spec.LanChannels) > 0 { + bp.LanChannel = spec.LanChannels[0] + } + if len(spec.LanChannels) > 1 { + bp.LanChannel2 = spec.LanChannels[1] + } + if len(spec.LanChannels) > 2 { + bp.LanChannel3 = spec.LanChannels[2] + } + bp.RootName = spec.RootName + bp.RootId = spec.RootId + bp.StrongPass = spec.StrongPass + bp.SetModelManager(bpm, &bp) + + err := bpm.TableSpec().InsertOrUpdate(context.Background(), &bp) + if err != nil { + return errors.Wrapf(err, "insert default baremetal profile %s", jsonutils.Marshal(bp)) + } + } + return nil +} + +func (bpm *SBaremetalProfileManager) ValidateCreateData( + ctx context.Context, + userCred mcclient.TokenCredential, + ownerId mcclient.IIdentityProvider, + query jsonutils.JSONObject, + input baremetalapi.BaremetalProfileCreateInput, +) (baremetalapi.BaremetalProfileCreateInput, error) { + var err error + input.StandaloneAnonResourceCreateInput, err = bpm.SStandaloneAnonResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StandaloneAnonResourceCreateInput) + if err != nil { + return input, errors.Wrap(err, "StandaloneAnonResourceBaseManager.ValidateCreateData") + } + input.OemName = strings.ToLower(strings.TrimSpace(input.OemName)) + input.Model = strings.ToLower(strings.TrimSpace(input.Model)) + // ensure uniquess + uniqQuery := bpm.fetchByOemNameAndModelQuery(input.OemName, input.Model, true) + cnt, err := uniqQuery.CountWithError() + if err != nil { + return input, errors.Wrap(err, "CountWithError") + } + if cnt > 0 { + return input, errors.Wrapf(httperrors.ErrConflict, "%s/%s already exists", input.OemName, input.Model) + } + if input.LanChannel == 0 { + return input, errors.Wrap(httperrors.ErrInputParameter, "lan_channel must be set") + } + if len(input.RootName) == 0 { + return input, errors.Wrap(httperrors.ErrInputParameter, "root_name must be set") + } + + return input, nil +} + +func (bpm *SBaremetalProfileManager) fetchByOemNameAndModelQuery(oemName, model string, exact bool) *sqlchemy.SQuery { + q := bpm.Query() + if exact { + q = q.Equals("oem_name", oemName) + } else { + q = q.Filter(sqlchemy.OR( + sqlchemy.IsEmpty(q.Field("oem_name")), + sqlchemy.Equals(q.Field("oem_name"), oemName), + )) + } + if exact { + q = q.Equals("model", model) + } else { + q = q.Filter(sqlchemy.OR( + sqlchemy.IsEmpty(q.Field("model")), + sqlchemy.Equals(q.Field("model"), model), + )) + } + return q +} + +func (bp *SBaremetalProfile) ValidateUpdateData( + ctx context.Context, + userCred mcclient.TokenCredential, + query jsonutils.JSONObject, + input baremetalapi.BaremetalProfileUpdateInput, +) (baremetalapi.BaremetalProfileUpdateInput, error) { + var err error + input.StandaloneAnonResourceBaseUpdateInput, err = bp.SStandaloneAnonResourceBase.ValidateUpdateData(ctx, userCred, query, input.StandaloneAnonResourceBaseUpdateInput) + if err != nil { + return input, errors.Wrap(err, "SStandaloneAnonResourceBase.ValidateUpdateData") + } + return input, nil +} diff --git a/pkg/compute/models/initdb.go b/pkg/compute/models/initdb.go index 21b0f8a754..c0c6b53cbe 100644 --- a/pkg/compute/models/initdb.go +++ b/pkg/compute/models/initdb.go @@ -22,6 +22,7 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/proxy" + "yunion.io/x/onecloud/pkg/compute/models/baremetal" ) func InitDB() error { @@ -78,6 +79,8 @@ func InitDB() error { GroupnetworkManager, ElasticcacheManager, + + baremetal.BaremetalProfileManager, } { now := time.Now() err := manager.InitializeData() diff --git a/pkg/compute/service/handlers.go b/pkg/compute/service/handlers.go index 52e717233c..f2e3ee52bd 100644 --- a/pkg/compute/service/handlers.go +++ b/pkg/compute/service/handlers.go @@ -25,6 +25,7 @@ import ( "yunion.io/x/onecloud/pkg/compute/capabilities" "yunion.io/x/onecloud/pkg/compute/misc" "yunion.io/x/onecloud/pkg/compute/models" + baremetalmodels "yunion.io/x/onecloud/pkg/compute/models/baremetal" "yunion.io/x/onecloud/pkg/compute/options" "yunion.io/x/onecloud/pkg/compute/specs" "yunion.io/x/onecloud/pkg/compute/sshkeys" @@ -243,6 +244,8 @@ func InitHandlers(app *appsrv.Application) { models.MiscResourceManager, models.SSLCertificateManager, + + baremetalmodels.BaremetalProfileManager, } { db.RegisterModelManager(manager) handler := db.NewModelHandler(manager) diff --git a/pkg/hostman/hostinfo/hostdhcp/dhcprelay.go b/pkg/hostman/hostinfo/hostdhcp/dhcprelay.go index 0a5f77b455..5b5b913462 100644 --- a/pkg/hostman/hostinfo/hostdhcp/dhcprelay.go +++ b/pkg/hostman/hostinfo/hostdhcp/dhcprelay.go @@ -15,6 +15,7 @@ package hostdhcp import ( + "context" "fmt" "net" "strconv" @@ -83,7 +84,7 @@ func (r *SDHCPRelay) Setup(addr string) error { return nil } -func (r *SDHCPRelay) ServeDHCP(pkt dhcp.Packet, addr *net.UDPAddr, intf *net.Interface) (dhcp.Packet, []string, error) { +func (r *SDHCPRelay) ServeDHCP(ctx context.Context, pkt dhcp.Packet, addr *net.UDPAddr, intf *net.Interface) (dhcp.Packet, []string, error) { pkg, err := r.serveDHCPInternal(pkt, addr, intf) return pkg, nil, err } diff --git a/pkg/hostman/hostinfo/hostdhcp/dhcpserver.go b/pkg/hostman/hostinfo/hostdhcp/dhcpserver.go index 5b00fccf33..ba169f8601 100644 --- a/pkg/hostman/hostinfo/hostdhcp/dhcpserver.go +++ b/pkg/hostman/hostinfo/hostdhcp/dhcpserver.go @@ -15,6 +15,7 @@ package hostdhcp import ( + "context" "fmt" "net" "strings" @@ -237,7 +238,7 @@ func (s *SGuestDHCPServer) IsDhcpPacket(pkt dhcp.Packet) bool { return pkt != nil && (pkt.Type() == dhcp.Request || pkt.Type() == dhcp.Discover) } -func (s *SGuestDHCPServer) ServeDHCP(pkt dhcp.Packet, addr *net.UDPAddr, intf *net.Interface) (dhcp.Packet, []string, error) { +func (s *SGuestDHCPServer) ServeDHCP(ctx context.Context, pkt dhcp.Packet, addr *net.UDPAddr, intf *net.Interface) (dhcp.Packet, []string, error) { pkg, err := s.serveDHCPInternal(pkt, addr, intf) return pkg, nil, err } diff --git a/pkg/mcclient/modules/compute/baremetal/doc.go b/pkg/mcclient/modules/compute/baremetal/doc.go new file mode 100644 index 0000000000..546d692b6c --- /dev/null +++ b/pkg/mcclient/modules/compute/baremetal/doc.go @@ -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 baremetal // import "yunion.io/x/onecloud/pkg/mcclient/modules/compute/baremetal" diff --git a/pkg/mcclient/modules/compute/baremetal/mod_baremeetalprofile.go b/pkg/mcclient/modules/compute/baremetal/mod_baremeetalprofile.go new file mode 100644 index 0000000000..56df553cbf --- /dev/null +++ b/pkg/mcclient/modules/compute/baremetal/mod_baremeetalprofile.go @@ -0,0 +1,78 @@ +// 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 baremetal + +import ( + "sort" + + "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" + + baremetalapi "yunion.io/x/onecloud/pkg/apis/compute/baremetal" + "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/pkg/mcclient/modulebase" + "yunion.io/x/onecloud/pkg/mcclient/modules" + baremetaloptions "yunion.io/x/onecloud/pkg/mcclient/options/compute/baremetal" +) + +type BaremetalProfileManager struct { + modulebase.ResourceManager +} + +func (m *BaremetalProfileManager) GetMatchProfiles(s *mcclient.ClientSession, oemName string, model string) ([]baremetalapi.BaremetalProfileSpec, error) { + params := baremetaloptions.BaremetalProfileListOptions{} + limit := 0 + params.Limit = &limit + params.OemName = []string{"", oemName} + if len(model) > 0 { + params.Model = []string{"", model} + } + + results, err := m.List(s, jsonutils.Marshal(params)) + if err != nil { + return nil, errors.Wrap(err, "List") + } + ret := make([]baremetalapi.BaremetalProfileSpec, 0) + for i := range results.Data { + details := baremetalapi.BaremetalProfileDetails{} + err := results.Data[i].Unmarshal(&details) + if err != nil { + return nil, errors.Wrap(err, "Unmarshal") + } + ret = append(ret, details.ToSpec()) + } + sort.Sort(baremetalapi.BaremetalProfileSpecs(ret)) + return ret, nil +} + +var ( + BaremetalProfiles BaremetalProfileManager +) + +func init() { + BaremetalProfiles = BaremetalProfileManager{modules.NewComputeManager("baremetal_profile", "baremetal_profiles", + []string{ + "oem_name", + "model", + "lan_channel", + "root_id", + "root_name", + "string_pass", + }, + []string{}, + )} + + modules.RegisterCompute(&BaremetalProfiles) +} diff --git a/pkg/mcclient/options/compute/baremetal/doc.go b/pkg/mcclient/options/compute/baremetal/doc.go new file mode 100644 index 0000000000..bdbda76860 --- /dev/null +++ b/pkg/mcclient/options/compute/baremetal/doc.go @@ -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 baremetal // import "yunion.io/x/onecloud/pkg/mcclient/options/compute/baremetal" diff --git a/pkg/mcclient/options/compute/baremetal/profile.go b/pkg/mcclient/options/compute/baremetal/profile.go new file mode 100644 index 0000000000..1af8adb175 --- /dev/null +++ b/pkg/mcclient/options/compute/baremetal/profile.go @@ -0,0 +1,36 @@ +// 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 baremetal + +import ( + "yunion.io/x/jsonutils" + + "yunion.io/x/onecloud/pkg/mcclient/options" +) + +type BaremetalProfileListOptions struct { + options.BaseListOptions + + OemName []string + Model []string +} + +func (opts *BaremetalProfileListOptions) Params() (jsonutils.JSONObject, error) { + return options.ListStructToParams(opts) +} + +type BaremetalProfileIdOptions struct { + options.BaseIdOptions +} diff --git a/pkg/util/dhcp/server.go b/pkg/util/dhcp/server.go index fe2b05450b..83962b7194 100644 --- a/pkg/util/dhcp/server.go +++ b/pkg/util/dhcp/server.go @@ -15,6 +15,7 @@ package dhcp import ( + "context" "fmt" "net" "runtime/debug" @@ -88,7 +89,7 @@ func NewDHCPServer2(iface string, dhcpServerPort, dhcpRelayPort uint16) (*DHCPSe } type DHCPHandler interface { - ServeDHCP(pkt Packet, addr *net.UDPAddr, intf *net.Interface) (Packet, []string, error) + ServeDHCP(ctx context.Context, pkt Packet, addr *net.UDPAddr, intf *net.Interface) (Packet, []string, error) } func (s *DHCPServer) ListenAndServe(handler DHCPHandler) error { @@ -101,6 +102,7 @@ func (s *DHCPServer) GetConn() *Conn { } func (s *DHCPServer) serveDHCP(handler DHCPHandler) error { + ctx := context.WithValue(context.Background(), "dhcp_server", s) for { pkt, addr, mac, intf, err := s.conn.RecvDHCP() if err != nil { @@ -119,7 +121,7 @@ func (s *DHCPServer) serveDHCP(handler DHCPHandler) error { } }() - resp, targets, err := handler.ServeDHCP(pkt, addr, intf) + resp, targets, err := handler.ServeDHCP(ctx, pkt, addr, intf) if err != nil { log.Warningf("[DHCP] handler serve error: %v", err) return diff --git a/pkg/util/ipmitool/shell/lan.go b/pkg/util/ipmitool/shell/lan.go index 0724ef85ee..c0847e0462 100644 --- a/pkg/util/ipmitool/shell/lan.go +++ b/pkg/util/ipmitool/shell/lan.go @@ -23,7 +23,7 @@ import ( func init() { type LanOptions struct { - CHANNEL int `help:"lan channel"` + CHANNEL uint8 `help:"lan channel"` } shellutils.R(&LanOptions{}, "set-lan-dhcp", "Set lan channel DHCP", func(client ipmitool.IPMIExecutor, args *LanOptions) error { return ipmitool.SetLanDHCP(client, args.CHANNEL) diff --git a/scripts/codegen.py b/scripts/codegen.py index e0a6ff7189..7ea1e3af05 100755 --- a/scripts/codegen.py +++ b/scripts/codegen.py @@ -131,6 +131,7 @@ class ModelAPI(FuncDispatcher): run_swagger_gen(['yunion.io/x/cloudmux/pkg/cloudprovider'], 'yunion.io/x/onecloud/pkg/apis/cloudprovider') self.run(pkg=["keystone", "models"], out=["identity"]) self.run_model("compute") + self.run(pkg=["compute", "models", "baremetal"], out=["compute", "baremetal"]) self.run_model("image") self.run_model("cloudid") self.run_model("notify")