feat: dfdaemon list scheduler cluster with multi idc (#917)

Signed-off-by: Gaius <gaius.qi@gmail.com>
This commit is contained in:
Gaius 2021-12-10 19:13:51 +08:00
parent 0751333215
commit 40a281a752
No known key found for this signature in database
GPG Key ID: 8B4E5D1290FA2FFB
2 changed files with 99 additions and 15 deletions

View File

@ -139,6 +139,7 @@ func (s *searcher) FindSchedulerCluster(ctx context.Context, schedulerClusters [
for _, cluster := range clusters { for _, cluster := range clusters {
var scopes Scopes var scopes Scopes
if err := mapstructure.Decode(cluster.Scopes, &scopes); err != nil { if err := mapstructure.Decode(cluster.Scopes, &scopes); err != nil {
logger.Infof("cluster %s decode scopes failed: %v", cluster.Name, err)
// Scopes parse failed to skip this evaluation // Scopes parse failed to skip this evaluation
continue continue
} }
@ -162,10 +163,24 @@ func Evaluate(conditions map[string]string, scopes Scopes) float64 {
// calculateIDCAffinityScore 0.0~1.0 larger and better // calculateIDCAffinityScore 0.0~1.0 larger and better
func calculateIDCAffinityScore(dst, src string) float64 { func calculateIDCAffinityScore(dst, src string) float64 {
if dst != "" && src != "" && strings.Compare(dst, src) == 0 { if dst == "" || src == "" {
return minScore
}
if strings.Compare(dst, src) == 0 {
return maxScore return maxScore
} }
// Dst has only one element, src has multiple elements separated by "|".
// When dst element matches one of the multiple elements of src,
// it gets the max score of idc.
srcElements := strings.Split(src, "|")
for _, srcElement := range srcElements {
if strings.Compare(dst, srcElement) == 0 {
return maxScore
}
}
return minScore return minScore
} }

View File

@ -117,7 +117,7 @@ func TestSchedulerCluster(t *testing.T) {
{ {
Name: "foo", Name: "foo",
Scopes: map[string]interface{}{ Scopes: map[string]interface{}{
"location": []string{"location-1"}, "location": "location-1",
}, },
Schedulers: []model.Scheduler{ Schedulers: []model.Scheduler{
{ {
@ -149,7 +149,7 @@ func TestSchedulerCluster(t *testing.T) {
{ {
Name: "foo", Name: "foo",
Scopes: map[string]interface{}{ Scopes: map[string]interface{}{
"idc": []string{"idc-1"}, "idc": "idc|idc-1",
}, },
Schedulers: []model.Scheduler{ Schedulers: []model.Scheduler{
{ {
@ -160,6 +160,9 @@ func TestSchedulerCluster(t *testing.T) {
}, },
{ {
Name: "bar", Name: "bar",
Scopes: map[string]interface{}{
"idc": "idc-2|idc-3",
},
Schedulers: []model.Scheduler{ Schedulers: []model.Scheduler{
{ {
HostName: "bar", HostName: "bar",
@ -168,10 +171,10 @@ func TestSchedulerCluster(t *testing.T) {
}, },
}, },
}, },
conditions: map[string]string{"idc": "idc-1"}, conditions: map[string]string{"idc": "idc-2"},
expect: func(t *testing.T, data model.SchedulerCluster, err error) { expect: func(t *testing.T, data model.SchedulerCluster, err error) {
assert := assert.New(t) assert := assert.New(t)
assert.Equal(data.Name, "foo") assert.Equal(data.Name, "bar")
assert.NoError(err) assert.NoError(err)
}, },
}, },
@ -181,7 +184,7 @@ func TestSchedulerCluster(t *testing.T) {
{ {
Name: "foo", Name: "foo",
Scopes: map[string]interface{}{ Scopes: map[string]interface{}{
"net_topology": []string{"net-topology-1"}, "net_topology": "net-topology-1",
}, },
Schedulers: []model.Scheduler{ Schedulers: []model.Scheduler{
{ {
@ -213,8 +216,8 @@ func TestSchedulerCluster(t *testing.T) {
{ {
Name: "foo", Name: "foo",
Scopes: map[string]interface{}{ Scopes: map[string]interface{}{
"location": []string{"location-1"}, "location": "location-1|location-2",
"idc": []string{"idc-1"}, "idc": "idc-1|idc-2",
}, },
Schedulers: []model.Scheduler{ Schedulers: []model.Scheduler{
{ {
@ -249,7 +252,7 @@ func TestSchedulerCluster(t *testing.T) {
{ {
Name: "foo", Name: "foo",
Scopes: map[string]interface{}{ Scopes: map[string]interface{}{
"location": []string{"location-1"}, "location": "location-1",
}, },
SecurityGroup: model.SecurityGroup{ SecurityGroup: model.SecurityGroup{
SecurityRules: []model.SecurityRule{ SecurityRules: []model.SecurityRule{
@ -291,7 +294,7 @@ func TestSchedulerCluster(t *testing.T) {
{ {
Name: "foo", Name: "foo",
Scopes: map[string]interface{}{ Scopes: map[string]interface{}{
"idc": []string{"idc-1"}, "idc": "idc-1",
}, },
SecurityGroup: model.SecurityGroup{ SecurityGroup: model.SecurityGroup{
SecurityRules: []model.SecurityRule{ SecurityRules: []model.SecurityRule{
@ -328,13 +331,13 @@ func TestSchedulerCluster(t *testing.T) {
}, },
}, },
{ {
name: "match according to all conditions", name: "match according to security_domain, idc and location conditions",
schedulerClusters: []model.SchedulerCluster{ schedulerClusters: []model.SchedulerCluster{
{ {
Name: "foo", Name: "foo",
Scopes: map[string]interface{}{ Scopes: map[string]interface{}{
"idc": []string{"idc-1"}, "idc": "idc-1",
"location": []string{"location-1"}, "location": "location-1",
}, },
SecurityGroup: model.SecurityGroup{ SecurityGroup: model.SecurityGroup{
SecurityRules: []model.SecurityRule{ SecurityRules: []model.SecurityRule{
@ -352,6 +355,17 @@ func TestSchedulerCluster(t *testing.T) {
}, },
{ {
Name: "bar", Name: "bar",
Scopes: map[string]interface{}{
"idc": "idc-2",
"location": "location-1",
},
SecurityGroup: model.SecurityGroup{
SecurityRules: []model.SecurityRule{
{
Domain: "domain-1",
},
},
},
Schedulers: []model.Scheduler{ Schedulers: []model.Scheduler{
{ {
HostName: "bar", HostName: "bar",
@ -362,8 +376,8 @@ func TestSchedulerCluster(t *testing.T) {
}, },
conditions: map[string]string{ conditions: map[string]string{
"security_domain": "domain-1", "security_domain": "domain-1",
"idc": "idc-1", "idc": "idc-1|idc-2",
"location": "location-1", "location": "location-1|location-2",
}, },
expect: func(t *testing.T, data model.SchedulerCluster, err error) { expect: func(t *testing.T, data model.SchedulerCluster, err error) {
assert := assert.New(t) assert := assert.New(t)
@ -371,6 +385,61 @@ func TestSchedulerCluster(t *testing.T) {
assert.NoError(err) assert.NoError(err)
}, },
}, },
{
name: "match according to all conditions",
schedulerClusters: []model.SchedulerCluster{
{
Name: "foo",
Scopes: map[string]interface{}{
"idc": "idc-1",
"location": "location-2",
},
SecurityGroup: model.SecurityGroup{
SecurityRules: []model.SecurityRule{
{
Domain: "domain-1",
},
},
},
Schedulers: []model.Scheduler{
{
HostName: "foo",
State: "active",
},
},
},
{
Name: "bar",
Scopes: map[string]interface{}{
"idc": "idc-1",
"location": "location-1",
},
SecurityGroup: model.SecurityGroup{
SecurityRules: []model.SecurityRule{
{
Domain: "domain-1",
},
},
},
Schedulers: []model.Scheduler{
{
HostName: "bar",
State: "active",
},
},
},
},
conditions: map[string]string{
"security_domain": "domain-1",
"idc": "idc-1|idc-2",
"location": "location-1|location-2",
},
expect: func(t *testing.T, data model.SchedulerCluster, err error) {
assert := assert.New(t)
assert.Equal(data.Name, "bar")
assert.NoError(err)
},
},
} }
for _, tc := range tests { for _, tc := range tests {