feature: pass ntp server by DHCP option

This commit is contained in:
Qiu Jian
2021-11-03 04:17:21 +08:00
parent 09a28d2264
commit 24825d642a
18 changed files with 233 additions and 34 deletions
+2 -1
View File
@@ -80,8 +80,9 @@ type GuestnetworkJsonDesc struct {
Virtual bool `json:"virtual"`
Ip string `json:"ip"`
Gateway string `json:"gateway"`
DNS string `json:"dns"`
Dns string `json:"dns"`
Domain string `json:"domain"`
Ntp string `json:"ntp"`
Routes jsonutils.JSONObject `json:"routes"`
Ifname string `json:"ifname"`
Masklen int8 `json:"masklen"`
+9 -1
View File
@@ -99,6 +99,8 @@ type NetworkListInput struct {
GuestDns []string `json:"guest_dns"`
// allow multiple dhcp, seperated by ","
GuestDhcp []string `json:"guest_dhcp"`
// NTP
GuestNtp []string `json:"guest_ntp"`
GuestDomain []string `json:"guest_domain"`
@@ -172,13 +174,17 @@ type NetworkCreateInput struct {
GuestGateway string `json:"guest_gateway"`
// description: guest dns
// example: 114.114.114.114
// example: 114.114.114.114,8.8.8.8
GuestDns string `json:"guest_dns"`
// description: guest dhcp
// example: 192.168.222.1,192.168.222.4
GuestDHCP string `json:"guest_dhcp"`
// description: guest ntp
// example: cn.pool.ntp.org,0.cn.pool.ntp.org
GuestNtp string `json:"guest_ntp"`
// swagger:ignore
WireId string `json:"wire_id"`
@@ -349,6 +355,8 @@ type NetworkUpdateInput struct {
GuestDns string `json:"guest_dns"`
// allow multiple dhcp, seperated by ","
GuestDhcp string `json:"guest_dhcp"`
// NTP
GuestNtp string `json:"guest_ntp"`
GuestDomain string `json:"guest_domain"`
+4
View File
@@ -18,6 +18,10 @@ import (
"time"
)
const (
DefaultDNSServers = "223.5.5.5,223.6.6.6"
)
const (
// # DEFAULT_BANDWIDTH = options.default_bandwidth
MAX_BANDWIDTH = 100000
+5 -1
View File
@@ -18,7 +18,11 @@ import (
"yunion.io/x/pkg/util/netutils"
)
const VPC_OVN_ENCAP_COST = 58
// IP: 20
// UDP: 8
// GENEVE HDR: 8 + 4x
// total: 36 + 4x
const VPC_OVN_ENCAP_COST = 60
const (
VPC_EXTERNAL_ACCESS_MODE_DISTGW = "distgw" // distgw only
+18 -3
View File
@@ -185,7 +185,7 @@ func ValueToJSONObject(out reflect.Value) jsonutils.JSONObject {
if obj, ok := isJSONObject(out); ok {
return obj
}
return jsonutils.Marshal(out.Interface())
return jsonutils.MarshalAll(out.Interface())
}
func ValueToJSONDict(out reflect.Value) *jsonutils.JSONDict {
@@ -207,8 +207,23 @@ func ValueToError(out reflect.Value) error {
func mergeInputOutputData(data *jsonutils.JSONDict, resVal reflect.Value) *jsonutils.JSONDict {
retJson := ValueToJSONDict(resVal)
// preserve the input info not returned by caller
data.Update(retJson)
return data
log.Debugf("retJson: %s", retJson)
log.Debugf("data: %s", data)
output := data.Copy()
jsonMap, _ := retJson.GetMap()
for k, v := range jsonMap {
if output.Contains(k) {
if v == jsonutils.JSONNull || v.IsZero() {
output.Remove(k)
} else if !v.IsZero() {
output.Set(k, v)
}
} else if !v.IsZero() {
output.Add(v, k)
}
}
log.Debugf("output: %s", output)
return output
}
func ValidateCreateData(funcName string, manager IModelManager, ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
+1 -1
View File
@@ -114,7 +114,7 @@ const (
type CommonOptions struct {
AuthURL string `help:"Keystone auth URL" alias:"auth-uri"`
AdminUser string `help:"Admin username"`
AdminDomain string `help:"Admin user domain" default:"default"`
AdminDomain string `help:"Admin user domain" default:"Default"`
AdminPassword string `help:"Admin password" alias:"admin-passwd"`
AdminProject string `help:"Admin project" default:"system" alias:"admin-tenant-name"`
AdminProjectDomain string `help:"Domain of Admin project" default:"default"`
+1
View File
@@ -65,6 +65,7 @@ type SServerNic struct {
BandWidth int `json:"bw"`
Mtu int `json:"mtu,omitempty"`
Dns string `json:"dns"`
Ntp string `json:"ntp"`
Net string `json:"net"`
Interface string `json:"interface"`
Gateway string `json:"gateway"`
+2 -1
View File
@@ -563,8 +563,9 @@ func (self *SGuestnetwork) getJsonDesc() *api.GuestnetworkJsonDesc {
desc.Ip = self.IpAddr
}
desc.Gateway = net.GuestGateway
desc.DNS = net.GetDNS()
desc.Dns = net.GetDNS()
desc.Domain = net.GetDomain()
desc.Ntp = net.GetNTP()
routes := net.GetRoutes()
if routes != nil && len(routes) > 0 {
+1
View File
@@ -155,6 +155,7 @@ func (self *SNetInterface) networkToJson(ipAddr string, network *SNetwork, desc
}
desc.Add(jsonutils.NewString(network.GetDNS()), "dns")
desc.Add(jsonutils.NewString(network.GetDomain()), "domain")
desc.Add(jsonutils.NewString(network.GetNTP()), "ntp")
routes := network.GetRoutes()
if routes != nil && len(routes) > 0 {
+74 -15
View File
@@ -111,10 +111,12 @@ type SNetwork struct {
GuestIpMask int8 `nullable:"false" list:"user" update:"user" create:"required"`
// 网关地址
GuestGateway string `width:"16" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
// DNS
GuestDns string `width:"16" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
// DNS, allow multiple dns, seperated by ","
GuestDns string `width:"64" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
// allow multiple dhcp, seperated by ","
GuestDhcp string `width:"64" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
// allow mutiple ntp, seperated by ","
GuestNtp string `width:"64" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
GuestDomain string `width:"128" charset:"ascii" nullable:"true" get:"user" update:"user"`
@@ -385,7 +387,10 @@ func (self *SNetwork) getFreeIP(addrTable map[string]bool, recentUsedAddrTable m
if len(self.AllocPolicy) > 0 && api.IPAllocationDirection(self.AllocPolicy) != api.IPAllocationNone {
allocDir = api.IPAllocationDirection(self.AllocPolicy)
}
if len(allocDir) == 0 || allocDir == api.IPAllocationStepdown {
if len(allocDir) == 0 {
allocDir = api.IPAllocationDirection(options.Options.DefaultIPAllocationDirection)
}
if allocDir == api.IPAllocationStepdown {
ip, _ := netutils.NewIPV4Addr(self.GuestIpEnd)
for iprange.Contains(ip) {
if !isIpUsed(ip.String(), addrTable, recentUsedAddrTable) {
@@ -457,7 +462,42 @@ func (self *SNetwork) GetDNS() string {
if len(self.GuestDns) > 0 {
return self.GuestDns
} else {
return options.Options.DNSServer
zoneName := ""
wire, _ := self.GetWire()
if wire != nil {
zone, _ := wire.GetZone()
if zone != nil {
zoneName = zone.Name
}
}
srvs, _ := auth.GetDNSServers(options.Options.Region, zoneName)
if len(srvs) > 0 {
return strings.Join(srvs, ",")
}
if len(options.Options.DNSServer) > 0 {
return options.Options.DNSServer
}
return api.DefaultDNSServers
}
}
func (self *SNetwork) GetNTP() string {
if len(self.GuestNtp) > 0 {
return self.GuestNtp
} else {
zoneName := ""
wire, _ := self.GetWire()
if wire != nil {
zone, _ := wire.GetZone()
if zone != nil {
zoneName = zone.Name
}
}
srvs, _ := auth.GetNTPServers(options.Options.Region, zoneName)
if len(srvs) > 0 {
return strings.Join(srvs, ",")
}
return ""
}
}
@@ -1532,19 +1572,21 @@ func (manager *SNetworkManager) ValidateCreateData(ctx context.Context, userCred
}
}
if len(input.GuestDns) == 0 {
input.GuestDns = options.Options.DNSServer
}
// do not set default dns
// if len(input.GuestDns) == 0 {
// input.GuestDns = options.Options.DNSServer
// }
for key, ipStr := range map[string]string{
"guest_gateway": input.GuestGateway,
"guest_dns": input.GuestDns,
"guest_dhcp": input.GuestDHCP,
"guest_ntp": input.GuestNtp,
} {
if ipStr == "" {
continue
}
if key == "guest_dhcp" {
if key == "guest_dhcp" || key == "guest_dns" || key == "guest_ntp" {
ipList := strings.Split(ipStr, ",")
for _, ipstr := range ipList {
if !regutils.MatchIPAddr(ipstr) {
@@ -1737,11 +1779,12 @@ func (self *SNetwork) validateUpdateData(ctx context.Context, userCred mcclient.
"guest_gateway": input.GuestGateway,
"guest_dns": input.GuestDns,
"guest_dhcp": input.GuestDhcp,
"guest_ntp": input.GuestNtp,
} {
if ipStr == "" {
continue
}
if key == "guest_dhcp" {
if key == "guest_dhcp" || key == "guest_dns" || key == "guest_ntp" {
ipList := strings.Split(ipStr, ",")
for _, ipstr := range ipList {
if !regutils.MatchIPAddr(ipstr) {
@@ -1772,13 +1815,19 @@ func (self *SNetwork) validateUpdateData(ctx context.Context, userCred mcclient.
}
func (self *SNetwork) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.NetworkUpdateInput) (api.NetworkUpdateInput, error) {
if !self.isManaged() && !self.isOneCloudVpcNetwork() {
var err error
input, err = self.validateUpdateData(ctx, userCred, query, input)
if err != nil {
return input, errors.Wrap(err, "validateUpdateData")
if !self.isManaged() {
if !self.isOneCloudVpcNetwork() {
// classic network
} else {
// vpc network
input.GuestIpStart = ""
input.GuestIpEnd = ""
input.GuestIpMask = nil
input.GuestGateway = ""
input.GuestDhcp = ""
}
} else {
// managed network
input.GuestIpStart = ""
input.GuestIpEnd = ""
input.GuestIpMask = nil
@@ -1786,9 +1835,14 @@ func (self *SNetwork) ValidateUpdateData(ctx context.Context, userCred mcclient.
input.GuestDns = ""
input.GuestDomain = ""
input.GuestDhcp = ""
input.GuestNtp = ""
}
var err error
input, err = self.validateUpdateData(ctx, userCred, query, input)
if err != nil {
return input, errors.Wrap(err, "validateUpdateData")
}
var err error
input.SharableVirtualResourceBaseUpdateInput, err = self.SSharableVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input.SharableVirtualResourceBaseUpdateInput)
if err != nil {
return input, errors.Wrap(err, "SSharableVirtualResourceBase.ValidateUpdateData")
@@ -2162,6 +2216,9 @@ func (manager *SNetworkManager) ListItemFilter(
if len(input.GuestDhcp) > 0 {
q = q.In("guest_dhcp", input.GuestDhcp)
}
if len(input.GuestNtp) > 0 {
q = q.In("guest_ntp", input.GuestNtp)
}
if len(input.GuestDomain) > 0 {
q = q.In("guest_domain", input.GuestDomain)
}
@@ -2534,6 +2591,7 @@ func (self *SNetwork) PerformSplit(ctx context.Context, userCred mcclient.TokenC
network.GuestGateway = self.GuestGateway
network.GuestDns = self.GuestDns
network.GuestDhcp = self.GuestDhcp
network.GuestNtp = self.GuestNtp
network.GuestDomain = self.GuestDomain
network.VlanId = self.VlanId
network.WireId = self.WireId
@@ -2688,6 +2746,7 @@ func (manager *SNetworkManager) PerformTryCreateNetwork(ctx context.Context, use
newNetwork.GuestIpMask = int8(input.Mask)
newNetwork.GuestDns = nm.GuestDns
newNetwork.GuestDhcp = nm.GuestDhcp
newNetwork.GuestNtp = nm.GuestNtp
newNetwork.WireId = nm.WireId
newNetwork.ServerType = input.ServerType
newNetwork.IsPublic = nm.IsPublic
+2
View File
@@ -177,6 +177,8 @@ type ComputeOptions struct {
GlobalMacPrefix string `help:"Global prefix of MAC address, default to 00:22" default:"00:22"`
DefaultIPAllocationDirection string `help:"default IP allocation direction" default:"stepdown"`
esxi.EsxiOptions
}
+14 -1
View File
@@ -24,9 +24,11 @@ import (
"yunion.io/x/log"
"yunion.io/x/pkg/util/netutils"
identityapi "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/cloudcommon/types"
guestman "yunion.io/x/onecloud/pkg/hostman/guestman/types"
"yunion.io/x/onecloud/pkg/hostman/options"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/dhcp"
"yunion.io/x/onecloud/pkg/util/netutils2"
)
@@ -135,8 +137,19 @@ func (s *SGuestDHCPServer) getGuestConfig(guestDesc, guestNic jsonutils.JSONObje
conf.Routes = route
if len(nicdesc.Dns) > 0 {
conf.DNSServer = net.ParseIP(nicdesc.Dns)
conf.DNSServers = make([]net.IP, 0)
for _, dns := range strings.Split(nicdesc.Dns, ",") {
conf.DNSServers = append(conf.DNSServers, net.ParseIP(dns))
}
}
if len(nicdesc.NTPServers) > 0 {
conf.NTPServers = make([]net.IP, 0)
for _, ntp := range strings.Split(nicdesc.Ntp, ",") {
conf.NTPServers = append(conf.NTPServers, net.ParseIP(ntp))
}
}
conf.OsName, _ = guestDesc.GetString("os_name")
conf.LeaseTime = time.Duration(options.HostOptions.DhcpLeaseTime) * time.Second
conf.RenewalTime = time.Duration(options.HostOptions.DhcpRenewalTime) * time.Second
+1 -1
View File
@@ -1696,7 +1696,7 @@ func (h *SHostInfo) OnCatalogChanged(catalog mcclient.KeystoneServiceCatalogV3)
}
if options.HostOptions.ManageNtpConfiguration {
ntpd := system_service.GetService("ntpd")
urls, _ := catalog.GetServiceURLs("ntp", options.HostOptions.Region, "", defaultEndpointType)
urls, _ := catalog.GetServiceURLs("ntp", options.HostOptions.Region, h.Zone, defaultEndpointType)
if len(urls) > 0 {
log.Infof("Get Ntp urls: %v", urls)
} else {
+36
View File
@@ -17,7 +17,9 @@ package auth
import (
"context"
"fmt"
"net"
"net/http"
"strings"
"time"
"yunion.io/x/jsonutils"
@@ -28,6 +30,7 @@ import (
"yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/cloudcommon/syncman"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
var (
@@ -231,6 +234,31 @@ func (a *authManager) GetServiceURLs(service, region, zone, endpointType string)
return a.adminCredential.GetServiceURLs(service, region, zone, endpointType)
}
func (a *authManager) getServiceIPs(service, region, zone, endpointType string, needResolve bool) ([]string, error) {
urls, err := a.GetServiceURLs(service, region, zone, endpointType)
if err != nil {
return nil, errors.Wrap(err, "GetServiceURLs")
}
ret := stringutils2.NewSortedStrings(nil)
for _, url := range urls {
slashIdx := strings.Index(url, "://")
if slashIdx >= 0 {
url = url[slashIdx+3:]
}
if needResolve {
addrs, err := net.LookupHost(url)
if err != nil {
log.Errorf("Lookup host %s fail: %s", url, err)
} else {
ret = ret.Append(addrs...)
}
} else {
ret = ret.Append(url)
}
}
return ret, nil
}
func (a *authManager) getTokenString() string {
return a.adminCredential.GetTokenString()
}
@@ -273,6 +301,14 @@ func GetServiceURLs(service, region, zone, endpointType string) ([]string, error
return manager.GetServiceURLs(service, region, zone, endpointType)
}
func GetDNSServers(region, zone string) ([]string, error) {
return manager.getServiceIPs("dns", region, zone, identity.EndpointInterfacePublic, false)
}
func GetNTPServers(region, zone string) ([]string, error) {
return manager.getServiceIPs("ntp", region, zone, identity.EndpointInterfacePublic, true)
}
func GetTokenString() string {
return manager.getTokenString()
}
+8
View File
@@ -66,6 +66,7 @@ type NetworkUpdateOptions struct {
Dns string `help:"IP of DNS server"`
Domain string `help:"Domain"`
Dhcp string `help:"DHCP server IP"`
Ntp string `help:"Ntp server domain names"`
VlanId int64 `help:"Vlan ID" default:"1"`
ExternalId string `help:"External ID"`
AllocPolicy string `help:"Address allocation policy" choices:"none|stepdown|stepup|random"`
@@ -113,6 +114,13 @@ func (opts *NetworkUpdateOptions) Params() (jsonutils.JSONObject, error) {
params.Add(jsonutils.NewString(opts.Dhcp), "guest_dhcp")
}
}
if len(opts.Ntp) > 0 {
if opts.Ntp == "none" {
params.Add(jsonutils.NewString(""), "guest_ntp")
} else {
params.Add(jsonutils.NewString(opts.Ntp), "guest_ntp")
}
}
if opts.VlanId > 0 {
params.Add(jsonutils.NewInt(opts.VlanId), "vlan_id")
}
+16 -3
View File
@@ -32,6 +32,7 @@ const (
OptClasslessRouteWin OptionCode = 249
)
// http://www.networksorcery.com/enp/rfc/rfc2132.txt
type ResponseConfig struct {
OsName string
ServerIP net.IP // OptServerIdentifier 54
@@ -43,8 +44,9 @@ type ResponseConfig struct {
BroadcastAddr net.IP // OptBroadcastAddr 28
Hostname string // OptHostname 12
SubnetMask net.IP // OptSubnetMask 1
DNSServer net.IP // OptDNSServers
DNSServers []net.IP // OptDNSServers
Routes [][]string // TODO: 249 for windows, 121 for linux
NTPServers []net.IP // OptNTPServers 42
// TFTP config
BootServer string
@@ -64,6 +66,14 @@ func GetOptIP(ip net.IP) []byte {
return []byte(ip.To4())
}
func GetOptIPs(ips []net.IP) []byte {
buf := make([]byte, 0)
for _, ip := range ips {
buf = append(buf, []byte(ip.To4())...)
}
return buf
}
func GetOptTime(d time.Duration) []byte {
timeBytes := make([]byte, 4)
binary.BigEndian.PutUint32(timeBytes, uint32(d/time.Second))
@@ -138,8 +148,11 @@ func makeDHCPReplyPacket(req Packet, conf *ResponseConfig, msgType MessageType)
if conf.Hostname != "" {
opts = append(opts, Option{OptionHostName, []byte(conf.GetHostname())})
}
if conf.DNSServer != nil {
opts = append(opts, Option{OptionDomainNameServer, GetOptIP(conf.DNSServer)})
if len(conf.DNSServers) > 0 {
opts = append(opts, Option{OptionDomainNameServer, GetOptIPs(conf.DNSServers)})
}
if len(conf.NTPServers) > 0 {
opts = append(opts, Option{OptionNetworkTimeProtocolServers, GetOptIPs(conf.NTPServers)})
}
resp := ReplyPacket(req, msgType, conf.ServerIP, conf.ClientIP, conf.LeaseTime, opts)
if conf.BootServer != "" {
+38 -5
View File
@@ -17,6 +17,7 @@ package ovn
import (
"context"
"fmt"
"net"
"sort"
"strings"
@@ -27,7 +28,10 @@ import (
"yunion.io/x/pkg/errors"
apis "yunion.io/x/onecloud/pkg/apis/compute"
identityapi "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/mcclient/auth"
agentmodels "yunion.io/x/onecloud/pkg/vpcagent/models"
"yunion.io/x/onecloud/pkg/vpcagent/options"
"yunion.io/x/onecloud/pkg/vpcagent/ovn/mac"
"yunion.io/x/onecloud/pkg/vpcagent/ovnutil"
)
@@ -264,7 +268,7 @@ func (keeper *OVNNorthboundKeeper) ClaimVpc(ctx context.Context, vpc *agentmodel
return keeper.cli.Must(ctx, "ClaimVpc", args)
}
func (keeper *OVNNorthboundKeeper) ClaimNetwork(ctx context.Context, network *agentmodels.Network, mtu int) error {
func (keeper *OVNNorthboundKeeper) ClaimNetwork(ctx context.Context, network *agentmodels.Network, opts *options.Options) error {
var (
rpMac = mac.HashSubnetRouterPortMac(network.Id)
dhcpMac = mac.HashSubnetDhcpMac(network.Id)
@@ -296,6 +300,7 @@ func (keeper *OVNNorthboundKeeper) ClaimNetwork(ctx context.Context, network *ag
mdIp, "0.0.0.0",
"0.0.0.0/0", network.GuestGateway,
}
mtu := opts.OvnUnderlayMtu
mtu -= apis.VPC_OVN_ENCAP_COST
const (
leaseTime = 86400 * 365 * 3
@@ -318,10 +323,38 @@ func (keeper *OVNNorthboundKeeper) ClaimNetwork(ctx context.Context, network *ag
externalKeyOcRef: network.Id,
},
}
if network.GuestDns != "" {
dhcpopts.Options["dns_server"] = "{" + network.GuestDns + "}"
} else {
dhcpopts.Options["dns_server"] = "{223.5.5.5,223.6.6.6}"
{
dnsSrvs := ""
if network.GuestDns != "" {
dnsSrvs = network.GuestDns
} else {
dns, err := auth.GetDNSServers(opts.Region, "")
if err != nil {
log.Errorf("auth.GetDNSServers fail %s", err)
} else {
dnsSrvs = strings.Join(dns, ",")
}
}
if len(dnsSrvs) == 0 {
dnsSrvs = apis.DefaultDNSServers
}
dhcpopts.Options["dns_server"] = "{" + dnsSrvs + "}"
}
{
ntpSrvs := ""
if network.GuestNtp != "" {
ntpSrvs = network.GuestNtp
} else {
ntp, err := auth.GetNTPServers(opts.Region, "")
if err != nil {
log.Errorf("auth.GetNTPServers fail %s", err)
} else {
ntpSrvs = strings.Join(ntp, ",")
}
}
if len(ntpSrvs) > 0 {
dhcpopts.Options["ntp_server"] = "{" + ntpSrvs + "}"
}
}
var (
+1 -1
View File
@@ -124,7 +124,7 @@ func (w *Worker) run(ctx context.Context, mss *agentmodels.ModelSets) (err error
ovndb.ClaimVpcEipgw(ctx, vpc)
}
for _, network := range vpc.Networks {
ovndb.ClaimNetwork(ctx, network, w.opts.OvnUnderlayMtu)
ovndb.ClaimNetwork(ctx, network, w.opts)
for _, guestnetwork := range network.Guestnetworks {
if guestnetwork.Guest == nil {
continue