class_metadata_predicate.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package predicates
  15. import (
  16. "context"
  17. "fmt"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/pkg/errors"
  20. "yunion.io/x/pkg/util/rbacscope"
  21. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  22. "yunion.io/x/onecloud/pkg/compute/models"
  23. "yunion.io/x/onecloud/pkg/mcclient/auth"
  24. "yunion.io/x/onecloud/pkg/scheduler/core"
  25. )
  26. type ClassMetadataPredicate struct {
  27. BasePredicate
  28. guestSource *ResourceWithClassMetadata
  29. tenant *ResourceWithClassMetadata
  30. }
  31. type ResourceWithClassMetadata struct {
  32. keyword string
  33. name string
  34. classMedata map[string]string
  35. }
  36. func (rcm *ResourceWithClassMetadata) GetAllClassMetadata() (map[string]string, error) {
  37. return rcm.classMedata, nil
  38. }
  39. func (rcm *ResourceWithClassMetadata) GetDescription() string {
  40. return fmt.Sprintf("%s %s", rcm.keyword, rcm.name)
  41. }
  42. func (p *ClassMetadataPredicate) Name() string {
  43. return "class_metadata"
  44. }
  45. func (p *ClassMetadataPredicate) Clone() core.FitPredicate {
  46. return &ClassMetadataPredicate{
  47. guestSource: p.guestSource,
  48. tenant: p.tenant,
  49. }
  50. }
  51. func (p *ClassMetadataPredicate) PreExecute(ctx context.Context, u *core.Unit, cs []core.Candidater) (bool, error) {
  52. info := u.SchedData()
  53. if info.ResetCpuNumaPin {
  54. return false, nil
  55. }
  56. tenant, err := db.TenantCacheManager.FetchTenantById(ctx, info.Project)
  57. if err != nil {
  58. return false, errors.Wrapf(err, "unable to fetch tenant %s", info.Project)
  59. }
  60. tcm, err := tenant.GetAllClassMetadata()
  61. if err != nil {
  62. return false, errors.Wrapf(err, "unable to GetAllClassMetadata of project %s", info.Project)
  63. }
  64. p.tenant = &ResourceWithClassMetadata{
  65. classMedata: tcm,
  66. keyword: tenant.Keyword(),
  67. name: tenant.GetName(),
  68. }
  69. // guest source
  70. guestSource := &ResourceWithClassMetadata{}
  71. disks := info.Disks
  72. var stand db.IStandaloneModel
  73. // TODO GuestImage
  74. switch {
  75. case len(info.InstanceBackupId) > 0:
  76. obj, err := models.InstanceBackupManager.FetchById(info.InstanceBackupId)
  77. if err != nil {
  78. return false, errors.Wrapf(err, "unable to fetch instanceBackup %s", info.InstanceBackupId)
  79. }
  80. stand = obj.(db.IStandaloneModel)
  81. case len(info.InstanceSnapshotId) > 0:
  82. obj, err := models.InstanceSnapshotManager.FetchById(info.InstanceSnapshotId)
  83. if err != nil {
  84. return false, errors.Wrapf(err, "unable to fetch instanceSnapshot %s", info.InstanceSnapshotId)
  85. }
  86. stand = obj.(db.IStandaloneModel)
  87. case len(disks) == 0:
  88. break
  89. case disks[0].ImageId != "":
  90. obj, err := models.CachedimageManager.GetCachedimageById(ctx, auth.AdminCredential(), disks[0].ImageId, false)
  91. if err == nil {
  92. // no check if image if system public image
  93. public := jsonutils.QueryBoolean(obj.Info, "is_public", false)
  94. publicScope, _ := obj.Info.GetString("public_scope")
  95. if !public || publicScope != string(rbacscope.ScopeSystem) {
  96. stand = obj
  97. guestSource.keyword = "image"
  98. }
  99. }
  100. case disks[0].SnapshotId != "":
  101. obj, err := models.SnapshotManager.FetchById(disks[0].SnapshotId)
  102. if err == nil {
  103. stand = obj.(db.IStandaloneModel)
  104. }
  105. case disks[0].BackupId != "":
  106. obj, err := models.DiskBackupManager.FetchById(disks[0].BackupId)
  107. if err != nil {
  108. return false, errors.Wrapf(err, "unable to fetch diskbackup %s", disks[0].BackupId)
  109. }
  110. stand = obj.(db.IStandaloneModel)
  111. }
  112. if stand == nil {
  113. return true, nil
  114. }
  115. cm, err := stand.GetAllClassMetadata()
  116. if err != nil {
  117. return false, errors.Wrapf(err, "unable to GetAllClassMetadata %s", stand.GetId())
  118. }
  119. guestSource.classMedata = cm
  120. if guestSource.keyword == "" {
  121. guestSource.keyword = stand.Keyword()
  122. }
  123. guestSource.name = stand.GetName()
  124. p.guestSource = guestSource
  125. return true, nil
  126. }
  127. func (p *ClassMetadataPredicate) Execute(ctx context.Context, u *core.Unit, c core.Candidater) (bool, []core.PredicateFailureReason, error) {
  128. h := NewPredicateHelper(p, u, c)
  129. for _, resource := range []*ResourceWithClassMetadata{p.tenant, p.guestSource} {
  130. if resource == nil {
  131. continue
  132. }
  133. ic, err := db.IsInSameClass(ctx, c.Getter(), resource)
  134. if err != nil {
  135. return false, nil, errors.Wrap(err, "unable to determine whether they are in a class")
  136. }
  137. if !ic {
  138. h.Exclude(fmt.Sprintf("The host doesn't have the same class metadata as the choosen %s.", resource.GetDescription()))
  139. break
  140. }
  141. }
  142. return h.GetResult()
  143. }