You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

scheduler.go 5.3 kB

11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. Copyright (c) [2023] [pcm]
  3. [pcm-coordinator] is licensed under Mulan PSL v2.
  4. You can use this software according to the terms and conditions of the Mulan PSL v2.
  5. You may obtain a copy of Mulan PSL v2 at:
  6. http://license.coscl.org.cn/MulanPSL2
  7. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
  8. EITHER EXPaRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
  9. MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
  10. See the Mulan PSL v2 for more details.
  11. */
  12. package scheduler
  13. import (
  14. "encoding/json"
  15. "github.com/pkg/errors"
  16. "github.com/zeromicro/go-zero/core/logx"
  17. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/common"
  18. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/database"
  19. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/service"
  20. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/strategy"
  21. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/response"
  22. "gorm.io/gorm"
  23. "sigs.k8s.io/yaml"
  24. "strings"
  25. "sync"
  26. )
  27. const (
  28. JOINT_CLOUD_MODE = iota + 1
  29. STORAGE_SCHEDULE_MODE
  30. )
  31. type Scheduler struct {
  32. task *response.TaskInfo
  33. participantIds []int64
  34. subSchedule SubSchedule
  35. dbEngin *gorm.DB
  36. result []string //pID:子任务yamlstring 键值对
  37. AiStorages *database.AiStorage
  38. AiService *service.AiService
  39. mu sync.RWMutex
  40. }
  41. type SubSchedule interface {
  42. GetNewStructForDb(task *response.TaskInfo, resource string, participantId int64) (interface{}, error)
  43. PickOptimalStrategy() (strategy.Strategy, error)
  44. AssignTask(clusters []*strategy.AssignedCluster, mode int) (interface{}, error)
  45. }
  46. func NewScheduler(subSchedule SubSchedule, val string, dbEngin *gorm.DB) (*Scheduler, error) {
  47. var task *response.TaskInfo
  48. err := json.Unmarshal([]byte(val), &task)
  49. if err != nil {
  50. return nil, errors.New("create scheduler failed : " + err.Error())
  51. }
  52. return &Scheduler{task: task, subSchedule: subSchedule, dbEngin: dbEngin}, nil
  53. }
  54. func NewSchdlr(aiService *service.AiService, storages *database.AiStorage) *Scheduler {
  55. return &Scheduler{AiService: aiService, AiStorages: storages}
  56. }
  57. func (s *Scheduler) SpecifyClusters() {
  58. // 如果已指定集群名,通过数据库查询后返回p端ip列表
  59. if len(s.task.Clusters) != 0 {
  60. s.dbEngin.Raw("select id from sc_participant_phy_info where `name` in (?)", s.task.Clusters).Scan(&s.participantIds)
  61. return
  62. }
  63. }
  64. func (s *Scheduler) SpecifyNsID() {
  65. // 未指定集群名,只指定nsID
  66. if len(s.task.Clusters) == 0 {
  67. if len(s.task.NsID) != 0 {
  68. var clusters string
  69. s.dbEngin.Raw("select clusters from sc_tenant_info where `tenant_name` = ?", s.task.NsID).Scan(&clusters)
  70. clusterArr := strings.Split(clusters, ",")
  71. s.dbEngin.Raw("select id from sc_participant_phy_info where `name` in (?)", clusterArr).Scan(&s.participantIds)
  72. }
  73. } else {
  74. return
  75. }
  76. }
  77. func (s *Scheduler) MatchLabels() {
  78. var ids []int64
  79. count := 0
  80. // 集群和nsID都未指定,则通过标签匹配
  81. if len(s.task.Clusters) == 0 && len(s.task.NsID) == 0 {
  82. //如果集群列表或nsID均未指定
  83. for key := range s.task.MatchLabels {
  84. var participantIds []int64
  85. s.dbEngin.Raw("select participant_id from sc_participant_label_info where `key` = ? and value = ?", key, s.task.MatchLabels[key]).Scan(&participantIds)
  86. if count == 0 {
  87. ids = participantIds
  88. }
  89. ids = common.Intersect(ids, participantIds)
  90. count++
  91. }
  92. s.participantIds = ids
  93. } else {
  94. return
  95. }
  96. }
  97. // TempAssign todo 屏蔽原调度算法
  98. func (s *Scheduler) TempAssign() error {
  99. //需要判断task中的资源类型,针对metadata中的多个kind做不同处理
  100. //输入副本数和集群列表,最终结果输出为pID对应副本数量列表,针对多个kind需要做拆分和重新拼接组合
  101. var meData []string
  102. for _, yamlString := range s.task.Metadata {
  103. var data map[string]interface{}
  104. err := yaml.Unmarshal([]byte(yamlString), &data)
  105. if err != nil {
  106. }
  107. jsonData, err := json.Marshal(data)
  108. if err != nil {
  109. }
  110. meData = append(meData, string(jsonData))
  111. }
  112. s.task.Metadata = meData
  113. return nil
  114. }
  115. func (s *Scheduler) AssignAndSchedule(ss SubSchedule, mode int) (interface{}, error) {
  116. //choose strategy
  117. strategy, err := ss.PickOptimalStrategy()
  118. if err != nil {
  119. return nil, err
  120. }
  121. //schedule
  122. clusters, err := strategy.Schedule()
  123. if err != nil {
  124. return nil, err
  125. }
  126. //assign tasks to clusters
  127. resp, err := ss.AssignTask(clusters, mode)
  128. if err != nil {
  129. return nil, err
  130. }
  131. return resp, nil
  132. }
  133. func (s *Scheduler) SaveToDb() error {
  134. for _, participantId := range s.participantIds {
  135. for _, resource := range s.task.Metadata {
  136. structForDb, err := s.subSchedule.GetNewStructForDb(s.task, resource, participantId)
  137. if err != nil {
  138. return err
  139. }
  140. tx := s.dbEngin.Create(structForDb)
  141. if tx.Error != nil {
  142. logx.Error(tx.Error)
  143. return tx.Error
  144. }
  145. }
  146. }
  147. return nil
  148. }
  149. func (s *Scheduler) CreateTask(taskName string, synergyCode int64, strategyName string, yaml string) (int64, error) {
  150. strategyCode, err := s.AiStorages.GetStrategyCode(strategyName)
  151. if err != nil {
  152. return 0, err
  153. }
  154. id, err := s.AiStorages.SaveTask(taskName, strategyCode, synergyCode, "10", yaml)
  155. if err != nil {
  156. return 0, err
  157. }
  158. return id, nil
  159. }

PCM is positioned as Software stack over Cloud, aiming to build the standards and ecology of heterogeneous cloud collaboration for JCC in a non intrusive and autonomous peer-to-peer manner.