feature: support cloudprovider, cloudregion and zone schedtag

This commit is contained in:
Zexi Li
2020-10-22 17:16:53 +08:00
parent 1de5147bf2
commit cc32bb39ef
37 changed files with 1204 additions and 330 deletions
@@ -123,5 +123,8 @@ func init() {
modules.Schedtaghosts,
modules.Schedtagstorages,
modules.Schedtagnetworks,
modules.Schedtagcloudproviders,
modules.Schedtagcloudregions,
modules.Schedtagzones,
).register()
}
+1 -1
View File
@@ -76,7 +76,7 @@ func init() {
Strategy string `help:"Policy" choices:"require|exclude|prefer|avoid"`
Desc string `help:"Description"`
Scope string `help:"Resource scope" choices:"system|domain|project"`
Type string `help:"Resource type" choices:"hosts|storages|networks"`
Type string `help:"Resource type" choices:"hosts|storages|networks|cloudproviders|cloudregions|zones"`
}
R(&SchedtagCreateOptions{}, "schedtag-create", "Create a schedule tag", func(s *mcclient.ClientSession, args *SchedtagCreateOptions) error {
params := jsonutils.NewDict()
+4 -3
View File
@@ -23,9 +23,10 @@ import (
type SchedtagConfig struct {
apis.Meta
Id string `json:"id"`
Strategy string `json:"strategy"`
Weight int `json:"weight"`
Id string `json:"id"`
Strategy string `json:"strategy"`
Weight int `json:"weight"`
ResourceType string `json:"resource_type"`
}
type NetworkConfig struct {
+27
View File
@@ -0,0 +1,27 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package compute
type CloudproviderschedtagDetails struct {
SchedtagJointResourceDetails
// cloudprovider name
Cloudprovider string `json:"cloudprovider"`
}
type CloudproviderschedtagListInput struct {
SchedtagJointsListInput
// TODO: add cloudprovider base filter list input
}
+26
View File
@@ -0,0 +1,26 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package compute
type CloudregionschedtagDetails struct {
SchedtagJointResourceDetails
Cloudregion string `json:"cloudregion"`
}
type CloudregionschedtagListInput struct {
SchedtagJointsListInput
RegionalFilterListInput
}
+26
View File
@@ -0,0 +1,26 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package compute
type ZoneschedtagDetails struct {
SchedtagJointResourceDetails
Zone string `json:"zone"`
}
type ZoneschedtagListInput struct {
SchedtagJointsListInput
ZonalFilterListInput
}
+2
View File
@@ -42,6 +42,8 @@ func (d SBaseGuestScheduleDriver) DoScheduleMemoryFilter() bool { return true }
func (d SBaseGuestScheduleDriver) DoScheduleStorageFilter() bool { return true }
func (d SBaseGuestScheduleDriver) DoScheduleCloudproviderTagFilter() bool { return false }
type SBaseGuestDriver struct {
SBaseGuestScheduleDriver
}
@@ -54,6 +54,8 @@ func (d SManagedVirtualizedGuestDriver) DoScheduleMemoryFilter() bool { return f
func (d SManagedVirtualizedGuestDriver) DoScheduleStorageFilter() bool { return false }
func (d SManagedVirtualizedGuestDriver) DoScheduleCloudproviderTagFilter() bool { return true }
func (self *SManagedVirtualizedGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost, params *jsonutils.JSONDict) (jsonutils.JSONObject, error) {
config := cloudprovider.SManagedVMCreateConfig{}
config.Name = guest.Name
@@ -0,0 +1,21 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package models
type SCloudproviderResourceBase struct {
CloudproviderId string `width:"36" charset:"ascii" nullable:"true" list:"user" index:"true" create:"optional"`
}
type SCloudproviderResourceBaseManager struct{}
+20
View File
@@ -1678,3 +1678,23 @@ func (self *SCloudprovider) SyncProject(ctx context.Context, userCred mcclient.T
}
return account.SyncProject(ctx, userCred, id)
}
func (self *SCloudprovider) GetSchedtags() []SSchedtag {
return GetSchedtags(CloudproviderschedtagManager, self.Id)
}
func (self *SCloudprovider) GetDynamicConditionInput() *jsonutils.JSONDict {
return jsonutils.Marshal(self).(*jsonutils.JSONDict)
}
func (self *SCloudprovider) AllowPerformSetSchedtag(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return AllowPerformSetResourceSchedtag(self, ctx, userCred, query, data)
}
func (self *SCloudprovider) PerformSetSchedtag(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
return PerformSetResourceSchedtag(self, ctx, userCred, query, data)
}
func (self *SCloudprovider) GetSchedtagJointManager() ISchedtagJointManager {
return CloudproviderschedtagManager
}
@@ -0,0 +1,104 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package models
import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
)
var (
CloudproviderschedtagManager *SCloudproviderschedtagManager
_ ISchedtagJointModel = new(SCloudproviderschedtag)
)
func init() {
db.InitManager(func() {
CloudproviderschedtagManager = &SCloudproviderschedtagManager{
SSchedtagJointsManager: NewSchedtagJointsManager(
SCloudproviderschedtag{},
"schedtag_cloudproviders_tbl",
"schedtagcloudprovider",
"schedtagcloudproviders",
CloudproviderManager,
),
}
CloudproviderschedtagManager.SetVirtualObject(CloudproviderschedtagManager)
})
}
type SCloudproviderschedtagManager struct {
*SSchedtagJointsManager
SCloudproviderResourceBaseManager
}
type SCloudproviderschedtag struct {
SSchedtagJointsBase
SCloudproviderResourceBase
}
func (m *SCloudproviderschedtagManager) GetMasterFieldName() string {
return "cloudprovider_id"
}
func (obj *SCloudproviderschedtag) GetResourceId() string {
return obj.CloudproviderId
}
func (obj *SCloudproviderschedtag) GetExtraDetails(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
isList bool,
) (api.CloudproviderschedtagDetails, error) {
return api.CloudproviderschedtagDetails{}, nil
}
func (obj *SCloudproviderschedtag) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return obj.SSchedtagJointsBase.delete(obj, ctx, userCred)
}
func (obj *SCloudproviderschedtag) Detach(ctx context.Context, userCred mcclient.TokenCredential) error {
return obj.SSchedtagJointsBase.detach(obj, ctx, userCred)
}
func (m *SCloudproviderschedtagManager) ListItemFilter(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.CloudproviderschedtagListInput,
) (*sqlchemy.SQuery, error) {
var err error
q, err = m.SSchedtagJointsManager.ListItemFilter(ctx, q, userCred, query.SchedtagJointsListInput)
if err != nil {
return nil, errors.Wrap(err, "SSchedtagJointsManager.ListItemFilter")
}
return q, nil
}
func (obj *SCloudproviderschedtag) GetDetails(base api.SchedtagJointResourceDetails, resourceName string, isList bool) interface{} {
out := api.CloudproviderschedtagDetails{
SchedtagJointResourceDetails: base,
}
out.Cloudprovider = resourceName
return out
}
+33
View File
@@ -937,3 +937,36 @@ func (manager *SCloudregionManager) FetchDefaultRegion() *SCloudregion {
func (self *SCloudregion) GetCloudEnv() string {
return cloudprovider.GetProviderCloudEnv(self.Provider)
}
func (self *SCloudregion) GetSchedtags() []SSchedtag {
return GetSchedtags(CloudregionschedtagManager, self.Id)
}
func (self *SCloudregion) GetDynamicConditionInput() *jsonutils.JSONDict {
return jsonutils.Marshal(self).(*jsonutils.JSONDict)
}
func (self *SCloudregion) AllowPerformSetSchedtag(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return AllowPerformSetResourceSchedtag(self, ctx, userCred, query, data)
}
func (self *SCloudregion) PerformSetSchedtag(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
return PerformSetResourceSchedtag(self, ctx, userCred, query, data)
}
func (self *SCloudregion) GetSchedtagJointManager() ISchedtagJointManager {
return CloudregionschedtagManager
}
func (self *SCloudregion) ClearSchedDescCache() error {
zones, err := self.GetZones()
if err != nil {
return errors.Wrap(err, "get zones")
}
for i := range zones {
if err := zones[i].ClearSchedDescCache(); err != nil {
return errors.Wrapf(err, "clean zone %s sched cache", zones[i].GetName())
}
}
return nil
}
@@ -0,0 +1,98 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package models
import (
"context"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
)
var (
CloudregionschedtagManager *SCloudregionschedtagManager
_ ISchedtagJointModel = new(SCloudregionschedtag)
)
func init() {
db.InitManager(func() {
CloudregionschedtagManager = &SCloudregionschedtagManager{
SSchedtagJointsManager: NewSchedtagJointsManager(
SCloudregionschedtag{},
"schedtag_cloudregions_tbl",
"schedtagcloudregion",
"schedtagcloudregions",
CloudregionManager,
),
}
CloudregionschedtagManager.SetVirtualObject(CloudregionschedtagManager)
})
}
type SCloudregionschedtagManager struct {
*SSchedtagJointsManager
resourceBaseManager SCloudregionResourceBaseManager
}
type SCloudregionschedtag struct {
SSchedtagJointsBase
SCloudregionResourceBase
}
func (m *SCloudregionschedtagManager) GetMasterFieldName() string {
return "cloudregion_id"
}
func (obj *SCloudregionschedtag) GetResourceId() string {
return obj.CloudregionId
}
func (obj *SCloudregionschedtag) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return obj.SSchedtagJointsBase.delete(obj, ctx, userCred)
}
func (obj *SCloudregionschedtag) Detach(ctx context.Context, userCred mcclient.TokenCredential) error {
return obj.SSchedtagJointsBase.detach(obj, ctx, userCred)
}
func (m *SCloudregionschedtagManager) ListItemFilter(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.CloudregionschedtagListInput,
) (*sqlchemy.SQuery, error) {
var err error
q, err = m.SSchedtagJointsManager.ListItemFilter(ctx, q, userCred, query.SchedtagJointsListInput)
if err != nil {
return nil, errors.Wrap(err, "SSchedtagJointsManager.ListItemFilter")
}
q, err = m.resourceBaseManager.ListItemFilter(ctx, q, userCred, query.RegionalFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemFilter")
}
return q, nil
}
func (obj *SCloudregionschedtag) GetDetails(base api.SchedtagJointResourceDetails, resourceName string, isList bool) interface{} {
out := api.CloudregionschedtagDetails{
SchedtagJointResourceDetails: base,
}
out.Cloudregion = resourceName
return out
}
+1
View File
@@ -35,6 +35,7 @@ type IGuestScheduleDriver interface {
DoScheduleCPUFilter() bool
DoScheduleMemoryFilter() bool
DoScheduleStorageFilter() bool
DoScheduleCloudproviderTagFilter() bool
}
type IGuestDriver interface {
+2 -11
View File
@@ -115,20 +115,11 @@ func ValidateScheduleCreateData(ctx context.Context, userCred mcclient.TokenCred
region := zone.GetRegion()
input.PreferRegion = region.Id
} else {
schedtags := make(map[string]string)
for _, tag := range input.Schedtags {
schedtags[tag.Id] = tag.Strategy
}
if len(schedtags) > 0 {
schedtags, err = SchedtagManager.ValidateSchedtags(userCred, schedtags)
if len(input.Schedtags) > 0 {
input.Schedtags, err = SchedtagManager.ValidateSchedtags(userCred, input.Schedtags)
if err != nil {
return nil, httperrors.NewInputParameterError("invalid aggregate_strategy: %s", err)
}
tags := make([]*api.SchedtagConfig, 0)
for name, strategy := range schedtags {
tags = append(tags, &api.SchedtagConfig{Id: name, Strategy: strategy})
}
input.Schedtags = tags
}
if input.PreferWire != "" {
+20 -41
View File
@@ -18,22 +18,18 @@ import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
type SHostschedtagManager struct {
*SSchedtagJointsManager
SHostResourceBaseManager
}
var HostschedtagManager *SHostschedtagManager
var (
HostschedtagManager *SHostschedtagManager
_ ISchedtagJointModel = new(SHostschedtag)
)
func init() {
db.InitManager(func() {
@@ -50,6 +46,11 @@ func init() {
})
}
type SHostschedtagManager struct {
*SSchedtagJointsManager
resourceBaseManager SHostResourceBaseManager
}
type SHostschedtag struct {
SSchedtagJointsBase
@@ -69,38 +70,12 @@ func (self *SHostschedtag) GetExtraDetails(
return api.HostschedtagDetails{}, nil
}
func (manager *SHostschedtagManager) FetchCustomizeColumns(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
objs []interface{},
fields stringutils2.SSortedStrings,
isList bool,
) []api.HostschedtagDetails {
rows := make([]api.HostschedtagDetails, len(objs))
schedRows := manager.SSchedtagJointsManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
hostIds := make([]string, len(rows))
for i := range rows {
rows[i] = api.HostschedtagDetails{
SchedtagJointResourceDetails: schedRows[i],
}
hostIds[i] = objs[i].(*SHostschedtag).HostId
func (self *SHostschedtag) GetDetails(base api.SchedtagJointResourceDetails, resourceName string, isList bool) interface{} {
out := api.HostschedtagDetails{
SchedtagJointResourceDetails: base,
}
hostIdMaps, err := db.FetchIdNameMap2(HostManager, hostIds)
if err != nil {
log.Errorf("FetchIdNameMap2 hostIds fail %s", err)
return rows
}
for i := range rows {
if name, ok := hostIdMaps[hostIds[i]]; ok {
rows[i].Host = name
}
}
return rows
out.Host = resourceName
return out
}
func (self *SHostschedtag) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
@@ -111,6 +86,10 @@ func (self *SHostschedtag) Detach(ctx context.Context, userCred mcclient.TokenCr
return self.SSchedtagJointsBase.detach(self, ctx, userCred)
}
func (self *SHostschedtag) GetResourceId() string {
return self.HostId
}
func (manager *SHostschedtagManager) ListItemFilter(
ctx context.Context,
q *sqlchemy.SQuery,
@@ -123,7 +102,7 @@ func (manager *SHostschedtagManager) ListItemFilter(
if err != nil {
return nil, errors.Wrap(err, "SSchedtagJointsManager.ListItemFilter")
}
q, err = manager.SHostResourceBaseManager.ListItemFilter(ctx, q, userCred, query.HostFilterListInput)
q, err = manager.resourceBaseManager.ListItemFilter(ctx, q, userCred, query.HostFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SHostResourceBaseManager.ListItemFilter")
}
@@ -143,7 +122,7 @@ func (manager *SHostschedtagManager) OrderByExtraFields(
if err != nil {
return nil, errors.Wrap(err, "SSchedtagJointsManager.OrderByExtraFields")
}
q, err = manager.SHostResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.HostFilterListInput)
q, err = manager.resourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.HostFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SHostResourceBaseManager.OrderByExtraFields")
}
+20 -41
View File
@@ -18,22 +18,18 @@ import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
type SNetworkschedtagManager struct {
*SSchedtagJointsManager
SNetworkResourceBaseManager
}
var NetworkschedtagManager *SNetworkschedtagManager
var (
NetworkschedtagManager *SNetworkschedtagManager
_ ISchedtagJointModel = new(SNetworkschedtag)
)
func init() {
db.InitManager(func() {
@@ -50,6 +46,11 @@ func init() {
})
}
type SNetworkschedtagManager struct {
*SSchedtagJointsManager
resourceBaseManager SNetworkResourceBaseManager
}
type SNetworkschedtag struct {
SSchedtagJointsBase
@@ -60,6 +61,10 @@ func (manager *SNetworkschedtagManager) GetMasterFieldName() string {
return "network_id"
}
func (s *SNetworkschedtag) GetResourceId() string {
return s.NetworkId
}
func (s *SNetworkschedtag) GetExtraDetails(
ctx context.Context,
userCred mcclient.TokenCredential,
@@ -69,38 +74,12 @@ func (s *SNetworkschedtag) GetExtraDetails(
return api.NetworkschedtagDetails{}, nil
}
func (manager *SNetworkschedtagManager) FetchCustomizeColumns(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
objs []interface{},
fields stringutils2.SSortedStrings,
isList bool,
) []api.NetworkschedtagDetails {
rows := make([]api.NetworkschedtagDetails, len(objs))
schedRows := manager.SSchedtagJointsManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
netIds := make([]string, len(rows))
for i := range rows {
rows[i] = api.NetworkschedtagDetails{
SchedtagJointResourceDetails: schedRows[i],
}
netIds[i] = objs[i].(*SNetworkschedtag).NetworkId
func (s *SNetworkschedtag) GetDetails(base api.SchedtagJointResourceDetails, resourceName string, isList bool) interface{} {
out := api.NetworkschedtagDetails{
SchedtagJointResourceDetails: base,
}
netIdMaps, err := db.FetchIdNameMap2(NetworkManager, netIds)
if err != nil {
log.Errorf("FetchIdNameMap2 netIds fail %s", err)
return rows
}
for i := range rows {
if name, ok := netIdMaps[netIds[i]]; ok {
rows[i].Network = name
}
}
return rows
out.Network = resourceName
return out
}
func (s *SNetworkschedtag) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
@@ -123,7 +102,7 @@ func (manager *SNetworkschedtagManager) ListItemFilter(
if err != nil {
return nil, errors.Wrap(err, "SSchedtagJointsManager.ListItemFilter")
}
q, err = manager.SNetworkResourceBaseManager.ListItemFilter(ctx, q, userCred, query.NetworkFilterListInput)
q, err = manager.resourceBaseManager.ListItemFilter(ctx, q, userCred, query.NetworkFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SNetworkResourceBaseManager.ListItemFilter")
}
@@ -143,7 +122,7 @@ func (manager *SNetworkschedtagManager) OrderByExtraFields(
if err != nil {
return nil, errors.Wrap(err, "SSchedtagJointsManager.OrderByExtraFields")
}
q, err = manager.SNetworkResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.NetworkFilterListInput)
q, err = manager.resourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.NetworkFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SNetworkResourceBaseManager.OrderByExtraFields")
}
+21 -9
View File
@@ -238,10 +238,10 @@ func applyResourceSchedPolicy(
input *jsonutils.JSONDict,
setTags func([]*api.SchedtagConfig),
) {
schedtags := make(map[string]string)
schedtags := make(map[string]*api.SchedtagConfig)
for _, tag := range oldTags {
schedtags[tag.Id] = tag.Strategy
schedtags[tag.Id] = tag
}
log.Infof("original schedtag %#v", schedtags)
@@ -250,17 +250,29 @@ func applyResourceSchedPolicy(
policy := policies[i]
st := policy.getSchedtag()
if matchResourceSchedPolicy(policy, input) {
schedtags[st.Name] = policy.Strategy
if conf, idOk := schedtags[st.GetId()]; idOk {
conf.Id = st.GetId()
conf.Strategy = policy.Strategy
schedtags[st.GetId()] = conf
} else if conf, nameOk := schedtags[st.GetName()]; nameOk {
conf.Id = st.GetId()
conf.Strategy = policy.Strategy
schedtags[st.GetId()] = conf
delete(schedtags, st.GetName())
} else {
schedtags[st.GetId()] = &api.SchedtagConfig{
Id: st.GetId(),
Strategy: policy.Strategy,
ResourceType: st.ResourceType,
}
}
}
}
log.Infof("updated sched tag %s", schedtags)
log.Infof("updated sched tag %#v", schedtags)
newSchedtags := make([]*api.SchedtagConfig, 0)
for name, strategy := range schedtags {
newSchedtags = append(newSchedtags, &api.SchedtagConfig{
Id: name,
Strategy: strategy,
})
for _, tag := range schedtags {
newSchedtags = append(newSchedtags, tag)
}
setTags(newSchedtags)
}
+23 -10
View File
@@ -21,7 +21,6 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/reflectutils"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
@@ -158,21 +157,20 @@ func (manager *SSchedtagJointsManager) FetchCustomizeColumns(
objs []interface{},
fields stringutils2.SSortedStrings,
isList bool,
) []api.SchedtagJointResourceDetails {
rows := make([]api.SchedtagJointResourceDetails, len(objs))
) []interface{} {
rows := make([]interface{}, len(objs))
jointRows := manager.SJointResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
tagIds := make([]string, len(rows))
resIds := make([]string, len(rows))
for i := range rows {
rows[i] = api.SchedtagJointResourceDetails{
JointResourceBaseDetails: jointRows[i],
}
var base *SSchedtagJointsBase
reflectutils.FindAnonymouStructPointer(objs[i], &base)
if base != nil && len(base.SchedtagId) > 0 {
tagIds[i] = base.SchedtagId
}
obj := objs[i].(ISchedtagJointModel)
tagIds[i] = obj.GetSchedtagId()
resIds[i] = obj.GetResourceId()
}
tags := make(map[string]SSchedtag)
@@ -184,11 +182,26 @@ func (manager *SSchedtagJointsManager) FetchCustomizeColumns(
for i := range rows {
if schedtag, ok := tags[tagIds[i]]; ok {
rows[i].Schedtag = schedtag.Name
rows[i].ResourceType = schedtag.ResourceType
out := rows[i].(api.SchedtagJointResourceDetails)
out.Schedtag = schedtag.Name
out.ResourceType = schedtag.ResourceType
rows[i] = out
}
}
resIdMaps, err := db.FetchIdNameMap2(manager.GetMasterManager(), resIds)
if err != nil {
log.Errorf("FetchIdNameMap2 %sIds error: %v", manager.GetMasterManager().Keyword(), err)
return rows
}
for idx := range objs {
obj := objs[idx].(ISchedtagJointModel)
baseDetail := rows[idx].(api.SchedtagJointResourceDetails)
out := obj.GetDetails(baseDetail, resIdMaps[resIds[idx]], isList)
rows[idx] = out
}
return rows
}
+22 -22
View File
@@ -57,6 +57,8 @@ type ISchedtagJointManager interface {
type ISchedtagJointModel interface {
db.IJointModel
GetSchedtagId() string
GetResourceId() string
GetDetails(base api.SchedtagJointResourceDetails, resourceName string, isList bool) interface{}
}
type IModelWithSchedtag interface {
@@ -103,9 +105,12 @@ func (manager *SSchedtagManager) InitializeData() error {
})
}
manager.BindJointManagers(map[db.IModelManager]ISchedtagJointManager{
HostManager: HostschedtagManager,
StorageManager: StorageschedtagManager,
NetworkManager: NetworkschedtagManager,
HostManager: HostschedtagManager,
StorageManager: StorageschedtagManager,
NetworkManager: NetworkschedtagManager,
CloudproviderManager: CloudproviderschedtagManager,
ZoneManager: ZoneschedtagManager,
CloudregionManager: CloudregionschedtagManager,
})
return nil
}
@@ -256,23 +261,25 @@ func (self *SSchedtag) AllowDeleteItem(ctx context.Context, userCred mcclient.To
return db.IsAdminAllowDelete(userCred, self)
}
func (manager *SSchedtagManager) ValidateSchedtags(userCred mcclient.TokenCredential, schedtags map[string]string) (map[string]string, error) {
ret := make(map[string]string)
for tag, act := range schedtags {
schedtagObj, err := manager.FetchByIdOrName(nil, tag)
func (manager *SSchedtagManager) ValidateSchedtags(userCred mcclient.TokenCredential, schedtags []*api.SchedtagConfig) ([]*api.SchedtagConfig, error) {
ret := make([]*api.SchedtagConfig, len(schedtags))
for idx, tag := range schedtags {
schedtagObj, err := manager.FetchByIdOrName(userCred, tag.Id)
if err != nil {
if err == sql.ErrNoRows {
return nil, httperrors.NewResourceNotFoundError("Invalid schedtag %s", tag)
return nil, httperrors.NewResourceNotFoundError("Invalid schedtag %s", tag.Id)
} else {
return nil, httperrors.NewGeneralError(err)
}
}
act = strings.ToLower(act)
strategy := strings.ToLower(tag.Strategy)
schedtag := schedtagObj.(*SSchedtag)
if !utils.IsInStringArray(act, STRATEGY_LIST) {
return nil, httperrors.NewInputParameterError("invalid strategy %s", act)
if !utils.IsInStringArray(strategy, STRATEGY_LIST) {
return nil, httperrors.NewInputParameterError("invalid strategy %s", strategy)
}
ret[schedtag.Name] = act
tag.Id = schedtag.GetId()
tag.ResourceType = schedtag.ResourceType
ret[idx] = tag
}
return ret, nil
}
@@ -379,15 +386,6 @@ func (self *SSchedtag) ValidateDeleteCondition(ctx context.Context) error {
return self.SStandaloneResourceBase.ValidateDeleteCondition(ctx)
}
/*
func (self *SSchedtag) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
return userCred.IsSystemAdmin()
}
func (self *SSchedtag) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
return userCred.IsSystemAdmin()
}*/
func (self *SSchedtag) GetObjects(objs interface{}) error {
q := self.GetObjectQuery()
masterMan := self.GetJointManager().GetMasterManager()
@@ -603,7 +601,9 @@ func PerformSetResourceSchedtag(obj IModelWithSchedtag, ctx context.Context, use
}
}
}
obj.ClearSchedDescCache()
if err := obj.ClearSchedDescCache(); err != nil {
log.Errorf("Resource %s/%s ClearSchedDescCache error: %v", obj.Keyword(), obj.GetId(), err)
}
return nil, nil
}
+17 -38
View File
@@ -18,23 +18,24 @@ import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/stringutils2"
)
var (
StorageschedtagManager *SStorageschedtagManager
_ ISchedtagJointModel = new(SStorageschedtag)
)
type SStorageschedtagManager struct {
*SSchedtagJointsManager
SStorageResourceBaseManager
resourceBaseManager SStorageResourceBaseManager
}
var StorageschedtagManager *SStorageschedtagManager
func init() {
db.InitManager(func() {
StorageschedtagManager = &SStorageschedtagManager{
@@ -60,6 +61,10 @@ func (manager *SStorageschedtagManager) GetMasterFieldName() string {
return "storage_id"
}
func (joint *SStorageschedtag) GetResourceId() string {
return joint.StorageId
}
func (joint *SStorageschedtag) GetExtraDetails(
ctx context.Context,
userCred mcclient.TokenCredential,
@@ -69,38 +74,12 @@ func (joint *SStorageschedtag) GetExtraDetails(
return api.StorageschedtagDetails{}, nil
}
func (manager *SStorageschedtagManager) FetchCustomizeColumns(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
objs []interface{},
fields stringutils2.SSortedStrings,
isList bool,
) []api.StorageschedtagDetails {
rows := make([]api.StorageschedtagDetails, len(objs))
schedRows := manager.SSchedtagJointsManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
storageIds := make([]string, len(rows))
for i := range rows {
rows[i] = api.StorageschedtagDetails{
SchedtagJointResourceDetails: schedRows[i],
}
storageIds[i] = objs[i].(*SStorageschedtag).StorageId
func (joint *SStorageschedtag) GetDetails(base api.SchedtagJointResourceDetails, resourceName string, isList bool) interface{} {
out := api.StorageschedtagDetails{
SchedtagJointResourceDetails: base,
}
storageIdMaps, err := db.FetchIdNameMap2(StorageManager, storageIds)
if err != nil {
log.Errorf("FetchIdNameMap2 hostIds fail %s", err)
return rows
}
for i := range rows {
if name, ok := storageIdMaps[storageIds[i]]; ok {
rows[i].Storage = name
}
}
return rows
out.Storage = resourceName
return out
}
func (joint *SStorageschedtag) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
@@ -123,7 +102,7 @@ func (manager *SStorageschedtagManager) ListItemFilter(
if err != nil {
return nil, errors.Wrap(err, "SSchedtagJointsManager.ListItemFilter")
}
q, err = manager.SStorageResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StorageFilterListInput)
q, err = manager.resourceBaseManager.ListItemFilter(ctx, q, userCred, query.StorageFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SStorageResourceBaseManager.ListItemFilter")
}
@@ -143,7 +122,7 @@ func (manager *SStorageschedtagManager) OrderByExtraFields(
if err != nil {
return nil, errors.Wrap(err, "SSchedtagJointsManager.OrderByExtraFields")
}
q, err = manager.SStorageResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StorageFilterListInput)
q, err = manager.resourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StorageFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SStorageResourceBaseManager.OrderByExtraFields")
}
+36
View File
@@ -714,3 +714,39 @@ func (manager *SZoneManager) ValidateCreateData(ctx context.Context, userCred mc
return input.JSON(input), nil
}
func (self *SZone) GetSchedtags() []SSchedtag {
return GetSchedtags(ZoneschedtagManager, self.Id)
}
func (self *SZone) GetDynamicConditionInput() *jsonutils.JSONDict {
return jsonutils.Marshal(self).(*jsonutils.JSONDict)
}
func (self *SZone) AllowPerformSetSchedtag(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return AllowPerformSetResourceSchedtag(self, ctx, userCred, query, data)
}
func (self *SZone) PerformSetSchedtag(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
return PerformSetResourceSchedtag(self, ctx, userCred, query, data)
}
func (self *SZone) GetSchedtagJointManager() ISchedtagJointManager {
return ZoneschedtagManager
}
func (self *SZone) ClearSchedDescCache() error {
hosts := make([]SHost, 0)
q := HostManager.Query().Equals("zone_id", self.Id)
err := db.FetchModelObjects(HostManager, q, &hosts)
if err != nil {
return errors.Wrapf(err, "fetch hosts by zone_id %s", self.Id)
}
for i := range hosts {
err := hosts[i].ClearSchedDescCache()
if err != nil {
return errors.Wrapf(err, "clean host %s sched cache", hosts[i].GetName())
}
}
return nil
}
+108
View File
@@ -0,0 +1,108 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package models
import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/mcclient"
)
var (
ZoneschedtagManager *SZoneschedtagManager
_ ISchedtagJointModel = new(SZoneschedtag)
)
func init() {
db.InitManager(func() {
ZoneschedtagManager = &SZoneschedtagManager{
SSchedtagJointsManager: NewSchedtagJointsManager(
SZoneschedtag{},
"schedtag_zones_tbl",
"schedtagzone",
"schedtagzones",
ZoneManager,
),
}
ZoneschedtagManager.SetVirtualObject(ZoneschedtagManager)
})
}
type SZoneschedtagManager struct {
*SSchedtagJointsManager
resourceBaseManager SZoneResourceBaseManager
}
type SZoneschedtag struct {
SSchedtagJointsBase
SZoneResourceBase
}
func (m *SZoneschedtagManager) GetMasterFieldName() string {
return "zone_id"
}
func (obj *SZoneschedtag) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
return obj.SSchedtagJointsBase.delete(obj, ctx, userCred)
}
func (obj *SZoneschedtag) Detach(ctx context.Context, userCred mcclient.TokenCredential) error {
return obj.SSchedtagJointsBase.detach(obj, ctx, userCred)
}
func (obj *SZoneschedtag) GetResourceId() string {
return obj.ZoneId
}
func (obj *SZoneschedtag) GetExtraDetails(
ctx context.Context,
userCred mcclient.TokenCredential,
query jsonutils.JSONObject,
isList bool,
) (api.ZoneschedtagDetails, error) {
return api.ZoneschedtagDetails{}, nil
}
func (m *SZoneschedtagManager) ListItemFilter(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.ZoneschedtagListInput,
) (*sqlchemy.SQuery, error) {
var err error
q, err = m.SSchedtagJointsManager.ListItemFilter(ctx, q, userCred, query.SchedtagJointsListInput)
if err != nil {
return nil, errors.Wrap(err, "SSchedtagJointsManager.ListItemFilter")
}
q, err = m.resourceBaseManager.ListItemFilter(ctx, q, userCred, query.ZonalFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SZoneResourceBaseManager.ListItemFilter")
}
return q, nil
}
func (obj *SZoneschedtag) GetDetails(base api.SchedtagJointResourceDetails, resourceName string, isList bool) interface{} {
out := api.ZoneschedtagDetails{
SchedtagJointResourceDetails: base,
}
out.Zone = resourceName
return out
}
+3
View File
@@ -209,6 +209,9 @@ func InitHandlers(app *appsrv.Application) {
models.HostschedtagManager,
models.StorageschedtagManager,
models.NetworkschedtagManager,
models.CloudproviderschedtagManager,
models.ZoneschedtagManager,
models.CloudregionschedtagManager,
models.GuestnetworkManager,
models.GuestsecgroupManager,
models.LoadbalancernetworkManager,
+31 -6
View File
@@ -17,9 +17,12 @@ package modules
import "yunion.io/x/onecloud/pkg/mcclient/modulebase"
var (
Schedtaghosts modulebase.JointResourceManager
Schedtagstorages modulebase.JointResourceManager
Schedtagnetworks modulebase.JointResourceManager
Schedtaghosts modulebase.JointResourceManager
Schedtagstorages modulebase.JointResourceManager
Schedtagnetworks modulebase.JointResourceManager
Schedtagcloudproviders modulebase.JointResourceManager
Schedtagcloudregions modulebase.JointResourceManager
Schedtagzones modulebase.JointResourceManager
)
func newSchedtagJointManager(keyword, keywordPlural string, columns, adminColumns []string, slave modulebase.Manager) modulebase.JointResourceManager {
@@ -44,7 +47,29 @@ func init() {
[]string{},
&Networks)
registerCompute(&Schedtaghosts)
registerCompute(&Schedtagstorages)
registerCompute(&Schedtagnetworks)
Schedtagcloudproviders = newSchedtagJointManager("schedtagcloudprovider", "schedtagcloudproviders",
[]string{"Cloudprovider_ID", "Cloudprovider"},
[]string{},
&Cloudproviders)
Schedtagcloudregions = newSchedtagJointManager("schedtagcloudregion", "schedtagcloudregions",
[]string{"Cloudregion_ID", "Cloudregion"},
[]string{},
&Cloudregions)
Schedtagzones = newSchedtagJointManager("schedtagzone", "schedtagzones",
[]string{"Zone_ID", "Zone"},
[]string{},
&Zones)
for _, m := range []modulebase.IBaseManager{
&Schedtaghosts,
&Schedtagstorages,
&Schedtagnetworks,
&Schedtagcloudproviders,
&Schedtagcloudregions,
&Schedtagzones,
} {
registerCompute(m)
}
}
@@ -1,134 +0,0 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package predicates
import (
"yunion.io/x/jsonutils"
computemodels "yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/scheduler/algorithm/plugin"
"yunion.io/x/onecloud/pkg/scheduler/api"
"yunion.io/x/onecloud/pkg/scheduler/core"
"yunion.io/x/onecloud/pkg/scheduler/core/score"
)
// NOTE: Aggregate Description
// require: Must be scheduled to the specified host
// prefer: Priority to the specified host
// avoid: Try to avoid scheduling to the specified host
// exclude: Do not allow scheduling on the specified host
// AggregatePredicate is designed to quickly filter unavailable
// hosts and improve scheduling efficiency by tabbing whether
// the host is available.
type AggregatePredicate struct {
BasePredicate
plugin.BasePlugin
SchedtagPredicate *SchedtagPredicate
}
func (p *AggregatePredicate) Name() string {
return "host_aggregate"
}
func (p *AggregatePredicate) Clone() core.FitPredicate {
return &AggregatePredicate{}
}
func (p *AggregatePredicate) PreExecute(u *core.Unit, cs []core.Candidater) (bool, error) {
data := u.SchedData()
allAggs, err := GetAllSchedtags(computemodels.HostManager.KeywordPlural())
if err != nil {
return false, err
}
p.SchedtagPredicate = NewSchedtagPredicate(data.Schedtags, allAggs)
u.AppendSelectPlugin(p)
return true, nil
}
func (p *AggregatePredicate) Execute(u *core.Unit, c core.Candidater) (bool, []core.PredicateFailureReason, error) {
h := NewPredicateHelper(p, u, c)
if !u.ShouldExecuteSchedtagFilter(c.Getter().Id()) {
return true, nil, nil
}
if errMsg := p.exec(h); len(errMsg) > 0 {
h.Exclude(errMsg)
}
return h.GetResult()
}
type schedtagCandidateW struct {
core.Candidater
schedData *api.SchedInfo
}
func (w schedtagCandidateW) GetDynamicSchedDesc() *jsonutils.JSONDict {
ret := jsonutils.NewDict()
hostSchedDesc := w.GetSchedDesc()
srvSchedDesc := w.schedData.ToConditionInput()
ret.Add(hostSchedDesc, computemodels.HostManager.Keyword())
ret.Add(srvSchedDesc, computemodels.GuestManager.Keyword())
return ret
}
func (w schedtagCandidateW) GetSchedtags() []computemodels.SSchedtag {
return w.Getter().HostSchedtags()
}
func (w schedtagCandidateW) ResourceType() string {
return computemodels.HostManager.KeywordPlural()
}
func (p *AggregatePredicate) exec(h *PredicateHelper) string {
if err := p.SchedtagPredicate.Check(
schedtagCandidateW{
Candidater: h.Candidate,
schedData: h.Unit.SchedData(),
},
); err != nil {
return err.Error()
}
return ""
}
func SetCandidateScoreBySchedtag(u *core.Unit, c core.Candidater, aggCountMap map[string]int, prefer bool) {
stepScore := core.PriorityStep
doSet := u.SetPreferScore
if !prefer {
doSet = u.SetAvoidScore
}
for n, count := range aggCountMap {
doSet(c.IndexKey(), score.NewScore(score.TScore(count*stepScore), n))
}
}
func (p *AggregatePredicate) OnPriorityEnd(u *core.Unit, c core.Candidater) {
hostAggs := c.Getter().HostSchedtags()
avoidCountMap := GetSchedtagCount(p.SchedtagPredicate.GetAvoidTags(), hostAggs, api.AggregateStrategyAvoid)
preferCountMap := GetSchedtagCount(p.SchedtagPredicate.GetPreferTags(), hostAggs, api.AggregateStrategyPrefer)
setScore := SetCandidateScoreBySchedtag
setScore(u, c, preferCountMap, true)
setScore(u, c, avoidCountMap, false)
}
@@ -0,0 +1,91 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package predicates
import (
"yunion.io/x/jsonutils"
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
computemodels "yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/scheduler/api"
"yunion.io/x/onecloud/pkg/scheduler/core"
)
type CloudproviderSchedtagPredicate struct {
*ServerBaseSchedtagPredicate
}
func NewCloudproviderSchedtagPredicate() core.FitPredicate {
p := new(CloudproviderSchedtagPredicate)
p.ServerBaseSchedtagPredicate = NewServerBaseSchedtagPredicate(p)
return p
}
func (p *CloudproviderSchedtagPredicate) Name() string {
return "cloudprovider_schedtag"
}
func (p *CloudproviderSchedtagPredicate) Clone() core.FitPredicate {
return NewCloudproviderSchedtagPredicate()
}
func (p *CloudproviderSchedtagPredicate) PreExecute(u *core.Unit, cs []core.Candidater) (bool, error) {
if !u.GetHypervisorDriver().DoScheduleCloudproviderTagFilter() {
return false, nil
}
return p.ServerBaseSchedtagPredicate.PreExecute(u, cs)
}
type cloudproviderSchedtagW struct {
schedData *api.SchedInfo
cloudprovider string
schedtags []*computeapi.SchedtagConfig
}
func (p *CloudproviderSchedtagPredicate) GetInputs(u *core.Unit) []ISchedtagCustomer {
data := u.SchedData()
tags := data.Schedtags
return []ISchedtagCustomer{
&cloudproviderSchedtagW{
schedData: data,
cloudprovider: data.PreferManager,
schedtags: GetInputSchedtagByType(tags, computemodels.CloudproviderManager.KeywordPlural()),
}}
}
func (w *cloudproviderSchedtagW) Keyword() string {
return "server"
}
func (w *cloudproviderSchedtagW) ResourceKeyword() string {
return "cloudprovider"
}
func (w *cloudproviderSchedtagW) IsSpecifyResource() bool {
return w.cloudprovider != ""
}
func (w *cloudproviderSchedtagW) GetSchedtags() []*computeapi.SchedtagConfig {
return w.schedtags
}
func (w *cloudproviderSchedtagW) GetDynamicConditionInput() *jsonutils.JSONDict {
return w.schedData.ToConditionInput()
}
func (p *CloudproviderSchedtagPredicate) GetCandidateResource(c core.Candidater) ISchedtagCandidateResource {
provider := c.Getter().Cloudprovider()
return provider
}
@@ -0,0 +1,91 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package predicates
import (
"yunion.io/x/jsonutils"
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
computemodels "yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/scheduler/api"
"yunion.io/x/onecloud/pkg/scheduler/core"
)
type CloudregionSchedtagPredicate struct {
*ServerBaseSchedtagPredicate
}
func NewCloudregionSchedtagPredicate() core.FitPredicate {
p := new(CloudregionSchedtagPredicate)
p.ServerBaseSchedtagPredicate = NewServerBaseSchedtagPredicate(p)
return p
}
func (p *CloudregionSchedtagPredicate) Name() string {
return "cloudregion_schedtag"
}
func (p *CloudregionSchedtagPredicate) Clone() core.FitPredicate {
return NewCloudregionSchedtagPredicate()
}
type cloudregionSchedtagW struct {
schedData *api.SchedInfo
cloudregion string
schedtags []*computeapi.SchedtagConfig
}
func (p *CloudregionSchedtagPredicate) GetInputs(u *core.Unit) []ISchedtagCustomer {
data := u.SchedData()
tags := data.Schedtags
return []ISchedtagCustomer{
&cloudregionSchedtagW{
schedData: data,
cloudregion: data.PreferRegion,
schedtags: GetInputSchedtagByType(tags, computemodels.CloudregionManager.KeywordPlural()),
}}
}
func (w *cloudregionSchedtagW) Keyword() string {
return "server"
}
func (w *cloudregionSchedtagW) ResourceKeyword() string {
return "cloudregion"
}
func (w *cloudregionSchedtagW) GetDynamicConditionInput() *jsonutils.JSONDict {
return w.schedData.ToConditionInput()
}
func (w *cloudregionSchedtagW) IsSpecifyResource() bool {
return w.cloudregion != ""
}
func (w *cloudregionSchedtagW) GetSchedtags() []*computeapi.SchedtagConfig {
return w.schedtags
}
func (p *CloudregionSchedtagPredicate) GetCandidateResource(c core.Candidater) ISchedtagCandidateResource {
zone := c.Getter().Zone()
if zone == nil {
return nil
}
region := zone.GetRegion()
if region == nil {
return nil
}
return region
}
@@ -17,6 +17,7 @@ package predicates
import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/utils"
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
@@ -66,6 +67,10 @@ func (d diskW) GetSchedtags() []*computeapi.SchedtagConfig {
return d.DiskConfig.Schedtags
}
func (d diskW) GetDynamicConditionInput() *jsonutils.JSONDict {
return d.JSON(d)
}
func (p *DiskSchedtagPredicate) GetInputs(u *core.Unit) []ISchedtagCustomer {
ret := make([]ISchedtagCustomer, 0)
for _, disk := range u.SchedData().Disks {
@@ -0,0 +1,113 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package predicates
import (
"yunion.io/x/jsonutils"
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
computemodels "yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/scheduler/api"
"yunion.io/x/onecloud/pkg/scheduler/core"
)
type HostSchedtagPredicate struct {
*ServerBaseSchedtagPredicate
}
func NewHostSchedtagPredicate() core.FitPredicate {
p := new(HostSchedtagPredicate)
p.ServerBaseSchedtagPredicate = NewServerBaseSchedtagPredicate(p)
return p
}
func (p *HostSchedtagPredicate) Name() string {
return "host_schedtag"
}
func (p *HostSchedtagPredicate) Clone() core.FitPredicate {
return NewHostSchedtagPredicate()
}
type hostSchedtagInputW struct {
schedData *api.SchedInfo
host string
backupHost string
schedtags []*computeapi.SchedtagConfig
}
func (p *HostSchedtagPredicate) GetInputs(u *core.Unit) []ISchedtagCustomer {
data := u.SchedData()
tags := data.Schedtags
return []ISchedtagCustomer{
&hostSchedtagInputW{
schedData: data,
host: data.PreferHost,
backupHost: data.PreferBackupHost,
schedtags: GetInputSchedtagByType(tags, "", computemodels.HostManager.KeywordPlural()),
}}
}
func (w *hostSchedtagInputW) Keyword() string {
return "server"
}
func (w *hostSchedtagInputW) ResourceKeyword() string {
return "host"
}
func (w *hostSchedtagInputW) GetDynamicConditionInput() *jsonutils.JSONDict {
return w.schedData.ToConditionInput()
}
func (w *hostSchedtagInputW) IsSpecifyResource() bool {
return w.host != "" || w.backupHost != ""
}
func (w *hostSchedtagInputW) GetSchedtags() []*computeapi.SchedtagConfig {
return w.schedtags
}
type hostSchedtagResW struct {
core.Candidater
}
func (r hostSchedtagResW) GetName() string {
return r.Candidater.Getter().Name()
}
func (r hostSchedtagResW) GetId() string {
return r.Candidater.Getter().Id()
}
func (r hostSchedtagResW) Keyword() string {
return r.Candidater.Getter().Host().Keyword()
}
func (r hostSchedtagResW) GetSchedtags() []computemodels.SSchedtag {
return r.Candidater.Getter().HostSchedtags()
}
func (r hostSchedtagResW) GetSchedtagJointManager() computemodels.ISchedtagJointManager {
return r.Candidater.Getter().Host().GetSchedtagJointManager()
}
func (r hostSchedtagResW) GetDynamicConditionInput() *jsonutils.JSONDict {
return r.GetSchedDesc()
}
func (p *HostSchedtagPredicate) GetCandidateResource(c core.Candidater) ISchedtagCandidateResource {
return hostSchedtagResW{c}
}
@@ -17,6 +17,7 @@ package predicates
import (
"sort"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
@@ -63,6 +64,10 @@ func (n netW) GetSchedtags() []*computeapi.SchedtagConfig {
return n.NetworkConfig.Schedtags
}
func (n netW) GetDynamicConditionInput() *jsonutils.JSONDict {
return n.NetworkConfig.JSON(n.NetworkConfig)
}
func (p *NetworkSchedtagPredicate) GetInputs(u *core.Unit) []ISchedtagCustomer {
ret := make([]ISchedtagCustomer, 0)
for _, net := range u.SchedData().Networks {
@@ -41,6 +41,7 @@ import (
"yunion.io/x/onecloud/pkg/scheduler/algorithm/plugin"
"yunion.io/x/onecloud/pkg/scheduler/api"
"yunion.io/x/onecloud/pkg/scheduler/core"
"yunion.io/x/onecloud/pkg/scheduler/core/score"
)
// BasePredicate is a default struct for all the predicates that will
@@ -264,6 +265,11 @@ type ISchedtagPredicateInstance interface {
GetCandidateResourceSortScore(candidate ISchedtagCandidateResource) int64
}
// Schedtag Description
// require: Must be scheduled to the specified tag resource
// prefer: Priority to the specified resource
// avoid: Try to avoid scheduling to the specified resource
// exclude: Do not allow scheduling on the specified resource
type BaseSchedtagPredicate struct {
BasePredicate
plugin.BasePlugin
@@ -292,7 +298,8 @@ func (p *PredicatedSchedtagResource) hasAvoidTags() bool {
}
type ISchedtagCustomer interface {
JSON(interface{}) *jsonutils.JSONDict
// JSON(interface{}) *jsonutils.JSONDict
GetDynamicConditionInput() *jsonutils.JSONDict
Keyword() string
IsSpecifyResource() bool
GetSchedtags() []*computeapi.SchedtagConfig
@@ -323,7 +330,7 @@ func (w SchedtagResourceW) GetSchedtags() []models.SSchedtag {
func (w SchedtagResourceW) GetDynamicSchedDesc() *jsonutils.JSONDict {
ret := jsonutils.NewDict()
resSchedDesc := w.candidater.GetDynamicConditionInput()
inputSchedDesc := w.input.JSON(w.input)
inputSchedDesc := w.input.GetDynamicConditionInput()
ret.Add(resSchedDesc, w.candidater.Keyword())
ret.Add(inputSchedDesc, w.input.Keyword())
return ret
@@ -339,11 +346,10 @@ func (p *BaseSchedtagPredicate) check(input ISchedtagCustomer, candidate ISchedt
return nil, err
}
tagPredicate := NewSchedtagPredicate(input.GetSchedtags(), allTags)
shouldExec := u.ShouldExecuteSchedtagFilter(c.Getter().Id())
res := &PredicatedSchedtagResource{
ISchedtagCandidateResource: candidate,
}
if shouldExec && !input.IsSpecifyResource() {
if !input.IsSpecifyResource() {
if err := tagPredicate.Check(
SchedtagResourceW{
candidater: candidate,
@@ -421,7 +427,7 @@ func (p *BaseSchedtagPredicate) Execute(
}
if len(matchedRes) == 0 {
errs = append(errs, &FailReason{
Reason: fmt.Sprintf("Not found matched %s, candidate: %s, %s: %s", input.ResourceKeyword(), c.Getter().Name(), input.Keyword(), input.JSON(input).String()),
Reason: fmt.Sprintf("Not found matched %s, candidate: %s, %s: %s", input.ResourceKeyword(), c.Getter().Name(), input.Keyword(), input.GetDynamicConditionInput()),
Type: fmt.Sprintf("%s_match", input.ResourceKeyword()),
})
}
@@ -454,6 +460,17 @@ func (p *BaseSchedtagPredicate) Execute(
return h.GetResult()
}
func SetCandidateScoreBySchedtag(u *core.Unit, c core.Candidater, aggCountMap map[string]int, prefer bool) {
stepScore := core.PriorityStep
doSet := u.SetPreferScore
if !prefer {
doSet = u.SetAvoidScore
}
for n, count := range aggCountMap {
doSet(c.IndexKey(), score.NewScore(score.TScore(count*stepScore), n))
}
}
func (p *BaseSchedtagPredicate) OnPriorityEnd(sp ISchedtagPredicateInstance, u *core.Unit, c core.Candidater) {
resTags := []models.SSchedtag{}
for _, res := range sp.GetResources(c) {
@@ -554,3 +571,71 @@ func (p *BaseSchedtagPredicate) selectResource(
}
return nil
}
type iServerBaseSchedtagPredicate interface {
ISchedtagPredicateInstance
GetCandidateResource(core.Candidater) ISchedtagCandidateResource
}
type ServerBaseSchedtagPredicate struct {
*BaseSchedtagPredicate
filter iServerBaseSchedtagPredicate
}
func NewServerBaseSchedtagPredicate(filter iServerBaseSchedtagPredicate) *ServerBaseSchedtagPredicate {
return &ServerBaseSchedtagPredicate{
BaseSchedtagPredicate: NewBaseSchedtagPredicate(),
filter: filter,
}
}
func (p *ServerBaseSchedtagPredicate) PreExecute(u *core.Unit, cs []core.Candidater) (bool, error) {
return p.BaseSchedtagPredicate.PreExecute(p.filter, u, cs)
}
func (p *ServerBaseSchedtagPredicate) Execute(u *core.Unit, c core.Candidater) (bool, []core.PredicateFailureReason, error) {
return p.BaseSchedtagPredicate.Execute(p.filter, u, c)
}
func (p *ServerBaseSchedtagPredicate) GetResources(c core.Candidater) []ISchedtagCandidateResource {
res := p.filter.GetCandidateResource(c)
if res == nil {
return nil
}
return []ISchedtagCandidateResource{
res,
}
}
func (p *ServerBaseSchedtagPredicate) IsResourceMatchInput(input ISchedtagCustomer, res ISchedtagCandidateResource) bool {
return true
}
func (p *ServerBaseSchedtagPredicate) IsResourceFitInput(u *core.Unit, c core.Candidater, res ISchedtagCandidateResource, input ISchedtagCustomer) core.PredicateFailureReason {
return nil
}
func (p *ServerBaseSchedtagPredicate) DoSelect(
c core.Candidater,
input ISchedtagCustomer,
res []ISchedtagCandidateResource,
) []ISchedtagCandidateResource {
return res
}
func (p *ServerBaseSchedtagPredicate) AddSelectResult(index int, input ISchedtagCustomer, selectRes []ISchedtagCandidateResource, output *core.AllocatedResource) {
// resource is host, do nothing
}
func (p *ServerBaseSchedtagPredicate) GetCandidateResourceSortScore(selectRes ISchedtagCandidateResource) int64 {
// TODO
return 1
}
func (p *ServerBaseSchedtagPredicate) OnPriorityEnd(u *core.Unit, c core.Candidater) {
p.BaseSchedtagPredicate.OnPriorityEnd(p.filter, u, c)
}
func (p *ServerBaseSchedtagPredicate) OnSelectEnd(u *core.Unit, c core.Candidater, count int64) {
p.BaseSchedtagPredicate.OnSelectEnd(p.filter, u, c, count)
}
@@ -19,6 +19,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/utils"
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/compute/models"
@@ -300,3 +301,13 @@ func (c *SchedtagChecker) Check(p ISchedtagPredicate, candidate ISchedtagCandida
return nil
}
func GetInputSchedtagByType(tags []*computeapi.SchedtagConfig, types ...string) []*computeapi.SchedtagConfig {
ret := make([]*computeapi.SchedtagConfig, 0)
for _, tag := range tags {
if utils.IsInStringArray(tag.ResourceType, types) {
ret = append(ret, tag)
}
}
return ret
}
@@ -0,0 +1,119 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package predicates
import (
"yunion.io/x/jsonutils"
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
computemodels "yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/scheduler/api"
"yunion.io/x/onecloud/pkg/scheduler/core"
)
type ZoneSchedtagPredicate struct {
*ServerBaseSchedtagPredicate
}
func NewZoneSchedtagPredicate() core.FitPredicate {
p := new(ZoneSchedtagPredicate)
p.ServerBaseSchedtagPredicate = NewServerBaseSchedtagPredicate(p)
return p
}
func (p *ZoneSchedtagPredicate) Name() string {
return "zone_schedtag"
}
func (p *ZoneSchedtagPredicate) Clone() core.FitPredicate {
return NewZoneSchedtagPredicate()
}
type zoneSchedtagInputW struct {
schedData *api.SchedInfo
zone string
schedtags []*computeapi.SchedtagConfig
}
func (p *ZoneSchedtagPredicate) GetInputs(u *core.Unit) []ISchedtagCustomer {
data := u.SchedData()
tags := data.Schedtags
return []ISchedtagCustomer{
&zoneSchedtagInputW{
schedData: data,
zone: data.PreferZone,
schedtags: GetInputSchedtagByType(tags, computemodels.ZoneManager.KeywordPlural()),
},
}
}
func (w *zoneSchedtagInputW) Keyword() string {
return "server"
}
func (w *zoneSchedtagInputW) ResourceKeyword() string {
return "zone"
}
func (w *zoneSchedtagInputW) GetDynamicConditionInput() *jsonutils.JSONDict {
return w.schedData.ToConditionInput()
}
func (w *zoneSchedtagInputW) IsSpecifyResource() bool {
return w.zone != ""
}
func (w *zoneSchedtagInputW) GetSchedtags() []*computeapi.SchedtagConfig {
return w.schedtags
}
type zoneSchedtagResW struct {
zone *computemodels.SZone
c core.Candidater
}
func (r zoneSchedtagResW) GetName() string {
return r.zone.GetName()
}
func (r zoneSchedtagResW) GetId() string {
return r.zone.GetId()
}
func (r zoneSchedtagResW) Keyword() string {
return r.zone.Keyword()
}
func (r zoneSchedtagResW) GetSchedtags() []computemodels.SSchedtag {
// TODO: not fetch schedtags from database, should get zone schedtags from r.c cache candidater
return r.zone.GetSchedtags()
}
func (r zoneSchedtagResW) GetSchedtagJointManager() computemodels.ISchedtagJointManager {
return r.zone.GetSchedtagJointManager()
}
func (r zoneSchedtagResW) GetDynamicConditionInput() *jsonutils.JSONDict {
// TODO: use sched input data ???
return r.zone.GetDynamicConditionInput()
}
func (p *ZoneSchedtagPredicate) GetCandidateResource(c core.Candidater) ISchedtagCandidateResource {
zone := c.Getter().Zone()
return zoneSchedtagResW{
zone: zone,
c: c,
}
}
+4 -1
View File
@@ -30,7 +30,7 @@ func init() {
func baremetalPredicates() sets.String {
return sets.NewString(
factory.RegisterFitPredicate("a-BaremetalStatusFilter", &predicatebm.StatusPredicate{}),
factory.RegisterFitPredicate("b-BaremetalAggregateFilter", &predicates.AggregatePredicate{}),
factory.RegisterFitPredicate("b-BaremetalschedtagFilter", predicates.NewHostSchedtagPredicate()),
factory.RegisterFitPredicate("c-BaremetalCPUFilter", &predicatebm.CPUPredicate{}),
factory.RegisterFitPredicate("d-BaremetalMemoryFilter", &predicatebm.MemoryPredicate{}),
factory.RegisterFitPredicate("e-BaremetalStorageFilter", &predicatebm.StoragePredicate{}),
@@ -41,5 +41,8 @@ func baremetalPredicates() sets.String {
factory.RegisterFitPredicate("k-NetBondingFilter", &predicatebm.NetBondingPredicate{}),
factory.RegisterFitPredicate("l-CdromFilter", &predicatebm.CdromBootPredicate{}),
factory.RegisterFitPredicate("m-IsolatedDevicesFilter", &predicates.IsolatedDevicePredicate{}),
factory.RegisterFitPredicate("n-CloudproviderschedtagFilter", predicates.NewCloudproviderSchedtagPredicate()),
factory.RegisterFitPredicate("o-CloudregionschedtagFilter", predicates.NewCloudregionSchedtagPredicate()),
factory.RegisterFitPredicate("p-ZoneschedtagFilter", predicates.NewZoneSchedtagPredicate()),
)
}
+4 -1
View File
@@ -31,7 +31,7 @@ func defaultPredicates() sets.String {
return sets.NewString(
factory.RegisterFitPredicate("a-GuestHostStatusFilter", &predicateguest.StatusPredicate{}),
factory.RegisterFitPredicate("b-GuestHypervisorFilter", &predicateguest.HypervisorPredicate{}),
factory.RegisterFitPredicate("c-GuestAggregateFilter", &predicates.AggregatePredicate{}),
factory.RegisterFitPredicate("c-GuestHostschedtagFilter", predicates.NewHostSchedtagPredicate()),
factory.RegisterFitPredicate("d-GuestMigrateFilter", &predicateguest.MigratePredicate{}),
factory.RegisterFitPredicate("e-GuestDomainFilter", &predicates.DomainPredicate{}),
factory.RegisterFitPredicate("e-GuestImageFilter", &predicateguest.ImagePredicate{}),
@@ -45,6 +45,9 @@ func defaultPredicates() sets.String {
factory.RegisterFitPredicate("m-GuestDiskschedtagFilter", &predicates.DiskSchedtagPredicate{}),
factory.RegisterFitPredicate("n-ServerSkuFilter", &predicates.InstanceTypePredicate{}),
factory.RegisterFitPredicate("o-GuestNetschedtagFilter", &predicates.NetworkSchedtagPredicate{}),
factory.RegisterFitPredicate("p-CloudproviderschedtagFilter", predicates.NewCloudproviderSchedtagPredicate()),
factory.RegisterFitPredicate("q-CloudregionschedtagFilter", predicates.NewCloudregionSchedtagPredicate()),
factory.RegisterFitPredicate("r-ZoneschedtagFilter", predicates.NewZoneSchedtagPredicate()),
factory.RegisterFitPredicate("z-QuotaFilter", &predicates.SQuotaPredicate{}),
)
}
-7
View File
@@ -22,7 +22,6 @@ import (
"yunion.io/x/log"
"yunion.io/x/pkg/tristate"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/compute/models"
@@ -448,12 +447,6 @@ func (u *Unit) SchedData() *api.SchedInfo {
return u.SchedInfo
}
func (u *Unit) ShouldExecuteSchedtagFilter(hostId string) bool {
return !utils.IsInStringArray(
hostId, []string{u.SchedInfo.PreferHost, u.SchedInfo.PreferBackupHost},
)
}
func (u *Unit) GetHypervisor() string {
hypervisor := compute.HOSTTYPE_HYPERVISOR[u.SchedData().Hypervisor]
if hypervisor == "" {