From 1dd89ffd59908d0076eee3f4ab4cb35e38492b28 Mon Sep 17 00:00:00 2001 From: Zexi Li Date: Wed, 19 Dec 2018 18:59:04 +0800 Subject: [PATCH] baremetal related api --- pkg/baremetal/handler/delay.go | 12 +++-- pkg/baremetal/handler/handlers.go | 25 +++++++-- pkg/baremetal/handler/middleware.go | 4 +- pkg/baremetal/manager.go | 43 ++++++++++++++- pkg/baremetal/tasks/resetbmc.go | 67 ++++++++++++++++++++++++ pkg/baremetal/utils/ipmitool/ipmitool.go | 2 +- 6 files changed, 139 insertions(+), 14 deletions(-) create mode 100644 pkg/baremetal/tasks/resetbmc.go diff --git a/pkg/baremetal/handler/delay.go b/pkg/baremetal/handler/delay.go index bc11a11753..852aba82cb 100644 --- a/pkg/baremetal/handler/delay.go +++ b/pkg/baremetal/handler/delay.go @@ -14,30 +14,32 @@ func init() { delayTaskWorkerMan = appsrv.NewWorkerManager("DelayTaskWorkerManager", 8, 1024) } -type ProcessFunc func() (jsonutils.JSONObject, error) +type ProcessFunc func(data jsonutils.JSONObject) (jsonutils.JSONObject, error) type delayTask struct { process ProcessFunc taskId string session *mcclient.ClientSession + data jsonutils.JSONObject } -func newDelayTask(process ProcessFunc, session *mcclient.ClientSession, taskId string) *delayTask { +func newDelayTask(process ProcessFunc, session *mcclient.ClientSession, taskId string, data jsonutils.JSONObject) *delayTask { return &delayTask{ process: process, taskId: taskId, session: session, + data: data, } } -func DelayProcess(process ProcessFunc, session *mcclient.ClientSession, taskId string) { +func DelayProcess(process ProcessFunc, session *mcclient.ClientSession, taskId string, data jsonutils.JSONObject) { delayTaskWorkerMan.Run(func() { - executeDelayProcess(newDelayTask(process, session, taskId)) + executeDelayProcess(newDelayTask(process, session, taskId, data)) }, nil, nil) } func executeDelayProcess(task *delayTask) { - ret, err := task.process() + ret, err := task.process(task.data) if err != nil { modules.ComputeTasks.TaskFailed(task.session, task.taskId, err) return diff --git a/pkg/baremetal/handler/handlers.go b/pkg/baremetal/handler/handlers.go index bb386eb4cd..71e42f3a7d 100644 --- a/pkg/baremetal/handler/handlers.go +++ b/pkg/baremetal/handler/handlers.go @@ -5,7 +5,6 @@ import ( "yunion.io/x/onecloud/pkg/appsrv" "yunion.io/x/onecloud/pkg/baremetal" - "yunion.io/x/onecloud/pkg/baremetal/tasks" "yunion.io/x/onecloud/pkg/httperrors" ) @@ -19,7 +18,10 @@ func initBaremetalsHandler(app *appsrv.Application) { app.AddHandler("POST", getBaremetalPrefix("unmaintenance"), objectMiddleware(handleBaremetalUnmaintenance)) app.AddHandler("POST", getBaremetalPrefix("delete"), objectMiddleware(handleBaremetalDelete)) app.AddHandler("POST", getBaremetalPrefix("syncstatus"), objectMiddleware(handleBaremetalSyncStatus)) + app.AddHandler("POST", getBaremetalPrefix("sync-config"), objectMiddleware(handleBaremetalSyncConfig)) + app.AddHandler("POST", getBaremetalPrefix("sync-ipmi"), objectMiddleware(handleBaremetalSyncIPMI)) app.AddHandler("POST", getBaremetalPrefix("prepare"), objectMiddleware(handleBaremetalPrepare)) + app.AddHandler("POST", getBaremetalPrefix("reset-bmc"), objectMiddleware(handleBaremetalResetBMC)) } func handleBaremetalNotify(ctx *Context, bm *baremetal.SBaremetalInstance) { @@ -38,7 +40,7 @@ func handleBaremetalNotify(ctx *Context, bm *baremetal.SBaremetalInstance) { task := bm.GetTask() log.Errorf("====== get task %#v", task) if task != nil { - task.(*tasks.SBaremetalServerPrepareTask).SSHExecute(task, remoteAddr, key, nil) + task.SSHExecute(task, remoteAddr, key, nil) } ctx.ResponseOk() } @@ -54,12 +56,22 @@ func handleBaremetalUnmaintenance(ctx *Context, bm *baremetal.SBaremetalInstance } func handleBaremetalDelete(ctx *Context, bm *baremetal.SBaremetalInstance) { - ctx.DelayProcess(bm.DelayedRemove) + ctx.DelayProcess(bm.DelayedRemove, nil) ctx.ResponseOk() } func handleBaremetalSyncStatus(ctx *Context, bm *baremetal.SBaremetalInstance) { - ctx.DelayProcess(bm.DelayedSyncStatus) + ctx.DelayProcess(bm.DelayedSyncStatus, nil) + ctx.ResponseOk() +} + +func handleBaremetalSyncConfig(ctx *Context, bm *baremetal.SBaremetalInstance) { + ctx.DelayProcess(bm.DelayedSyncDesc, nil) + ctx.ResponseOk() +} + +func handleBaremetalSyncIPMI(ctx *Context, bm *baremetal.SBaremetalInstance) { + ctx.DelayProcess(bm.DelayedSyncIPMIInfo, nil) ctx.ResponseOk() } @@ -67,3 +79,8 @@ func handleBaremetalPrepare(ctx *Context, bm *baremetal.SBaremetalInstance) { bm.StartBaremetalReprepareTask(ctx.UserCred(), ctx.TaskId(), ctx.Data()) ctx.ResponseOk() } + +func handleBaremetalResetBMC(ctx *Context, bm *baremetal.SBaremetalInstance) { + bm.StartBaremetalResetBMCTask(ctx.UserCred(), ctx.TaskId(), ctx.Data()) + ctx.ResponseOk() +} diff --git a/pkg/baremetal/handler/middleware.go b/pkg/baremetal/handler/middleware.go index 91ed7d8a05..c93c4394d2 100644 --- a/pkg/baremetal/handler/middleware.go +++ b/pkg/baremetal/handler/middleware.go @@ -123,6 +123,6 @@ func (ctx *Context) GetBaremetalManager() *baremetal.SBaremetalManager { return baremetal.GetBaremetalManager() } -func (ctx *Context) DelayProcess(process ProcessFunc) { - DelayProcess(process, ctx.GetBaremetalManager().GetClientSession(), ctx.TaskId()) +func (ctx *Context) DelayProcess(process ProcessFunc, data jsonutils.JSONObject) { + DelayProcess(process, ctx.GetBaremetalManager().GetClientSession(), ctx.TaskId(), data) } diff --git a/pkg/baremetal/manager.go b/pkg/baremetal/manager.go index 90159c8a9d..167dffb761 100644 --- a/pkg/baremetal/manager.go +++ b/pkg/baremetal/manager.go @@ -450,7 +450,7 @@ func (b *SBaremetalInstance) AutoSyncAllStatus() { b.SyncAllStatus("") } -func (b *SBaremetalInstance) DelayedSyncStatus() (jsonutils.JSONObject, error) { +func (b *SBaremetalInstance) DelayedSyncStatus(_ jsonutils.JSONObject) (jsonutils.JSONObject, error) { b.AutoSyncAllStatus() return nil, nil } @@ -816,7 +816,7 @@ func (b *SBaremetalInstance) GetZoneId() string { return b.manager.GetZoneId() } -func (b *SBaremetalInstance) DelayedRemove() (jsonutils.JSONObject, error) { +func (b *SBaremetalInstance) DelayedRemove(_ jsonutils.JSONObject) (jsonutils.JSONObject, error) { b.remove() return nil, nil } @@ -847,3 +847,42 @@ func (b *SBaremetalInstance) StartBaremetalReprepareTask(userCred mcclient.Token task := tasks.NewBaremetalReprepareTask(b, taskId, data) b.SetTask(task) } + +func (b *SBaremetalInstance) StartBaremetalResetBMCTask(userCred mcclient.TokenCredential, taskId string, data jsonutils.JSONObject) { + task := tasks.NewBaremetalResetBMCTask(b, taskId, data) + b.SetTask(task) +} + +func (b *SBaremetalInstance) DelayedSyncIPMIInfo(data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + ipmiCli := b.GetIPMITool() + lanChannel := b.GetIPMILanChannel() + sysInfo, err := ipmitool.GetSysInfo(ipmiCli) + if err != nil { + return nil, err + } + if lanChannel <= 0 { + lanChannel = ipmitool.GetDefaultLanChannel(sysInfo) + } + retObj := make(map[string]string) + if ipAddr, _ := data.GetString("ip_addr"); ipAddr != "" { + err = ipmitool.SetLanStaticIP(ipmiCli, lanChannel, ipAddr) + if err != nil { + return nil, err + } + // TODO: netutils.wait_ip_alive(ipAddr, 120) + retObj["ipmi_ip_addr"] = ipAddr + } + if passwd, _ := data.GetString("password"); passwd != "" { + err = ipmitool.SetLanPasswd(ipmiCli, ipmitool.GetRootId(sysInfo), passwd) + if err != nil { + return nil, err + } + retObj["ipmi_password"] = passwd + } + return jsonutils.Marshal(retObj), nil +} + +func (b *SBaremetalInstance) DelayedSyncDesc(data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + err := b.SaveDesc(data) + return nil, err +} diff --git a/pkg/baremetal/tasks/resetbmc.go b/pkg/baremetal/tasks/resetbmc.go new file mode 100644 index 0000000000..f751ae4e20 --- /dev/null +++ b/pkg/baremetal/tasks/resetbmc.go @@ -0,0 +1,67 @@ +package tasks + +import ( + "context" + "time" + + "yunion.io/x/jsonutils" + + "yunion.io/x/onecloud/pkg/baremetal/types" + "yunion.io/x/onecloud/pkg/baremetal/utils/ipmitool" + "yunion.io/x/onecloud/pkg/util/ssh" +) + +type SBaremetalResetBMCTask struct { + *SBaremetalPXEBootTaskBase + term *ssh.Client +} + +func NewBaremetalResetBMCTask( + baremetal IBaremetal, + taskId string, + data jsonutils.JSONObject, +) *SBaremetalResetBMCTask { + task := new(SBaremetalResetBMCTask) + baseTask := newBaremetalPXEBootTaskBase(baremetal, taskId, data) + task.SBaremetalPXEBootTaskBase = baseTask + baseTask.InitPXEBootTask(task, data) + return task +} + +func (self *SBaremetalResetBMCTask) GetName() string { + return "BaremetalResetBMCTask" +} + +func (self *SBaremetalResetBMCTask) GetIPMITool() *ipmitool.SSHIPMI { + return ipmitool.NewSSHIPMI(self.term) +} + +func (self *SBaremetalResetBMCTask) OnPXEBoot(ctx context.Context, term *ssh.Client, args interface{}) error { + self.term = term + self.SetStage(self.WaitForBMCReady) + err := ipmitool.DoBMCReset(self.GetIPMITool()) + if err != nil { + return err + } + time.Sleep(10 * time.Second) + ExecuteTask(self, nil) + return nil +} + +func (self *SBaremetalResetBMCTask) WaitForBMCReady(ctx context.Context, args interface{}) error { + self.SetStage(self.OnBMCReady) + status, err := ipmitool.GetChassisPowerStatus(self.GetIPMITool()) + if err != nil { + return err + } + if status != "" && status == types.POWER_STATUS_ON { + ExecuteTask(self, nil) + } + return nil +} + +func (self *SBaremetalResetBMCTask) OnBMCReady(ctx context.Context, args interface{}) error { + time.Sleep(20 * time.Second) + SetTaskComplete(self, nil) + return nil +} diff --git a/pkg/baremetal/utils/ipmitool/ipmitool.go b/pkg/baremetal/utils/ipmitool/ipmitool.go index a67f469881..9834274b84 100644 --- a/pkg/baremetal/utils/ipmitool/ipmitool.go +++ b/pkg/baremetal/utils/ipmitool/ipmitool.go @@ -330,7 +330,7 @@ func SetLanUserPasswd(exector IPMIExecutor, channel int, user string, password s return doActions(exector, "set_lan_user_password3", args...) } -func SetLanPasswd(exector IPMIExecutor, rootId string, password string) error { +func SetLanPasswd(exector IPMIExecutor, rootId int, password string) error { // TODO: escape password args := newArgs("user", "set", "password", rootId, fmt.Sprint("\"%s\"", password)) return doActions(exector, "set_lan_passwd", args)