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.7 kB

10 months ago
11 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
11 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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/service/executor"
  21. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/strategy"
  22. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/response"
  23. "gorm.io/gorm"
  24. "sigs.k8s.io/yaml"
  25. "strings"
  26. "sync"
  27. )
  28. type Scheduler struct {
  29. task *response.TaskInfo
  30. participantIds []int64
  31. subSchedule SubSchedule
  32. dbEngin *gorm.DB
  33. result []string //pID:子任务yamlstring 键值对
  34. AiStorages *database.AiStorage
  35. AiService *service.AiService
  36. mu sync.RWMutex
  37. }
  38. type SubSchedule interface {
  39. GetNewStructForDb(task *response.TaskInfo, resource string, participantId int64) (interface{}, error)
  40. PickOptimalStrategy() (strategy.Strategy, error)
  41. AssignTask(clusters []*strategy.AssignedCluster, mode int) (interface{}, error)
  42. }
  43. func NewScheduler(subSchedule SubSchedule, val string, dbEngin *gorm.DB) (*Scheduler, error) {
  44. var task *response.TaskInfo
  45. err := json.Unmarshal([]byte(val), &task)
  46. if err != nil {
  47. return nil, errors.New("create scheduler failed : " + err.Error())
  48. }
  49. return &Scheduler{task: task, subSchedule: subSchedule, dbEngin: dbEngin}, nil
  50. }
  51. func NewSchdlr(aiService *service.AiService, storages *database.AiStorage) *Scheduler {
  52. return &Scheduler{AiService: aiService, AiStorages: storages}
  53. }
  54. func (s *Scheduler) SpecifyClusters() {
  55. // 如果已指定集群名,通过数据库查询后返回p端ip列表
  56. if len(s.task.Clusters) != 0 {
  57. s.dbEngin.Raw("select id from sc_participant_phy_info where `name` in (?)", s.task.Clusters).Scan(&s.participantIds)
  58. return
  59. }
  60. }
  61. func (s *Scheduler) SpecifyNsID() {
  62. // 未指定集群名,只指定nsID
  63. if len(s.task.Clusters) == 0 {
  64. if len(s.task.NsID) != 0 {
  65. var clusters string
  66. s.dbEngin.Raw("select clusters from sc_tenant_info where `tenant_name` = ?", s.task.NsID).Scan(&clusters)
  67. clusterArr := strings.Split(clusters, ",")
  68. s.dbEngin.Raw("select id from sc_participant_phy_info where `name` in (?)", clusterArr).Scan(&s.participantIds)
  69. }
  70. } else {
  71. return
  72. }
  73. }
  74. func (s *Scheduler) MatchLabels() {
  75. var ids []int64
  76. count := 0
  77. // 集群和nsID都未指定,则通过标签匹配
  78. if len(s.task.Clusters) == 0 && len(s.task.NsID) == 0 {
  79. //如果集群列表或nsID均未指定
  80. for key := range s.task.MatchLabels {
  81. var participantIds []int64
  82. s.dbEngin.Raw("select participant_id from sc_participant_label_info where `key` = ? and value = ?", key, s.task.MatchLabels[key]).Scan(&participantIds)
  83. if count == 0 {
  84. ids = participantIds
  85. }
  86. ids = common.Intersect(ids, participantIds)
  87. count++
  88. }
  89. s.participantIds = ids
  90. } else {
  91. return
  92. }
  93. }
  94. // TempAssign todo 屏蔽原调度算法
  95. func (s *Scheduler) TempAssign() error {
  96. //需要判断task中的资源类型,针对metadata中的多个kind做不同处理
  97. //输入副本数和集群列表,最终结果输出为pID对应副本数量列表,针对多个kind需要做拆分和重新拼接组合
  98. var meData []string
  99. for _, yamlString := range s.task.Metadata {
  100. var data map[string]interface{}
  101. err := yaml.Unmarshal([]byte(yamlString), &data)
  102. if err != nil {
  103. }
  104. jsonData, err := json.Marshal(data)
  105. if err != nil {
  106. }
  107. meData = append(meData, string(jsonData))
  108. }
  109. s.task.Metadata = meData
  110. return nil
  111. }
  112. func (s *Scheduler) AssignAndSchedule(ss SubSchedule, mode int, assignedClusters []*strategy.AssignedCluster) (interface{}, error) {
  113. var result interface{}
  114. switch mode {
  115. case executor.SUBMIT_MODE_JOINT_CLOUD:
  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. result = resp
  132. case executor.SUBMIT_MODE_STORAGE_SCHEDULE:
  133. //assign tasks to clusters
  134. resp, err := ss.AssignTask(assignedClusters, mode)
  135. if err != nil {
  136. return nil, err
  137. }
  138. result = resp
  139. }
  140. return result, nil
  141. }
  142. func (s *Scheduler) SaveToDb() error {
  143. for _, participantId := range s.participantIds {
  144. for _, resource := range s.task.Metadata {
  145. structForDb, err := s.subSchedule.GetNewStructForDb(s.task, resource, participantId)
  146. if err != nil {
  147. return err
  148. }
  149. tx := s.dbEngin.Create(structForDb)
  150. if tx.Error != nil {
  151. logx.Error(tx.Error)
  152. return tx.Error
  153. }
  154. }
  155. }
  156. return nil
  157. }
  158. func (s *Scheduler) CreateTask(taskName string, synergyCode int64, strategyName string, yaml string) (int64, error) {
  159. strategyCode, err := s.AiStorages.GetStrategyCode(strategyName)
  160. if err != nil {
  161. return 0, err
  162. }
  163. id, err := s.AiStorages.SaveTask(taskName, strategyCode, synergyCode, "10", yaml)
  164. if err != nil {
  165. return 0, err
  166. }
  167. return id, nil
  168. }

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.