diff --git a/pkg/baremetal/handler/handlers.go b/pkg/baremetal/handler/handlers.go index 2f76102cec..06a940b626 100644 --- a/pkg/baremetal/handler/handlers.go +++ b/pkg/baremetal/handler/handlers.go @@ -54,7 +54,7 @@ func AddHandler2(app *appsrv.Application, method string, prefix string, func customizeHandlerInfo(info *appsrv.SHandlerInfo) { if info.GetName(nil) == "baremetal-register" { - info.SetProcessTimeout(time.Second * 180).SetWorkerManager(registerWorkMan) + info.SetProcessTimeout(time.Second * 300).SetWorkerManager(registerWorkMan) } } diff --git a/pkg/baremetal/handler/middleware.go b/pkg/baremetal/handler/middleware.go index c89e97f69e..f281423652 100644 --- a/pkg/baremetal/handler/middleware.go +++ b/pkg/baremetal/handler/middleware.go @@ -176,13 +176,8 @@ func bmRegisterMiddleware(h bmRegisterFunc) appsrv.FilterHandler { newCtx.ResponseError(httperrors.NewMissingParameterError("password")) return } - ipAddr, err := newCtx.Data().GetString("ip_addr") - if err != nil { - newCtx.ResponseError(httperrors.NewMissingParameterError("ip_addr")) - return - } - ctx, cancel := context.WithTimeout(ctx, time.Second*175) + ctx, cancel := context.WithTimeout(ctx, time.Second*298) defer cancel() data := &baremetal.BmRegisterInput{ @@ -196,7 +191,6 @@ func bmRegisterMiddleware(h bmRegisterFunc) appsrv.FilterHandler { RemoteIp: remoteIp, Username: username, Password: password, - IpAddr: ipAddr, } h(newCtx, data) diff --git a/pkg/baremetal/manager.go b/pkg/baremetal/manager.go index f829f2272f..075705650d 100644 --- a/pkg/baremetal/manager.go +++ b/pkg/baremetal/manager.go @@ -40,7 +40,6 @@ import ( "yunion.io/x/pkg/utils" api "yunion.io/x/onecloud/pkg/apis/compute" - "yunion.io/x/onecloud/pkg/appsrv" o "yunion.io/x/onecloud/pkg/baremetal/options" "yunion.io/x/onecloud/pkg/baremetal/profiles" "yunion.io/x/onecloud/pkg/baremetal/pxe" @@ -265,10 +264,8 @@ type BmRegisterInput struct { IpAddr string } -func (i *BmRegisterInput) responseOk() { - obj := jsonutils.NewDict() - obj.Add(jsonutils.NewString("ok"), "result") - appsrv.SendJSON(i.W, obj) +func (i *BmRegisterInput) responseSucc(bmId string) { + fmt.Fprintf(i.W, bmId) close(i.C) } @@ -295,6 +292,25 @@ func (m *SBaremetalManager) RegisterBaremetal(ctx context.Context, input *BmRegi input.responseErr(httperrors.NewBadRequestError("Verify network failed: %s", err)) return } + + sshCli, err := m.checkSshInfo(input) + if input.isTimeout() { + return + } else if err != nil { + input.responseErr(httperrors.NewBadRequestError("SSH verify failed: %s", err)) + return + } + + input.IpAddr, err = m.fetchIpmiIp(sshCli) + + if input.isTimeout() { + return + } else if err != nil { + input.responseErr(httperrors.NewBadRequestError("Fetch ipmi address failed: %s", err)) + return + } + log.Infof("Find ipmi address %s", input.IpAddr) + ipmiWire, err := m.checkNetworkFromIp(input.IpAddr) if input.isTimeout() { return @@ -311,14 +327,6 @@ func (m *SBaremetalManager) RegisterBaremetal(ctx context.Context, input *BmRegi return } - sshCli, err := m.checkSshInfo(input) - if input.isTimeout() { - return - } else if err != nil { - input.responseErr(httperrors.NewBadRequestError("SSH verify failed: %s", err)) - return - } - err = m.verifyMacAddr(sshCli) if input.isTimeout() { return @@ -332,7 +340,7 @@ func (m *SBaremetalManager) RegisterBaremetal(ctx context.Context, input *BmRegi input.Username, input.Password, input.IpAddr, ipmiMac, ipmiLanChannel, adminWire, ipmiWire, ) - err = registerTask.CreateBaremetal() + bmId, err := registerTask.CreateBaremetal() if input.isTimeout() { return } else if err != nil { @@ -340,10 +348,24 @@ func (m *SBaremetalManager) RegisterBaremetal(ctx context.Context, input *BmRegi return } - input.responseOk() + input.responseSucc(bmId) registerTask.DoPrepare(ctx, sshCli) } +func (m *SBaremetalManager) fetchIpmiIp(sshCli *ssh.Client) (string, error) { + res, err := sshCli.RawRun(`/usr/bin/ipmitool lan print | grep "IP Address "`) + if err != nil { + return "", err + } + if len(res) == 1 { + segs := strings.Fields(res[0]) + if len(segs) == 4 { + return strings.TrimSpace(segs[3]), nil + } + } + return "", fmt.Errorf("Failed to find ipmi ip address") +} + func (m *SBaremetalManager) checkNetworkFromIp(ip string) (string, error) { params := jsonutils.NewDict() params.Set("ip", jsonutils.NewString(ip)) diff --git a/pkg/baremetal/tasks/bm_register.go b/pkg/baremetal/tasks/bm_register.go index 658155d518..21ad7e86c1 100644 --- a/pkg/baremetal/tasks/bm_register.go +++ b/pkg/baremetal/tasks/bm_register.go @@ -73,24 +73,57 @@ func NewBaremetalRegisterTask(bmManager IBmManager, sshCli *ssh.Client, } } -func (s *sBaremetalRegisterTask) CreateBaremetal() error { +func (s *sBaremetalRegisterTask) getAccessDevMacAddr(ip string) (string, error) { + nicsRet, err := s.SshCli.Run("/sbin/ip -o -4 addr show") + if err != nil { + return "", fmt.Errorf("Failed get access nic %s", err) + } + + var dev string + for i := 0; i < len(nicsRet); i++ { + if strings.Contains(nicsRet[i], ip+"/") { + segs := strings.Split(nicsRet[i], " ") + if len(segs) > 1 { + dev = segs[1] + break + } + } + } + if len(dev) == 0 { + return "", fmt.Errorf("Can't get access dev") + } + log.Infof("Access dev is %s", dev) + macRet, err := s.SshCli.Run("/sbin/ip a show " + dev) + if err != nil || len(macRet) < 2 { + return "", fmt.Errorf("Failed get access nic mac address %s", err) + } + segs := strings.Fields(macRet[1]) + if len(segs) < 2 { + return "", fmt.Errorf("Failed to find mac address") + } + return segs[1], nil +} + +func (s *sBaremetalRegisterTask) CreateBaremetal() (string, error) { zoneId := s.BmManager.GetZoneId() ret, err := s.SshCli.Run("/lib/mos/lsnic") if err != nil { - return fmt.Errorf("Register baremeatl failed on lsnic: %s", err) + return "", fmt.Errorf("Register baremeatl failed on lsnic: %s", err) + } + + accessMac, err := s.getAccessDevMacAddr(s.RemoteIp) + if err != nil { + return "", err + } + accessMacAddr, err := net.ParseMAC(accessMac) + if err != nil { + return "", fmt.Errorf("Failed parse access mac %s", accessMac) } nicinfo := sysutils.ParseNicInfo(ret) for _, nic := range nicinfo { - ret, err := s.SshCli.RawRun("/sbin/ip a show " + nic.Dev) - if err != nil { - return fmt.Errorf("Register baremeatl failed on ip command: %s", err) - } - if strings.Index(ret[0], s.RemoteIp) >= 0 { + if nic.Mac.String() == accessMacAddr.String() { s.accessNic = nic - break - } else { - continue } } if s.accessNic == nil { @@ -105,21 +138,22 @@ func (s *sBaremetalRegisterTask) CreateBaremetal() error { params.Set("is_import", jsonutils.JSONTrue) res, err := modules.Hosts.CreateInContext(s.BmManager.GetClientSession(), params, &modules.Zones, zoneId) if err != nil { - return fmt.Errorf("Create baremetal failed: %s", err) + return "", fmt.Errorf("Create baremetal failed: %s", err) } pxeBm, err := s.BmManager.AddBaremetal(res) if err != nil { - return fmt.Errorf("BmManager add baremetal failed: %s", err) + return "", fmt.Errorf("BmManager add baremetal failed: %s", err) } + err = pxeBm.InitAdminNetif( 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) + return "", fmt.Errorf("BmManager add admin netif failed: %s", err) } err = pxeBm.InitAdminNetif( 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) + return "", fmt.Errorf("BmManager add ipmi netif failed: %s", err) } for _, nic := range nicinfo { if nic.Dev != s.accessNic.Dev { @@ -127,7 +161,8 @@ func (s *sBaremetalRegisterTask) CreateBaremetal() error { } } s.baremetal = pxeBm.(IBaremetal) - return nil + bmInstanceId, _ := res.GetString("id") + return bmInstanceId, nil } func (s *sBaremetalRegisterTask) update() { diff --git a/pkg/compute/misc/handler.go b/pkg/compute/misc/handler.go index b75e73515c..0541ef7019 100644 --- a/pkg/compute/misc/handler.go +++ b/pkg/compute/misc/handler.go @@ -17,6 +17,7 @@ package misc import ( "context" "fmt" + "net" "net/http" "yunion.io/x/log" @@ -43,18 +44,17 @@ func addHandler(method, prefix string, f appsrv.FilterHandler, app *appsrv.Appli } func getBmAgentUrl(ctx context.Context, w http.ResponseWriter, r *http.Request) { - _, query, _ := appsrv.FetchEnv(ctx, w, r) - ipAddr, err := query.GetString("ip") + ipAddr, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - httperrors.MissingParameterError(w, "ip") + httperrors.NewInternalServerError("Parse remote ip error %s", err) return } n, _ := models.NetworkManager.GetOnPremiseNetworkOfIP( - ipAddr, compute.NETWORK_TYPE_IPMI, tristate.None) + ipAddr, compute.NETWORK_TYPE_BAREMETAL, tristate.None) if n == nil { n, _ = models.NetworkManager.GetOnPremiseNetworkOfIP( - ipAddr, compute.NETWORK_TYPE_BAREMETAL, tristate.None) + ipAddr, compute.NETWORK_TYPE_IPMI, tristate.None) } if n == nil { httperrors.NotFoundError(w, "Network not found")