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

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.