pxe.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package pxe
  15. import (
  16. "context"
  17. "fmt"
  18. "net"
  19. "yunion.io/x/cloudmux/pkg/apis/compute"
  20. "yunion.io/x/jsonutils"
  21. computeapi "yunion.io/x/onecloud/pkg/apis/compute"
  22. "yunion.io/x/onecloud/pkg/cloudcommon/types"
  23. "yunion.io/x/onecloud/pkg/mcclient"
  24. "yunion.io/x/onecloud/pkg/util/dhcp"
  25. )
  26. const (
  27. portDHCP = 67
  28. portTFTP = 69
  29. )
  30. // Architecture describes a kind of CPU architecture
  31. type Architecture int
  32. // Architecture types that pxe knows how to boot
  33. // These architectures are self-reported by the booting machine. The
  34. // machine may support additional execution mode. For example, legacy
  35. // PC BIOS reports itself as an ArchIA32, but may also support ArchX64
  36. // execution
  37. const (
  38. // ArchIA32 is a 32-bit x86 machine. It may also support X64
  39. // execution, but pxe has no way of kowning.
  40. ArchIA32 Architecture = iota
  41. // ArchX64 is a 64-bit x86 machine (aka amd64 aka x64)
  42. ArchX64
  43. ArchUnknown
  44. )
  45. func (a Architecture) String() string {
  46. switch a {
  47. case ArchIA32:
  48. return "IA32"
  49. case ArchX64:
  50. return "X64"
  51. default:
  52. return "Unknown architecture"
  53. }
  54. }
  55. // A Machine describes a machine that is attempting to boot
  56. type Machine struct {
  57. MAC net.HardwareAddr
  58. Arch Architecture
  59. }
  60. // Firmware describes a kind of firmware attempting to boot.
  61. // This should only be used for selecting the right bootloader within
  62. // pxe, kernel selection should key off the more generic
  63. // Architecture
  64. type Firmware int
  65. // The bootloaders that pxe knows how to handle
  66. const (
  67. FirmwareX86PC Firmware = iota // "Classic" x86 BIOS with PXE/UNDI support
  68. FirmwareEFI32 // 32-bit x86 processor running EFI
  69. FirmwareEFI64 // 64-bit x86 processor running EFI
  70. FirmwareEFIBC // 64-bit x86 processor running EFI
  71. FirmwareX86Ipxe // "Classic" x86 BIOS running iPXE (no UNDI support)
  72. FirmwareUnknown
  73. )
  74. type IBaremetalManager interface {
  75. GetZoneId() string
  76. GetBaremetalByMac(mac net.HardwareAddr) IBaremetalInstance
  77. AddBaremetal(ctx context.Context, desc jsonutils.JSONObject) (IBaremetalInstance, error)
  78. GetClientSession() *mcclient.ClientSession
  79. }
  80. type IBaremetalInstance interface {
  81. NeedPXEBoot() bool
  82. GetIPMINic(cliMac net.HardwareAddr) *types.SNic
  83. GetPXEDHCPConfig(arch uint16) (*dhcp.ResponseConfig, error)
  84. GetDHCPConfig(cliMac net.HardwareAddr) (*dhcp.ResponseConfig, error)
  85. InitAdminNetif(ctx context.Context, cliMac net.HardwareAddr, wireId string, nicType compute.TNicType, netType computeapi.TNetworkType, isDoImport bool, ipAddr string) error
  86. RegisterNetif(ctx context.Context, cliMac net.HardwareAddr, wireId string) error
  87. GetTFTPResponse() string
  88. }
  89. type Server struct {
  90. // Address to listen on, or empty for all interfaces
  91. Address string
  92. DHCPPort int
  93. ListenIface string
  94. TFTPPort int
  95. TFTPRootDir string
  96. errs chan error
  97. BaremetalManager IBaremetalManager
  98. }
  99. func (s *Server) Serve() error {
  100. if s.Address == "" {
  101. s.Address = "0.0.0.0"
  102. }
  103. if s.DHCPPort == 0 {
  104. s.DHCPPort = portDHCP
  105. }
  106. if s.TFTPPort == 0 {
  107. s.TFTPPort = portTFTP
  108. }
  109. tftpConn, err := net.ListenPacket("udp", fmt.Sprintf("%s:%d", s.Address, s.TFTPPort))
  110. if err != nil {
  111. return err
  112. }
  113. tftpHandler, err := NewTFTPHandler(s.TFTPRootDir, s.BaremetalManager)
  114. if err != nil {
  115. return err
  116. }
  117. dhcpSrv, err := dhcp.NewDHCPServer3(s.Address, s.DHCPPort)
  118. if err != nil {
  119. return err
  120. }
  121. s.errs = make(chan error)
  122. dhcpHandler := &DHCPHandler{baremetalManager: s.BaremetalManager}
  123. go func() { s.errs <- s.serveDHCP(dhcpSrv, dhcpHandler) }()
  124. go func() { s.errs <- s.serveTFTP(tftpConn, tftpHandler) }()
  125. err = <-s.errs
  126. return err
  127. }