diff --git a/pkg/baremetal/handler/handlers.go b/pkg/baremetal/handler/handlers.go index 6f6125deef..2f76102cec 100644 --- a/pkg/baremetal/handler/handlers.go +++ b/pkg/baremetal/handler/handlers.go @@ -218,7 +218,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) { - baremetal.GetBaremetalManager().RegisterBaremetal(input) + baremetal.GetBaremetalManager().RegisterBaremetal(ctx, input) return nil, nil }, nil) } diff --git a/pkg/baremetal/manager.go b/pkg/baremetal/manager.go index a931370bd6..f829f2272f 100644 --- a/pkg/baremetal/manager.go +++ b/pkg/baremetal/manager.go @@ -287,7 +287,7 @@ func (i *BmRegisterInput) isTimeout() bool { } // delay task -func (m *SBaremetalManager) RegisterBaremetal(input *BmRegisterInput) { +func (m *SBaremetalManager) RegisterBaremetal(ctx context.Context, input *BmRegisterInput) { adminWire, err := m.checkNetworkFromIp(input.RemoteIp) if input.isTimeout() { return @@ -303,7 +303,7 @@ func (m *SBaremetalManager) RegisterBaremetal(input *BmRegisterInput) { return } - ipmiMac, err := m.checkIpmiInfo(input.Username, input.Password, input.IpAddr) + ipmiLanChannel, ipmiMac, err := m.checkIpmiInfo(input.Username, input.Password, input.IpAddr) if input.isTimeout() { return } else if err != nil { @@ -330,7 +330,7 @@ func (m *SBaremetalManager) RegisterBaremetal(input *BmRegisterInput) { registerTask := tasks.NewBaremetalRegisterTask( m, sshCli, input.Hostname, input.RemoteIp, input.Username, input.Password, input.IpAddr, - ipmiMac, adminWire, ipmiWire, + ipmiMac, ipmiLanChannel, adminWire, ipmiWire, ) err = registerTask.CreateBaremetal() if input.isTimeout() { @@ -341,7 +341,7 @@ func (m *SBaremetalManager) RegisterBaremetal(input *BmRegisterInput) { } input.responseOk() - registerTask.DoPrepare(sshCli) + registerTask.DoPrepare(ctx, sshCli) } func (m *SBaremetalManager) checkNetworkFromIp(ip string) (string, error) { @@ -407,11 +407,11 @@ func (m *SBaremetalManager) checkSshInfo(input *BmRegisterInput) (*ssh.Client, e return sshCLi, nil } -func (m *SBaremetalManager) checkIpmiInfo(username, password, ipAddr string) (net.HardwareAddr, error) { +func (m *SBaremetalManager) checkIpmiInfo(username, password, ipAddr string) (int, net.HardwareAddr, error) { lanPlusTool := ipmitool.NewLanPlusIPMI(ipAddr, username, password) sysInfo, err := ipmitool.GetSysInfo(lanPlusTool) if err != nil { - return nil, err + return -1, nil, err } for _, lanChannel := range ipmitool.GetLanChannels(sysInfo) { @@ -423,9 +423,9 @@ func (m *SBaremetalManager) checkIpmiInfo(username, password, ipAddr string) (ne if len(config.Mac) == 0 { continue } - return config.Mac, nil + return lanChannel, config.Mac, nil } - return nil, fmt.Errorf("Ipmi can't fetch lan config") + return -1, nil, fmt.Errorf("Ipmi can't fetch lan config") } func (m *SBaremetalManager) Stop() { @@ -1861,7 +1861,7 @@ func (b *SBaremetalInstance) doCronJobs(ctx context.Context) { for _, job := range b.cronJobs { now := time.Now().UTC() if job.NeedsToRun(now) { - log.Debugf("need to run %s", job.Name()) + // log.Debugf("need to run %s", job.Name()) func() { job.StartRun() defer job.StopRun() diff --git a/pkg/baremetal/tasks/bm_register.go b/pkg/baremetal/tasks/bm_register.go index ef9fba2dc8..658155d518 100644 --- a/pkg/baremetal/tasks/bm_register.go +++ b/pkg/baremetal/tasks/bm_register.go @@ -15,6 +15,7 @@ package tasks import ( + "context" "fmt" "net" "strings" @@ -27,6 +28,7 @@ import ( "yunion.io/x/onecloud/pkg/baremetal/utils/ipmitool" "yunion.io/x/onecloud/pkg/cloudcommon/types" "yunion.io/x/onecloud/pkg/mcclient/modules" + "yunion.io/x/onecloud/pkg/util/redfish" "yunion.io/x/onecloud/pkg/util/ssh" "yunion.io/x/onecloud/pkg/util/sysutils" ) @@ -44,26 +46,30 @@ type sBaremetalRegisterTask struct { IpmiPassword string IpmiIpAddr string IpmiMac net.HardwareAddr - AdminWire string - IpmiWire string + + IpmiLanChannel int + + AdminWire string + IpmiWire string accessNic *types.SNicDevInfo } func NewBaremetalRegisterTask(bmManager IBmManager, sshCli *ssh.Client, hostname, remoteIp, ipmiUsername, ipmiPassword, ipmiIpAddr string, - ipmiMac net.HardwareAddr, adminWire, ipmiWire string) *sBaremetalRegisterTask { + ipmiMac net.HardwareAddr, ipmiLanChannel int, adminWire, ipmiWire string) *sBaremetalRegisterTask { return &sBaremetalRegisterTask{ - BmManager: bmManager, - SshCli: sshCli, - Hostname: hostname, - RemoteIp: remoteIp, - IpmiUsername: ipmiUsername, - IpmiPassword: ipmiPassword, - IpmiIpAddr: ipmiIpAddr, - IpmiMac: ipmiMac, - AdminWire: adminWire, - IpmiWire: ipmiWire, + BmManager: bmManager, + SshCli: sshCli, + Hostname: hostname, + RemoteIp: remoteIp, + IpmiUsername: ipmiUsername, + IpmiPassword: ipmiPassword, + IpmiIpAddr: ipmiIpAddr, + IpmiMac: ipmiMac, + IpmiLanChannel: ipmiLanChannel, + AdminWire: adminWire, + IpmiWire: ipmiWire, } } @@ -128,15 +134,33 @@ func (s *sBaremetalRegisterTask) update() { } -func (s *sBaremetalRegisterTask) DoPrepare(cli *ssh.Client) error { +func (s *sBaremetalRegisterTask) doRedfishProbe(ctx context.Context) (redfishSupport bool, cdromBoot bool) { + redfishCli := redfish.NewRedfishDriver(ctx, "https://"+s.IpmiIpAddr, s.IpmiUsername, s.IpmiPassword, false) + if redfishCli != nil { + _, cdInfo, _ := redfishCli.GetVirtualCdromInfo(ctx) + redfishSupport = true + cdromBoot = cdInfo.SupportAction + } + return +} + +func (s *sBaremetalRegisterTask) DoPrepare(ctx context.Context, cli *ssh.Client) error { infos, err := s.prepareBaremetalInfo(cli) if err != nil { return err } + redfishSupport, cdromSupport := s.doRedfishProbe(ctx) + infos.ipmiInfo.IpAddr = s.IpmiIpAddr infos.ipmiInfo.Username = s.IpmiUsername infos.ipmiInfo.Password = s.IpmiPassword + infos.ipmiInfo.LanChannel = s.IpmiLanChannel + infos.ipmiInfo.Verified = true + infos.ipmiInfo.Present = true + infos.ipmiInfo.RedfishApi = redfishSupport + infos.ipmiInfo.CdromBoot = cdromSupport + s.updateIpmiInfo(cli) return s.updateBmInfo(cli, infos) diff --git a/pkg/cloudcommon/app/mergeconf.go b/pkg/cloudcommon/app/mergeconf.go index 273e21843d..3c7b709d43 100644 --- a/pkg/cloudcommon/app/mergeconf.go +++ b/pkg/cloudcommon/app/mergeconf.go @@ -19,6 +19,7 @@ import ( "database/sql" "yunion.io/x/jsonutils" + "yunion.io/x/log" "yunion.io/x/pkg/errors" "yunion.io/x/sqlchemy" @@ -65,19 +66,21 @@ func MergeServiceConfig(opts interface{}, serviceType string, serviceVersion str if len(serviceId) > 0 { serviceConf, err := getServiceConfig(s, serviceId) if err != nil { - return errors.Wrap(err, "getServiceConfig") + log.Errorf("getServiceConfig for %s failed: %s", serviceType, err) + } else { + conf.Update(serviceConf) + merged = true } - conf.Update(serviceConf) - merged = true } commonServiceId, _ := getServiceIdByType(s, consts.COMMON_SERVICE, "") if len(commonServiceId) > 0 { commonConf, err := getServiceConfig(s, commonServiceId) if err != nil { - return errors.Wrap(err, "getServiceConfig common service") + log.Errorf("getServiceConfig for %s failed: %s", consts.COMMON_SERVICE, err) + } else { + conf.Update(commonConf) + merged = true } - conf.Update(commonConf) - merged = true } if merged { err := conf.Unmarshal(opts) @@ -89,7 +92,8 @@ func MergeServiceConfig(opts interface{}, serviceType string, serviceVersion str nconf.Add(conf, "config", "default") _, err := modules.ServicesV3.PerformAction(s, serviceId, "config", nconf) if err != nil { - return errors.Wrap(err, "modules.ServicesV3.PerformAction") + // ignore the error + log.Errorf("fail to save config: %s", err) } } } diff --git a/pkg/compute/guestdrivers/baremetals.go b/pkg/compute/guestdrivers/baremetals.go index dc4f497c35..9128295ed1 100644 --- a/pkg/compute/guestdrivers/baremetals.go +++ b/pkg/compute/guestdrivers/baremetals.go @@ -261,9 +261,13 @@ func (self *SBaremetalGuestDriver) RequestGuestCreateAllDisks(ctx context.Contex return storageCache.StartImageCacheTask(ctx, task.GetUserCred(), imageId, diskCat.Root.DiskFormat, false, task.GetTaskId()) } -func (self *SBaremetalGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, task taskman.ITask) error { +func (self *SBaremetalGuestDriver) NeedRequestGuestHotAddIso(ctx context.Context, guest *models.SGuest) bool { + return true +} + +func (self *SBaremetalGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, boot bool, task taskman.ITask) error { host := guest.GetHost() - return host.StartInsertIsoTask(ctx, task.GetUserCred(), filepath.Base(path), false, task.GetTaskId()) + return host.StartInsertIsoTask(ctx, task.GetUserCred(), filepath.Base(path), boot, task.GetTaskId()) } func (self *SBaremetalGuestDriver) RequestGuestHotRemoveIso(ctx context.Context, guest *models.SGuest, task taskman.ITask) error { @@ -272,8 +276,7 @@ func (self *SBaremetalGuestDriver) RequestGuestHotRemoveIso(ctx context.Context, } func (self *SBaremetalGuestDriver) RequestGuestCreateInsertIso(ctx context.Context, imageId string, guest *models.SGuest, task taskman.ITask) error { - host := guest.GetHost() - return host.StartInsertIsoTask(ctx, task.GetUserCred(), imageId, true, task.GetTaskId()) + return guest.StartInsertIsoTask(ctx, imageId, true, guest.HostId, task.GetUserCred(), task.GetTaskId()) } func (self *SBaremetalGuestDriver) RequestStartOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, userCred mcclient.TokenCredential, task taskman.ITask) (jsonutils.JSONObject, error) { diff --git a/pkg/compute/guestdrivers/base.go b/pkg/compute/guestdrivers/base.go index fd2c2c7f36..1a347eea54 100644 --- a/pkg/compute/guestdrivers/base.go +++ b/pkg/compute/guestdrivers/base.go @@ -199,7 +199,11 @@ func (self *SBaseGuestDriver) RequestChangeVmConfig(ctx context.Context, guest * return fmt.Errorf("Not Implement") } -func (self *SBaseGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, task taskman.ITask) error { +func (self *SBaseGuestDriver) NeedRequestGuestHotAddIso(ctx context.Context, guest *models.SGuest) bool { + return false +} + +func (self *SBaseGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, boot bool, task taskman.ITask) error { return fmt.Errorf("Not Implement") } diff --git a/pkg/compute/guestdrivers/container.go b/pkg/compute/guestdrivers/container.go index ca0ac3f633..bb5abb50cb 100644 --- a/pkg/compute/guestdrivers/container.go +++ b/pkg/compute/guestdrivers/container.go @@ -77,7 +77,7 @@ func (self *SContainerDriver) RequestGuestCreateAllDisks(ctx context.Context, gu return nil } -func (self *SContainerDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, task taskman.ITask) error { +func (self *SContainerDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, boot bool, task taskman.ITask) error { // do nothing, call next stage task.ScheduleRun(nil) return nil diff --git a/pkg/compute/guestdrivers/esxi.go b/pkg/compute/guestdrivers/esxi.go index fdbc764850..0cb07ea0bc 100644 --- a/pkg/compute/guestdrivers/esxi.go +++ b/pkg/compute/guestdrivers/esxi.go @@ -106,7 +106,7 @@ func (self *SESXiGuestDriver) CanKeepDetachDisk() bool { // return nil // } -func (self *SESXiGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, task taskman.ITask) error { +func (self *SESXiGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, boot bool, task taskman.ITask) error { task.ScheduleRun(nil) return nil } diff --git a/pkg/compute/guestdrivers/kvm.go b/pkg/compute/guestdrivers/kvm.go index d6fab80b53..677bca258d 100644 --- a/pkg/compute/guestdrivers/kvm.go +++ b/pkg/compute/guestdrivers/kvm.go @@ -408,7 +408,11 @@ func (self *SKVMGuestDriver) RequestGuestCreateAllDisks(ctx context.Context, gue return guest.StartGuestCreateDiskTask(ctx, task.GetUserCred(), input.Disks, task.GetTaskId()) } -func (self *SKVMGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, task taskman.ITask) error { +func (self *SKVMGuestDriver) NeedRequestGuestHotAddIso(ctx context.Context, guest *models.SGuest) bool { + return guest.Status == api.VM_RUNNING +} + +func (self *SKVMGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, boot bool, task taskman.ITask) error { return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId()) } diff --git a/pkg/compute/guestdrivers/virtualization.go b/pkg/compute/guestdrivers/virtualization.go index 5edecaf1ac..93ac579c51 100644 --- a/pkg/compute/guestdrivers/virtualization.go +++ b/pkg/compute/guestdrivers/virtualization.go @@ -163,7 +163,7 @@ func (self *SVirtualizedGuestDriver) ChooseHostStorage(host *models.SHost, backe } func (self *SVirtualizedGuestDriver) RequestGuestCreateInsertIso(ctx context.Context, imageId string, guest *models.SGuest, task taskman.ITask) error { - return guest.StartInsertIsoTask(ctx, imageId, guest.HostId, task.GetUserCred(), task.GetTaskId()) + return guest.StartInsertIsoTask(ctx, imageId, true, guest.HostId, task.GetUserCred(), task.GetTaskId()) } func (self *SVirtualizedGuestDriver) StartGuestStopTask(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error { diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 4334951205..5969647799 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -882,7 +882,7 @@ func (self *SGuest) PerformInsertiso(ctx context.Context, userCred mcclient.Toke } if utils.IsInStringArray(self.Status, []string{api.VM_RUNNING, api.VM_READY}) { - err = self.StartInsertIsoTask(ctx, image.Id, self.HostId, userCred, "") + err = self.StartInsertIsoTask(ctx, image.Id, false, self.HostId, userCred, "") return nil, err } else { return nil, httperrors.NewServerStatusError("Insert ISO not allowed in status %s", self.Status) @@ -918,12 +918,15 @@ func (self *SGuest) StartEjectisoTask(ctx context.Context, userCred mcclient.Tok return nil } -func (self *SGuest) StartInsertIsoTask(ctx context.Context, imageId string, hostId string, userCred mcclient.TokenCredential, parentTaskId string) error { +func (self *SGuest) StartInsertIsoTask(ctx context.Context, imageId string, boot bool, hostId string, userCred mcclient.TokenCredential, parentTaskId string) error { self.insertIso(imageId) data := jsonutils.NewDict() data.Add(jsonutils.NewString(imageId), "image_id") data.Add(jsonutils.NewString(hostId), "host_id") + if boot { + data.Add(jsonutils.JSONTrue, "boot") + } task, err := taskman.TaskManager.NewTask(ctx, "GuestInsertIsoTask", self, userCred, data, parentTaskId, "", nil) if err != nil { diff --git a/pkg/compute/models/guestdrivers.go b/pkg/compute/models/guestdrivers.go index f0cb0ab507..ab6bdf684a 100644 --- a/pkg/compute/models/guestdrivers.go +++ b/pkg/compute/models/guestdrivers.go @@ -150,7 +150,8 @@ type IGuestDriver interface { DoGuestCreateDisksTask(ctx context.Context, guest *SGuest, task taskman.ITask) error RequestChangeVmConfig(ctx context.Context, guest *SGuest, task taskman.ITask, instanceType string, vcpuCount, vmemSize int64) error - RequestGuestHotAddIso(ctx context.Context, guest *SGuest, path string, task taskman.ITask) error + NeedRequestGuestHotAddIso(ctx context.Context, guest *SGuest) bool + RequestGuestHotAddIso(ctx context.Context, guest *SGuest, path string, boot bool, task taskman.ITask) error RequestGuestHotRemoveIso(ctx context.Context, guest *SGuest, task taskman.ITask) error RequestRebuildRootDisk(ctx context.Context, guest *SGuest, task taskman.ITask) error diff --git a/pkg/compute/tasks/guest_backup_tasks.go b/pkg/compute/tasks/guest_backup_tasks.go index 197429facc..9f75dc22fd 100644 --- a/pkg/compute/tasks/guest_backup_tasks.go +++ b/pkg/compute/tasks/guest_backup_tasks.go @@ -278,7 +278,7 @@ func (self *GuestCreateBackupTask) StartCreateBackupDisks(ctx context.Context, g func (self *GuestCreateBackupTask) StartInsertIso(ctx context.Context, guest *models.SGuest, imageId string) { self.SetStage("OnInsertIso", nil) - guest.StartInsertIsoTask(ctx, imageId, guest.BackupHostId, self.UserCred, self.GetTaskId()) + guest.StartInsertIsoTask(ctx, imageId, false, guest.BackupHostId, self.UserCred, self.GetTaskId()) } func (self *GuestCreateBackupTask) OnInsertIso(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) { diff --git a/pkg/compute/tasks/guest_insert_iso_task.go b/pkg/compute/tasks/guest_insert_iso_task.go index fa80aee7c5..5caea25bdc 100644 --- a/pkg/compute/tasks/guest_insert_iso_task.go +++ b/pkg/compute/tasks/guest_insert_iso_task.go @@ -19,7 +19,6 @@ import ( "yunion.io/x/jsonutils" - api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" "yunion.io/x/onecloud/pkg/compute/models" @@ -77,9 +76,10 @@ func (self *GuestInsertIsoTask) OnIsoPrepareComplete(ctx context.Context, obj db guest := obj.(*models.SGuest) if guest.InsertIsoSucc(imageId, path, int(size), name) { db.OpsLog.LogEvent(guest, db.ACT_ISO_ATTACH, guest.GetDetailsIso(self.UserCred), self.UserCred) - if guest.Status == api.VM_RUNNING { + if guest.GetDriver().NeedRequestGuestHotAddIso(ctx, guest) { self.SetStage("OnConfigSyncComplete", nil) - guest.GetDriver().RequestGuestHotAddIso(ctx, guest, path, self) + boot := jsonutils.QueryBoolean(self.Params, "boot", false) + guest.GetDriver().RequestGuestHotAddIso(ctx, guest, path, boot, self) } else { self.SetStageComplete(ctx, nil) } diff --git a/pkg/util/influxdb/metrics.go b/pkg/util/influxdb/metrics.go index e32b31e995..4383d03b6d 100644 --- a/pkg/util/influxdb/metrics.go +++ b/pkg/util/influxdb/metrics.go @@ -51,8 +51,10 @@ func (m *SMetricData) Line() string { line := strings.Builder{} line.WriteString(m.Name) for i := range m.Tags { - line.WriteByte(',') - line.WriteString(m.Tags[i].String()) + if len(m.Tags[i].Key) > 0 && len(m.Tags[i].Value) > 0 { + line.WriteByte(',') + line.WriteString(m.Tags[i].String()) + } } line.WriteByte(' ') for i := range m.Metrics {