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.

cloudScheduler.go 6.5 kB

11 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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 schedulers
  13. import (
  14. "context"
  15. "errors"
  16. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler"
  17. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/schedulers/option"
  18. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/service/collector"
  19. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/strategy"
  20. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/strategy/param"
  21. "gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
  22. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/constants"
  23. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/models/cloud"
  24. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/response"
  25. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/tracker"
  26. "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/utils"
  27. "gorm.io/gorm"
  28. "math"
  29. "time"
  30. )
  31. type CloudScheduler struct {
  32. yamlString string
  33. task *response.TaskInfo
  34. *scheduler.Scheduler
  35. option *option.CloudOption
  36. ctx context.Context
  37. dbEngin *gorm.DB
  38. promClient tracker.Prometheus
  39. svcCtx *svc.ServiceContext
  40. }
  41. type CloudResult struct {
  42. TaskId string
  43. ClusterId string
  44. ClusterName string
  45. Strategy string
  46. Replica int32
  47. Msg string
  48. }
  49. func NewCloudScheduler(ctx context.Context, val string, scheduler *scheduler.Scheduler, option *option.CloudOption, dbEngin *gorm.DB, promClient tracker.Prometheus) (*CloudScheduler, error) {
  50. return &CloudScheduler{ctx: ctx, yamlString: val, Scheduler: scheduler, option: option, dbEngin: dbEngin, promClient: promClient}, nil
  51. }
  52. func (as *CloudScheduler) GetNewStructForDb(task *response.TaskInfo, resource string, participantId int64) (interface{}, error) {
  53. c := cloud.TaskCloudModel{
  54. AdapterId: (participantId),
  55. TaskId: (task.TaskId),
  56. Status: constants.Saved,
  57. YamlString: as.yamlString,
  58. }
  59. utils.Convert(task.Metadata, &c)
  60. return c, nil
  61. }
  62. func (as *CloudScheduler) PickOptimalStrategy() (strategy.Strategy, error) {
  63. if len(as.option.ClusterIds) == 1 {
  64. return &strategy.SingleAssignment{Cluster: &strategy.AssignedCluster{ClusterId: as.option.ClusterIds[0], Replicas: 1}}, nil
  65. }
  66. resources, err := as.findClustersWithResources()
  67. if err != nil {
  68. return nil, err
  69. }
  70. if len(resources) == 0 {
  71. return nil, errors.New("no cluster has resources")
  72. }
  73. if len(resources) == 1 {
  74. var cluster strategy.AssignedCluster
  75. cluster.ClusterId = resources[0].ClusterId
  76. cluster.Replicas = 1
  77. return &strategy.SingleAssignment{Cluster: &cluster}, nil
  78. }
  79. params := &param.Params{Resources: resources}
  80. switch as.option.Strategy {
  81. case strategy.REPLICATION:
  82. var clusterIds []string
  83. for _, resource := range resources {
  84. clusterIds = append(clusterIds, resource.ClusterId)
  85. }
  86. strategy := strategy.NewReplicationStrategy(clusterIds, as.option.Replica)
  87. return strategy, nil
  88. case strategy.RESOURCES_PRICING:
  89. strategy := strategy.NewPricingStrategy(&param.ResourcePricingParams{Params: params, Replicas: as.option.Replica})
  90. return strategy, nil
  91. case strategy.DYNAMIC_RESOURCES:
  92. strategy := strategy.NewDynamicResourcesStrategy(params.Resources, as.option, 1)
  93. return strategy, nil
  94. case strategy.STATIC_WEIGHT:
  95. //todo resources should match cluster StaticWeightMap
  96. strategy := strategy.NewStaticWeightStrategy(as.option.StaticWeightMap, as.option.Replica)
  97. return strategy, nil
  98. }
  99. return nil, errors.New("no strategy has been chosen")
  100. }
  101. func (as *CloudScheduler) AssignTask(clusters []*strategy.AssignedCluster, mode int) (interface{}, error) {
  102. if clusters == nil {
  103. return nil, errors.New("clusters is nil")
  104. }
  105. for i := len(clusters) - 1; i >= 0; i-- {
  106. if clusters[i].Replicas == 0 {
  107. clusters = append(clusters[:i], clusters[i+1:]...)
  108. }
  109. }
  110. if len(clusters) == 0 {
  111. return nil, errors.New("clusters is nil")
  112. }
  113. var results []*CloudResult
  114. for _, cluster := range clusters {
  115. cName := ""
  116. as.dbEngin.Table("t_cluster").Select("name").Where("id=?", cluster.ClusterId).Find(&cName)
  117. cr := CloudResult{
  118. ClusterId: cluster.ClusterId,
  119. ClusterName: cName,
  120. Replica: cluster.Replicas,
  121. }
  122. cr.ClusterId = cluster.ClusterId
  123. cr.Replica = cluster.Replicas
  124. cr.ClusterName = cName
  125. results = append(results, &cr)
  126. }
  127. return results, nil
  128. }
  129. func (as *CloudScheduler) findClustersWithResources() ([]*collector.ResourceStats, error) {
  130. resp := []*collector.ResourceStats{}
  131. //查询集群资源信息
  132. var rMetrics []tracker.Metric
  133. metrics := []string{"cluster_cpu_utilisation", "cluster_cpu_avail", "cluster_cpu_total", "cluster_memory_total", "cluster_memory_avail", "cluster_memory_utilisation", "cluster_disk_utilisation", "cluster_disk_avail", "cluster_disk_total", "cluster_pod_utilisation"}
  134. var clusterNames []string
  135. as.dbEngin.Table("t_cluster").Select("name").Where("id in ?", as.option.ClusterIds).Find(&clusterNames)
  136. for _, c := range clusterNames {
  137. rMetrics = as.promClient.GetNamedMetrics(metrics, time.Now(), tracker.ClusterOption{ClusterName: c})
  138. r := collector.ResourceStats{}
  139. var cid string
  140. as.dbEngin.Table("t_cluster").Select("id").Where("name = ?", c).Find(&cid)
  141. r.ClusterId = cid
  142. r.Name = c
  143. for _, metric := range rMetrics {
  144. if metric.MetricName == "cluster_cpu_total" {
  145. r.CpuCoreTotal = int64(metric.MetricData.MetricValues[0].Sample.Value())
  146. }
  147. if metric.MetricName == "cluster_cpu_avail" {
  148. cpuAvail := metric.MetricData.MetricValues[0].Sample.Value()
  149. r.CpuCoreAvail = int64(math.Round(cpuAvail))
  150. }
  151. if metric.MetricName == "cluster_memory_total" {
  152. r.MemTotal = metric.MetricData.MetricValues[0].Sample.Value()
  153. }
  154. if metric.MetricName == "cluster_memory_avail" {
  155. r.MemAvail = metric.MetricData.MetricValues[0].Sample.Value()
  156. }
  157. if metric.MetricName == "cluster_disk_total" {
  158. r.DiskTotal = metric.MetricData.MetricValues[0].Sample.Value()
  159. }
  160. if metric.MetricName == "cluster_disk_avail" {
  161. r.DiskAvail = metric.MetricData.MetricValues[0].Sample.Value()
  162. }
  163. }
  164. resp = append(resp, &r)
  165. }
  166. return resp, nil
  167. }

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.