mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
fix: allow multi-guest-dhcp
This commit is contained in:
+51
-20
@@ -68,25 +68,29 @@ type dhcpRequest struct {
|
||||
netConfig *types.SNetworkConfig
|
||||
}
|
||||
|
||||
func (h *DHCPHandler) ServeDHCP(pkt dhcp.Packet, _ *net.UDPAddr, _ *net.Interface) (dhcp.Packet, error) {
|
||||
func (h *DHCPHandler) ServeDHCP(pkt dhcp.Packet, _ *net.UDPAddr, _ *net.Interface) (dhcp.Packet, []string, error) {
|
||||
req, err := h.newRequest(pkt, h.baremetalManager)
|
||||
if err != nil {
|
||||
log.Errorf("[DHCP] new request by packet error: %v", err)
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
log.V(4).Debugf("[DHCP] request packet: %#v", req)
|
||||
|
||||
if req.RelayAddr.String() == "0.0.0.0" {
|
||||
return nil, fmt.Errorf("Request not from a DHCP relay, ignore mac: %s", req.ClientMac)
|
||||
return nil, nil, fmt.Errorf("Request not from a DHCP relay, ignore mac: %s", req.ClientMac)
|
||||
}
|
||||
conf, err := req.fetchConfig(h.baremetalManager.GetClientSession())
|
||||
conf, targets, err := req.fetchConfig(h.baremetalManager.GetClientSession())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
if conf == nil {
|
||||
return nil, fmt.Errorf("Empty packet config")
|
||||
return nil, nil, fmt.Errorf("Empty packet config")
|
||||
}
|
||||
return dhcp.MakeReplyPacket(pkt, conf)
|
||||
pkg, err := dhcp.MakeReplyPacket(pkt, conf)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "dhcp.MakeReplyPacket")
|
||||
}
|
||||
return pkg, targets, nil
|
||||
}
|
||||
|
||||
func (h *DHCPHandler) newRequest(pkt dhcp.Packet, man IBaremetalManager) (*dhcpRequest, error) {
|
||||
@@ -173,33 +177,43 @@ func formatUuidString(uuidBytes []byte) string {
|
||||
}, "-")
|
||||
}
|
||||
|
||||
func (req *dhcpRequest) fetchConfig(session *mcclient.ClientSession) (*dhcp.ResponseConfig, error) {
|
||||
func (req *dhcpRequest) fetchConfig(session *mcclient.ClientSession) (*dhcp.ResponseConfig, []string, error) {
|
||||
// 1. find_network_conf
|
||||
netConf, err := req.findNetworkConf(session, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
req.netConfig = netConf
|
||||
var dhcpAddrList []string
|
||||
if len(netConf.GuestDhcp) > 0 {
|
||||
dhcpAddrList = strings.Split(netConf.GuestDhcp, ",")
|
||||
}
|
||||
log.Debugf("dhcpAddrList %s", dhcpAddrList)
|
||||
|
||||
// TODO: set cache for netConf
|
||||
if req.isPXERequest() {
|
||||
if !o.Options.EnablePxeBoot {
|
||||
return nil, errors.Error("PXE Boot disabled")
|
||||
return nil, nil, errors.Error("PXE Boot disabled")
|
||||
}
|
||||
// handle PXE DHCP request
|
||||
log.Infof("DHCP relay from %s(%s) for %s, find matched networks: %#v", req.RelayAddr, req.ClientAddr, req.ClientMac, netConf)
|
||||
bmDesc, err := req.createOrUpdateBaremetal(session)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
err = req.doInitBaremetalAdminNetif(bmDesc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
// always response PXE request
|
||||
// let bootloader decide boot local or remote
|
||||
// if req.baremetalInstance.NeedPXEBoot() {
|
||||
return req.baremetalInstance.GetPXEDHCPConfig(req.ClientArch)
|
||||
conf, err := req.baremetalInstance.GetPXEDHCPConfig(req.ClientArch)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "req.baremetalInstance.GetPXEDHCPConfig")
|
||||
}
|
||||
return conf, dhcpAddrList, nil
|
||||
|
||||
// }
|
||||
// ignore
|
||||
// log.Warningf("No need to pxeboot, ignore the request ...(mac:%s guid:%s)", req.ClientMac, req.ClientGuid)
|
||||
@@ -213,7 +227,7 @@ func (req *dhcpRequest) fetchConfig(session *mcclient.ClientSession) (*dhcp.Resp
|
||||
// from guestdhcp import GuestDHCPHelperTask
|
||||
// task = GuestDHCPHelperTask(self)
|
||||
// task.start()
|
||||
return nil, nil
|
||||
return nil, nil, nil
|
||||
}
|
||||
req.baremetalInstance = bmInstance
|
||||
ipmiNic := req.baremetalInstance.GetIPMINic(req.ClientMac)
|
||||
@@ -221,16 +235,20 @@ func (req *dhcpRequest) fetchConfig(session *mcclient.ClientSession) (*dhcp.Resp
|
||||
err = req.baremetalInstance.InitAdminNetif(
|
||||
req.ClientMac, req.netConfig.WireId, api.NIC_TYPE_IPMI, api.NETWORK_TYPE_IPMI, false, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
} else {
|
||||
err = req.baremetalInstance.RegisterNetif(req.ClientMac, req.netConfig.WireId)
|
||||
if err != nil {
|
||||
log.Errorf("RegisterNetif error: %v", err)
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
return req.baremetalInstance.GetDHCPConfig(req.ClientMac)
|
||||
conf, err := req.baremetalInstance.GetDHCPConfig(req.ClientMac)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "req.baremetalInstance.GetDHCPConfig")
|
||||
}
|
||||
return conf, dhcpAddrList, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,8 +261,14 @@ func (req *dhcpRequest) findNetworkConf(session *mcclient.ClientSession, filterU
|
||||
fmt.Sprintf("guest_gateway.equals(%s)", req.RelayAddr)),
|
||||
"filter.0")
|
||||
params.Add(jsonutils.NewString(
|
||||
fmt.Sprintf("guest_dhcp.equals(%s)", req.RelayAddr)),
|
||||
fmt.Sprintf("guest_dhcp.startswith('%s,')", req.RelayAddr)),
|
||||
"filter.1")
|
||||
params.Add(jsonutils.NewString(
|
||||
fmt.Sprintf("guest_dhcp.contains(',%s,')", req.RelayAddr)),
|
||||
"filter.2")
|
||||
params.Add(jsonutils.NewString(
|
||||
fmt.Sprintf("guest_dhcp.endswith(',%s')", req.RelayAddr)),
|
||||
"filter.3")
|
||||
params.Add(jsonutils.JSONTrue, "filter_any")
|
||||
}
|
||||
params.Add(jsonutils.JSONTrue, "is_on_premise")
|
||||
@@ -259,9 +283,16 @@ func (req *dhcpRequest) findNetworkConf(session *mcclient.ClientSession, filterU
|
||||
}
|
||||
return nil, fmt.Errorf("DHCP relay from %s(%s) for %s, find no match network", req.RelayAddr, req.ClientAddr, req.ClientMac)
|
||||
}
|
||||
|
||||
idx := 0
|
||||
for i := range ret.Data {
|
||||
netType, _ := ret.Data[i].GetString("server_type")
|
||||
if netType == api.NETWORK_TYPE_PXE {
|
||||
idx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
network := types.SNetworkConfig{}
|
||||
err = ret.Data[0].Unmarshal(&network)
|
||||
err = ret.Data[idx].Unmarshal(&network)
|
||||
return &network, err
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,8 @@ type SNetwork struct {
|
||||
GuestIpMask int8 `nullable:"false" list:"user" update:"user" create:"required"` // Column(TINYINT, nullable=False)
|
||||
GuestGateway string `width:"16" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"` // Column(VARCHAR(16, charset='ascii'), nullable=True)
|
||||
GuestDns string `width:"16" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"` // Column(VARCHAR(16, charset='ascii'), nullable=True)
|
||||
GuestDhcp string `width:"16" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"` // Column(VARCHAR(16, charset='ascii'), nullable=True)
|
||||
// allow multiple dhcp, seperated by ","
|
||||
GuestDhcp string `width:"64" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"` // Column(VARCHAR(16, charset='ascii'), nullable=True)
|
||||
|
||||
GuestDomain string `width:"128" charset:"ascii" nullable:"true" get:"user" update:"user"` // Column(VARCHAR(128, charset='ascii'), nullable=True)
|
||||
|
||||
@@ -1212,8 +1213,17 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
|
||||
|
||||
for _, key := range []string{"guest_gateway", "guest_dns", "guest_dhcp"} {
|
||||
ipStr, _ := data.GetString(key)
|
||||
if len(ipStr) > 0 && !regutils.MatchIPAddr(ipStr) {
|
||||
return nil, httperrors.NewInputParameterError("%s: Invalid IP address %s", key, ipStr)
|
||||
if len(ipStr) > 0 {
|
||||
if key == "guest_dhcp" {
|
||||
ipList := strings.Split(ipStr, ",")
|
||||
for _, ipstr := range ipList {
|
||||
if !regutils.MatchIPAddr(ipstr) {
|
||||
return nil, httperrors.NewInputParameterError("%s: Invalid IP address %s", key, ipstr)
|
||||
}
|
||||
}
|
||||
} else if !regutils.MatchIPAddr(ipStr) {
|
||||
return nil, httperrors.NewInputParameterError("%s: Invalid IP address %s", key, ipStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1430,9 +1440,18 @@ func (self *SNetwork) ValidateUpdateData(ctx context.Context, userCred mcclient.
|
||||
if len(ipStr) > 0 {
|
||||
if self.isManaged() {
|
||||
return nil, httperrors.NewForbiddenError("Cannot update a managed network")
|
||||
}
|
||||
if key == "guest_dhcp" {
|
||||
ipList := strings.Split(ipStr, ",")
|
||||
for _, ipstr := range ipList {
|
||||
if !regutils.MatchIPAddr(ipstr) {
|
||||
return nil, httperrors.NewInputParameterError("%s: Invalid IP address %s", key, ipstr)
|
||||
}
|
||||
}
|
||||
} else if !regutils.MatchIPAddr(ipStr) {
|
||||
return nil, httperrors.NewInputParameterError("%s: Invalid IP address %s", key, ipStr)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,12 @@ func (r *SDHCPRelay) Setup(addr string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *SDHCPRelay) ServeDHCP(pkt dhcp.Packet, _ *net.UDPAddr, intf *net.Interface) (dhcp.Packet, error) {
|
||||
func (r *SDHCPRelay) ServeDHCP(pkt dhcp.Packet, addr *net.UDPAddr, intf *net.Interface) (dhcp.Packet, []string, error) {
|
||||
pkg, err := r.serveDHCPInternal(pkt, addr, intf)
|
||||
return pkg, nil, err
|
||||
}
|
||||
|
||||
func (r *SDHCPRelay) serveDHCPInternal(pkt dhcp.Packet, _ *net.UDPAddr, intf *net.Interface) (dhcp.Packet, error) {
|
||||
log.Infof("DHCP Relay Reply TO %s", pkt.CHAddr())
|
||||
v, ok := r.cache.Load(pkt.TransactionID())
|
||||
if ok {
|
||||
|
||||
@@ -159,7 +159,12 @@ func (s *SGuestDHCPServer) IsDhcpPacket(pkt dhcp.Packet) bool {
|
||||
return pkt != nil && (pkt.Type() == dhcp.Request || pkt.Type() == dhcp.Discover)
|
||||
}
|
||||
|
||||
func (s *SGuestDHCPServer) ServeDHCP(pkt dhcp.Packet, addr *net.UDPAddr, intf *net.Interface) (dhcp.Packet, error) {
|
||||
func (s *SGuestDHCPServer) ServeDHCP(pkt dhcp.Packet, addr *net.UDPAddr, intf *net.Interface) (dhcp.Packet, []string, error) {
|
||||
pkg, err := s.serveDHCPInternal(pkt, addr, intf)
|
||||
return pkg, nil, err
|
||||
}
|
||||
|
||||
func (s *SGuestDHCPServer) serveDHCPInternal(pkt dhcp.Packet, addr *net.UDPAddr, intf *net.Interface) (dhcp.Packet, error) {
|
||||
if !s.IsDhcpPacket(pkt) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
+14
-2
@@ -87,7 +87,7 @@ func NewDHCPServer2(iface string, dhcpServerPort, dhcpRelayPort uint16) (*DHCPSe
|
||||
}
|
||||
|
||||
type DHCPHandler interface {
|
||||
ServeDHCP(pkt Packet, addr *net.UDPAddr, intf *net.Interface) (Packet, error)
|
||||
ServeDHCP(pkt Packet, addr *net.UDPAddr, intf *net.Interface) (Packet, []string, error)
|
||||
}
|
||||
|
||||
func (s *DHCPServer) ListenAndServe(handler DHCPHandler) error {
|
||||
@@ -117,7 +117,7 @@ func (s *DHCPServer) serveDHCP(handler DHCPHandler) error {
|
||||
}
|
||||
}()
|
||||
|
||||
resp, err := handler.ServeDHCP(pkt, addr, intf)
|
||||
resp, targets, err := handler.ServeDHCP(pkt, addr, intf)
|
||||
if err != nil {
|
||||
log.Warningf("[DHCP] handler serve error: %v", err)
|
||||
return
|
||||
@@ -126,6 +126,18 @@ func (s *DHCPServer) serveDHCP(handler DHCPHandler) error {
|
||||
// log.Warningf("[DHCP] hander response null packet")
|
||||
return
|
||||
}
|
||||
if len(targets) > 0 {
|
||||
targetUdpAddr := *addr
|
||||
for _, target := range targets {
|
||||
log.Debugf("[DHCP] Send packet back to %s", target)
|
||||
targetUdpAddr.IP = net.ParseIP(target)
|
||||
resp.SetGIAddr(targetUdpAddr.IP)
|
||||
if err = s.conn.SendDHCP(resp, &targetUdpAddr, mac, intf); err != nil {
|
||||
log.Errorf("[DHCP] failed to response packet for %s: %v", pkt.CHAddr(), err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
//log.Debugf("[DHCP] send response packet: %s to interface: %#v", resp.DebugString(), intf)
|
||||
if err = s.conn.SendDHCP(resp, addr, mac, intf); err != nil {
|
||||
log.Errorf("[DHCP] failed to response packet for %s: %v", pkt.CHAddr(), err)
|
||||
|
||||
Reference in New Issue
Block a user