diff --git a/manager/searcher/searcher.go b/manager/searcher/searcher.go index 175927063..d073e62ba 100644 --- a/manager/searcher/searcher.go +++ b/manager/searcher/searcher.go @@ -23,6 +23,7 @@ import ( "errors" "fmt" "net" + "regexp" "sort" "strings" @@ -46,13 +47,16 @@ const ( const ( // cidrAffinityWeight is CIDR affinity weight. - cidrAffinityWeight float64 = 0.4 + cidrAffinityWeight float64 = 0.3 + + // hostnameAffinityWeight is hostname affinity weight. + hostnameAffinityWeight = 0.3 // idcAffinityWeight is IDC affinity weight. - idcAffinityWeight float64 = 0.35 + idcAffinityWeight float64 = 0.25 // locationAffinityWeight is location affinity weight. - locationAffinityWeight = 0.24 + locationAffinityWeight = 0.14 // clusterTypeWeight is cluster type weight. clusterTypeWeight float64 = 0.01 @@ -73,9 +77,10 @@ const ( // Scheduler cluster scopes. type Scopes struct { - IDC string `mapstructure:"idc"` - Location string `mapstructure:"location"` - CIDRs []string `mapstructure:"cidrs"` + IDC string `mapstructure:"idc"` + Location string `mapstructure:"location"` + CIDRs []string `mapstructure:"cidrs"` + Hostnames []string `mapstructure:"hostnames"` } type Searcher interface { @@ -150,6 +155,7 @@ func FilterSchedulerClusters(conditions map[string]string, schedulerClusters []m // Evaluate the degree of matching between scheduler cluster and dfdaemon. func Evaluate(ip, hostname string, conditions map[string]string, scopes Scopes, cluster models.SchedulerCluster, log *zap.SugaredLogger) float64 { return cidrAffinityWeight*calculateCIDRAffinityScore(ip, scopes.CIDRs, log) + + hostnameAffinityWeight*calculateHostnameAffinityScore(hostname, scopes.Hostnames, log) + idcAffinityWeight*calculateIDCAffinityScore(conditions[ConditionIDC], scopes.IDC) + locationAffinityWeight*calculateMultiElementAffinityScore(conditions[ConditionLocation], scopes.Location) + clusterTypeWeight*calculateClusterTypeScore(cluster) @@ -186,6 +192,31 @@ func calculateCIDRAffinityScore(ip string, cidrs []string, log *zap.SugaredLogge return maxScore } +// calculateHostnameAffinityScore 0.0~1.0 larger and better. +func calculateHostnameAffinityScore(hostname string, hostnames []string, log *zap.SugaredLogger) float64 { + if hostname == "" { + return minScore + } + + if len(hostnames) == 0 { + return minScore + } + + for _, v := range hostnames { + regex, err := regexp.Compile(v) + if err != nil { + log.Error(err) + continue + } + + if regex.MatchString(hostname) { + return maxScore + } + } + + return minScore +} + // calculateIDCAffinityScore 0.0~1.0 larger and better. func calculateIDCAffinityScore(dst, src string) float64 { if dst == "" || src == "" { diff --git a/manager/searcher/searcher_test.go b/manager/searcher/searcher_test.go index e5b00bd75..577334d6a 100644 --- a/manager/searcher/searcher_test.go +++ b/manager/searcher/searcher_test.go @@ -176,6 +176,40 @@ func TestSearcher_FindSchedulerClusters(t *testing.T) { assert.Equal(len(data), 2) }, }, + { + name: "match according to hostname condition", + schedulerClusters: []models.SchedulerCluster{ + { + Name: "foo", + Scopes: map[string]any{ + "hostnames": []string{"f.*"}, + }, + Schedulers: []models.Scheduler{ + { + Hostname: "foo", + State: "active", + }, + }, + }, + { + Name: "bar", + Scopes: map[string]any{}, + Schedulers: []models.Scheduler{ + { + Hostname: "bar", + State: "active", + }, + }, + }, + }, + conditions: map[string]string{}, + expect: func(t *testing.T, data []models.SchedulerCluster, err error) { + assert := assert.New(t) + assert.Equal(data[0].Name, "foo") + assert.Equal(data[1].Name, "bar") + assert.Equal(len(data), 2) + }, + }, { name: "match according to idc and location conditions", schedulerClusters: []models.SchedulerCluster{ @@ -266,9 +300,10 @@ func TestSearcher_FindSchedulerClusters(t *testing.T) { { Name: "foo", Scopes: map[string]any{ - "idc": "IDC-1", - "location": "LOCATION-2", - "cidrs": []string{"128.168.1.0/24"}, + "idc": "IDC-1", + "location": "LOCATION-2", + "cidrs": []string{"128.168.1.0/24"}, + "hostnames": []string{"b.*"}, }, Schedulers: []models.Scheduler{ { @@ -280,9 +315,10 @@ func TestSearcher_FindSchedulerClusters(t *testing.T) { { Name: "bar", Scopes: map[string]any{ - "idc": "IDC-1", - "location": "LOCATION-1", - "cidrs": []string{"128.168.1.0/24"}, + "idc": "IDC-1", + "location": "LOCATION-1", + "cidrs": []string{"128.168.1.0/24"}, + "hostnames": []string{"c.*"}, }, Schedulers: []models.Scheduler{ { @@ -294,9 +330,10 @@ func TestSearcher_FindSchedulerClusters(t *testing.T) { { Name: "baz", Scopes: map[string]any{ - "idc": "IDC-1", - "location": "LOCATION-1|LOCATION-2", - "cidrs": []string{"128.168.1.0/24"}, + "idc": "IDC-1", + "location": "LOCATION-1|LOCATION-2", + "cidrs": []string{"128.168.1.0/24"}, + "hostnames": []string{"f.*"}, }, Schedulers: []models.Scheduler{ { @@ -308,9 +345,10 @@ func TestSearcher_FindSchedulerClusters(t *testing.T) { { Name: "bax", Scopes: map[string]any{ - "idc": "IDC-1", - "location": "LOCATION-2", - "cidrs": []string{"128.168.1.0/24"}, + "idc": "IDC-1", + "location": "LOCATION-2", + "cidrs": []string{"128.168.1.0/24"}, + "hostnames": []string{"d.*"}, }, Schedulers: []models.Scheduler{ { @@ -323,9 +361,10 @@ func TestSearcher_FindSchedulerClusters(t *testing.T) { { Name: "bac", Scopes: map[string]any{ - "idc": "IDC-1", - "location": "LOCATION-2", - "cidrs": []string{"128.168.1.0/24"}, + "idc": "IDC-1", + "location": "LOCATION-2", + "cidrs": []string{"128.168.1.0/24"}, + "hostnames": []string{"e.*"}, }, Schedulers: []models.Scheduler{ { @@ -337,9 +376,10 @@ func TestSearcher_FindSchedulerClusters(t *testing.T) { { Name: "bae", Scopes: map[string]any{ - "idc": "IDC-1", - "location": "LOCATION-2", - "cidrs": []string{"128.168.1.0/24"}, + "idc": "IDC-1", + "location": "LOCATION-2", + "cidrs": []string{"128.168.1.0/24"}, + "hostnames": []string{"a.*"}, }, Schedulers: []models.Scheduler{ { @@ -352,9 +392,10 @@ func TestSearcher_FindSchedulerClusters(t *testing.T) { { Name: "bat", Scopes: map[string]any{ - "idc": "IDC-1", - "location": "LOCATION-2", - "cidrs": []string{"192.168.1.0/24"}, + "idc": "IDC-1", + "location": "LOCATION-2", + "cidrs": []string{"192.168.1.0/24"}, + "hostnames": []string{"g.*"}, }, Schedulers: []models.Scheduler{ { diff --git a/manager/types/scheduler_cluster.go b/manager/types/scheduler_cluster.go index 363cd3b46..2a47caa0f 100644 --- a/manager/types/scheduler_cluster.go +++ b/manager/types/scheduler_cluster.go @@ -61,7 +61,8 @@ type SchedulerClusterClientConfig struct { } type SchedulerClusterScopes struct { - IDC string `yaml:"idc" mapstructure:"idc" json:"idc" binding:"omitempty"` - Location string `yaml:"location" mapstructure:"location" json:"location" binding:"omitempty"` - CIDRs []string `yaml:"cidrs" mapstructure:"cidrs" json:"cidrs" binding:"omitempty"` + IDC string `yaml:"idc" mapstructure:"idc" json:"idc" binding:"omitempty"` + Location string `yaml:"location" mapstructure:"location" json:"location" binding:"omitempty"` + CIDRs []string `yaml:"cidrs" mapstructure:"cidrs" json:"cidrs" binding:"omitempty"` + Hostnames []string `yaml:"hostnames" mapstructure:"hostnames" json:"hostnames" binding:"omitempty"` }