diff --git a/cmd/climc/shell/hosts.go b/cmd/climc/shell/hosts.go index e99eabf345..910fe8637d 100644 --- a/cmd/climc/shell/hosts.go +++ b/cmd/climc/shell/hosts.go @@ -135,6 +135,12 @@ func init() { return nil }) + R(&HostOpsOptions{}, "host-sync-config", "Synchronize config of a host", func(s *mcclient.ClientSession, args *HostOpsOptions) error { + results := modules.Hosts.BatchPerformAction(s, args.ID, "sync-config", nil) + printBatchResults(results, modules.Hosts.GetColumns(s)) + return nil + }) + R(&HostOpsOptions{}, "host-prepare", "Prepare a host for installation", func(s *mcclient.ClientSession, args *HostOpsOptions) error { results := modules.Hosts.BatchPerformAction(s, args.ID, "prepare", nil) printBatchResults(results, modules.Hosts.GetColumns(s)) @@ -202,6 +208,10 @@ func init() { // AccessIp string `help:"Change access ip, CAUTION!!!!"` AccessMac string `help:"Change baremetal access MAC, CAUTION!!!!"` Uuid string `help:"Change baremetal UUID, CAUTION!!!!"` + + IpmiUsername string `help:"IPMI user"` + IpmiPassword string `help:"IPMI password"` + IpmiIpAddr string `help:"IPMI ip_addr"` } R(&HostUpdateOptions{}, "host-update", "Update information of a host", func(s *mcclient.ClientSession, args *HostUpdateOptions) error { params := jsonutils.NewDict() @@ -232,6 +242,15 @@ func init() { if len(args.Uuid) > 0 { params.Add(jsonutils.NewString(args.Uuid), "uuid") } + if len(args.IpmiUsername) > 0 { + params.Add(jsonutils.NewString(args.IpmiUsername), "ipmi_username") + } + if len(args.IpmiPassword) > 0 { + params.Add(jsonutils.NewString(args.IpmiPassword), "ipmi_password") + } + if len(args.IpmiIpAddr) > 0 { + params.Add(jsonutils.NewString(args.IpmiIpAddr), "ipmi_ip_addr") + } if params.Size() == 0 { return fmt.Errorf("Not data to update") } diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index 8da30aa37e..b854bc5408 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -4681,3 +4681,27 @@ func (self *SHost) StartEjectIsoTask(ctx context.Context, userCred mcclient.Toke return nil } } + +func (self *SHost) AllowPerformSyncConfig(ctx context.Context, + userCred mcclient.TokenCredential, + query jsonutils.JSONObject, + data jsonutils.JSONObject) bool { + return db.IsAdminAllowPerform(userCred, self, "sync-config") +} + +func (self *SHost) PerformSyncConfig(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + if self.HostType != api.HOST_TYPE_BAREMETAL { + return nil, httperrors.NewBadRequestError("Cannot sync config a non-baremetal host") + } + self.SetStatus(userCred, api.BAREMETAL_SYNCING_STATUS, "") + return nil, self.StartSyncConfig(ctx, userCred, "") +} + +func (self *SHost) StartSyncConfig(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error { + task, err := taskman.TaskManager.NewTask(ctx, "BaremetalSyncConfigTask", self, userCred, nil, parentTaskId, "", nil) + if err != nil { + return err + } + task.ScheduleRun(nil) + return nil +} diff --git a/pkg/compute/tasks/baremetal_sync_config_task.go b/pkg/compute/tasks/baremetal_sync_config_task.go new file mode 100644 index 0000000000..08214d0266 --- /dev/null +++ b/pkg/compute/tasks/baremetal_sync_config_task.go @@ -0,0 +1,64 @@ +// 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 tasks + +import ( + "context" + "fmt" + + "yunion.io/x/jsonutils" + + "yunion.io/x/onecloud/pkg/cloudcommon/db" + "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" + "yunion.io/x/onecloud/pkg/compute/models" + "yunion.io/x/onecloud/pkg/util/logclient" +) + +type BaremetalSyncConfigTask struct { + SBaremetalBaseTask +} + +func init() { + taskman.RegisterTask(BaremetalSyncConfigTask{}) +} + +func (self *BaremetalSyncConfigTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) { + baremetal := obj.(*models.SHost) + if baremetal.IsBaremetal { + self.DoSyncConfig(ctx, baremetal) + } else { + self.SetStageComplete(ctx, nil) + } +} + +func (self *BaremetalSyncConfigTask) DoSyncConfig(ctx context.Context, baremetal *models.SHost) { + self.SetStage("OnSyncConfigComplete", nil) + url := fmt.Sprintf("/baremetals/%s/sync-config", baremetal.Id) + headers := self.GetTaskRequestHeader() + _, err := baremetal.BaremetalSyncRequest(ctx, "POST", url, headers, nil) + if err != nil { + self.SetStageFailed(ctx, err.Error()) + } +} + +func (self *BaremetalSyncConfigTask) OnSyncConfigComplete(ctx context.Context, baremetal *models.SHost, body jsonutils.JSONObject) { + self.SetStage("OnSyncstatusComplete", nil) + baremetal.StartSyncstatus(ctx, self.UserCred, self.GetTaskId()) + logclient.AddActionLogWithStartable(self, baremetal, logclient.ACT_SYNC_CONF, "", self.UserCred, true) +} + +func (self *BaremetalSyncConfigTask) OnSyncstatusComplete(ctx context.Context, baremetal *models.SHost, body jsonutils.JSONObject) { + self.SetStageComplete(ctx, nil) +}