From f32b20bd1861428f290b5503aa8a484905430bde Mon Sep 17 00:00:00 2001 From: zhangwei <894646498@qq.com> Date: Mon, 22 Apr 2024 15:14:26 +0800 Subject: [PATCH 01/13] Add filtering fields to the alarm list Former-commit-id: f99531dec1e2610267446bb414fb529bd4b5f97b --- api/desc/monitoring/pcm-monitoring.api | 2 + .../logic/monitoring/alertruleslogic.go | 10 +- api/internal/types/types.go | 180 ++++++++++++++++++ 3 files changed, 191 insertions(+), 1 deletion(-) diff --git a/api/desc/monitoring/pcm-monitoring.api b/api/desc/monitoring/pcm-monitoring.api index a70f3bf5..06f84557 100644 --- a/api/desc/monitoring/pcm-monitoring.api +++ b/api/desc/monitoring/pcm-monitoring.api @@ -14,6 +14,8 @@ type CreateAlertRuleReq { type ( AlertRulesReq { AlertType string `form:"alertType"` + AdapterId string `form:"adapterId,optional"` + ClusterId string `form:"clusterId,optional"` } AlertRulesResp { alertRules []AlertRule `json:"alertRules"` diff --git a/api/internal/logic/monitoring/alertruleslogic.go b/api/internal/logic/monitoring/alertruleslogic.go index e821897a..d7d2dde8 100644 --- a/api/internal/logic/monitoring/alertruleslogic.go +++ b/api/internal/logic/monitoring/alertruleslogic.go @@ -2,6 +2,7 @@ package monitoring import ( "context" + "fmt" "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/svc" "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/types" @@ -26,7 +27,14 @@ func NewAlertRulesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AlertR func (l *AlertRulesLogic) AlertRules(req *types.AlertRulesReq) (resp *types.AlertRulesResp, err error) { resp = &types.AlertRulesResp{} var alertRules []types.AlertRule - l.svcCtx.DbEngin.Raw("SELECT ar.id,ar.*,GROUP_CONCAT(tc.`name` ORDER BY tc.`name` ASC SEPARATOR ',') as cluster_name FROM alert_rule ar JOIN t_cluster tc ON ar.cluster_id = tc.id WHERE ar.alert_type = ? AND ar.deleted_at IS NULL AND tc.deleted_at IS NULL GROUP BY ar.id", req.AlertType).Scan(&alertRules) + sql := fmt.Sprintf("SELECT ar.*,GROUP_CONCAT(tc.`name` ORDER BY tc.`name` ASC SEPARATOR ',') as cluster_name FROM alert_rule ar JOIN t_cluster tc ON ar.cluster_id = tc.id WHERE ar.alert_type = %s AND ar.deleted_at IS NULL AND tc.deleted_at IS NULL GROUP BY ar.id", req.AlertType) + if req.AdapterId != "" { + sql = fmt.Sprintf("SELECT tar.*,GROUP_CONCAT( tc.`name` ORDER BY tc.`name` ASC SEPARATOR ',' ) AS cluster_name FROM talert_rule ar JOIN t_cluster tc ON ar.cluster_id = tc.id JOIN t_adapter ta ON ta.id = tc.adapter_id WHERE tar.alert_type = %s AND ta.id = %s AND ar.deleted_at IS NULL AND tc.deleted_at IS NULL GROUP BY tar.id", req.AlertType, req.AdapterId) + } + if req.ClusterId != "" { + sql = fmt.Sprintf("SELECT ar.*,GROUP_CONCAT(tc.`name` ORDER BY tc.`name` ASC SEPARATOR ',') as cluster_name FROM alert_rule ar JOIN t_cluster tc ON ar.cluster_id = tc.id WHERE ar.alert_type = %s AND ar.cluster_id = %s AND ar.deleted_at IS NULL AND tc.deleted_at IS NULL GROUP BY ar.id", req.AlertType, req.ClusterId) + } + l.svcCtx.DbEngin.Raw(sql).Scan(&alertRules) resp.AlertRules = alertRules return resp, nil } diff --git a/api/internal/types/types.go b/api/internal/types/types.go index 5b0c362d..757053fb 100644 --- a/api/internal/types/types.go +++ b/api/internal/types/types.go @@ -874,6 +874,184 @@ type ListResult struct { List interface{} `json:"list,omitempty"` } +type HpcInfo struct { + Id int64 `json:"id"` // id + TaskId int64 `json:"task_id"` // 任务id + JobId string `json:"job_id"` // 作业id(在第三方系统中的作业id) + AdapterId int64 `json:"adapter_id"` // 执行任务的适配器id + ClusterId int64 `json:"cluster_id"` // 执行任务的集群id + ClusterType string `json:"cluster_type"` // 执行任务的集群类型 + Name string `json:"name"` // 名称 + Status string `json:"status"` // 状态 + CmdScript string `json:"cmd_script"` + StartTime string `json:"start_time"` // 开始时间 + RunningTime int64 `json:"running_time"` // 运行时间 + DerivedEs string `json:"derived_es"` + Cluster string `json:"cluster"` + BlockId int64 `json:"block_id"` + AllocNodes int64 `json:"alloc_nodes"` + AllocCpu int64 `json:"alloc_cpu"` + CardCount int64 `json:"card_count"` // 卡数 + Version string `json:"version"` + Account string `json:"account"` + WorkDir string `json:"work_dir"` // 工作路径 + AssocId int64 `json:"assoc_id"` + ExitCode int64 `json:"exit_code"` + WallTime string `json:"wall_time"` // 最大运行时间 + Result string `json:"result"` // 运行结果 + DeletedAt string `json:"deleted_at"` // 删除时间 + YamlString string `json:"yaml_string"` + AppType string `json:"app_type"` // 应用类型 + AppName string `json:"app_name"` // 应用名称 + Queue string `json:"queue"` // 队列名称 + SubmitType string `json:"submit_type"` // cmd(命令行模式) + NNode string `json:"n_node"` // 节点个数(当指定该参数时,GAP_NODE_STRING必须为"") + StdOutFile string `json:"std_out_file"` // 工作路径/std.err.%j + StdErrFile string `json:"std_err_file"` // 工作路径/std.err.%j + StdInput string `json:"std_input"` + Environment string `json:"environment"` + DeletedFlag int64 `json:"deleted_flag"` // 是否删除(0-否,1-是) + CreatedBy int64 `json:"created_by"` // 创建人 + CreatedTime string `json:"created_time"` // 创建时间 + UpdatedBy int64 `json:"updated_by"` // 更新人 + UpdatedTime string `json:"updated_time"` // 更新时间 +} + +type CloudInfo struct { + Participant int64 `json:"participant,omitempty"` + Id int64 `json:"id,omitempty"` + TaskId int64 `json:"taskId,omitempty"` + ApiVersion string `json:"apiVersion,omitempty"` + Kind string `json:"kind,omitempty"` + Namespace string `json:"namespace,omitempty"` + Name string `json:"name,omitempty"` + Status string `json:"status,omitempty"` + StartTime string `json:"startTime,omitempty"` + RunningTime int64 `json:"runningTime,omitempty"` + Result string `json:"result,omitempty"` + YamlString string `json:"yamlString,omitempty"` +} + +type AiInfo struct { + ParticipantId int64 `json:"participantId,omitempty"` + TaskId int64 `json:"taskId,omitempty"` + ProjectId string `json:"project_id,omitempty"` + Name string `json:"name,omitempty"` + Status string `json:"status,omitempty"` + StartTime string `json:"startTime,omitempty"` + RunningTime int64 `json:"runningTime,omitempty"` + Result string `json:"result,omitempty"` + JobId string `json:"jobId,omitempty"` + CreateTime string `json:"createTime,omitempty"` + ImageUrl string `json:"imageUrl,omitempty"` + Command string `json:"command,omitempty"` + FlavorId string `json:"flavorId,omitempty"` + SubscriptionId string `json:"subscriptionId,omitempty"` + ItemVersionId string `json:"itemVersionId,omitempty"` +} + +type VmInfo struct { + ParticipantId int64 `json:"participantId,omitempty"` + TaskId int64 `json:"taskId,omitempty"` + Name string `json:"name,omitempty"` + FlavorRef string `json:"flavor_ref,omitempty"` + ImageRef string `json:"image_ref,omitempty"` + NetworkUuid string `json:"network_uuid,omitempty"` + BlockUuid string `json:"block_uuid,omitempty"` + SourceType string `json:"source_type,omitempty"` + DeleteOnTermination bool `json:"delete_on_termination,omitempty"` + Status string `json:"status,omitempty"` + MinCount string `json:"min_count,omitempty"` + Platform string `json:"platform,omitempty"` + Uuid string `json:"uuid,omitempty"` +} + +type PullTaskInfoReq struct { + AdapterId int64 `form:"adapterId"` +} + +type PullTaskInfoResp struct { + HpcInfoList []*HpcInfo `json:"HpcInfoList,omitempty"` + CloudInfoList []*CloudInfo `json:"CloudInfoList,omitempty"` + AiInfoList []*AiInfo `json:"AiInfoList,omitempty"` + VmInfoList []*VmInfo `json:"VmInfoList,omitempty"` +} + +type PushTaskInfoReq struct { + AdapterId int64 `json:"adapterId"` + HpcInfoList []*HpcInfo `json:"hpcInfoList"` + CloudInfoList []*CloudInfo `json:"cloudInfoList"` + AiInfoList []*AiInfo `json:"aiInfoList"` + VmInfoList []*VmInfo `json:"vmInfoList"` +} + +type PushTaskInfoResp struct { + Code int64 `json:"code"` + Msg string `json:"msg"` +} + +type PushResourceInfoReq struct { + AdapterId int64 `json:"adapterId"` + ResourceStats []ResourceStats `json:"resourceStats"` +} + +type PushResourceInfoResp struct { + Code int64 `json:"code"` + Msg string `json:"msg"` +} + +type NoticeInfo struct { + AdapterId int64 `json:"adapterId"` + AdapterName string `json:"adapterName"` + ClusterId int64 `json:"clusterId"` + ClusterName string `json:"clusterName"` + NoticeType string `json:"noticeType"` + TaskName string `json:"taskName"` + Incident string `json:"incident"` +} + +type ListNoticeReq struct { +} + +type ListNoticeResp struct { + Code int64 `json:"code"` + Msg string `json:"msg"` + Data []NoticeInfo `json:"data"` +} + +type PushNoticeReq struct { + NoticeInfo NoticeInfo `json:"noticeInfo"` +} + +type PushNoticeResp struct { + Code int64 `json:"code"` + Msg string `json:"msg"` +} + +type ResourceStats struct { + ClusterId int64 `json:"clusterId"` + Name string `json:"name"` + CpuCoreAvail int64 `json:"cpuCoreAvail"` + CpuCoreTotal int64 `json:"cpuCoreTotal"` + MemAvail float64 `json:"memAvail"` + MemTotal float64 `json:"memTotal"` + DiskAvail float64 `json:"diskAvail"` + DiskTotal float64 `json:"diskTotal"` + GpuAvail int64 `json:"gpuAvail"` + CardsAvail []*Card `json:"cardsAvail"` + CpuCoreHours float64 `json:"cpuCoreHours"` + Balance float64 `json:"balance"` +} + +type Card struct { + Platform string `json:"platform"` + Type string `json:"type"` + Name string `json:"name"` + TOpsAtFp16 float64 `json:"TOpsAtFp16"` + CardHours float64 `json:"cardHours"` + CardNum int32 `json:"cardNum"` +} + type CommitHpcTaskReq struct { Name string `json:"name"` // paratera:jobName Description string `json:"description,optional"` @@ -5363,6 +5541,8 @@ type CreateAlertRuleReq struct { type AlertRulesReq struct { AlertType string `form:"alertType"` + AdapterId string `form:"adapterId,optional"` + ClusterId string `form:"clusterId,optional"` } type AlertRulesResp struct { From c0dcacb06d4412ac66f9683f1724aa792b11c9f7 Mon Sep 17 00:00:00 2001 From: tzwang Date: Wed, 24 Apr 2024 17:23:43 +0800 Subject: [PATCH 02/13] added getAiJobLog apis Former-commit-id: 5379463930bfd5ef70797e1271880a2d8c3e8516 --- api/desc/pcm.api | 3 +++ api/desc/schedule/pcm-schedule.api | 9 +++++++++ .../scheduler/service/collector/collector.go | 1 + api/internal/storeLink/modelarts.go | 4 ++++ api/internal/storeLink/octopus.go | 19 +++++++++++++++++++ api/internal/storeLink/shuguangai.go | 18 ++++++++++++++++++ go.mod | 4 ++-- go.sum | 5 +++++ 8 files changed, 61 insertions(+), 2 deletions(-) diff --git a/api/desc/pcm.api b/api/desc/pcm.api index 2c76692c..cf485b54 100644 --- a/api/desc/pcm.api +++ b/api/desc/pcm.api @@ -922,6 +922,9 @@ service pcm { @handler ScheduleGetAlgorithmsHandler get /schedule/ai/getAlgorithms/:adapterId/:resourceType/:taskType/:dataset (AiAlgorithmsReq) returns (AiAlgorithmsResp) + @handler ScheduleGetAiJobLogLogHandler + get /schedule/ai/getJobLog/:taskId/:instanceNum (AiJobLogReq) returns (AiJobLogResp) + @handler ScheduleSubmitHandler post /schedule/submit (ScheduleReq) returns (ScheduleResp) } diff --git a/api/desc/schedule/pcm-schedule.api b/api/desc/schedule/pcm-schedule.api index 3eccf3e5..d3d61990 100644 --- a/api/desc/schedule/pcm-schedule.api +++ b/api/desc/schedule/pcm-schedule.api @@ -70,4 +70,13 @@ type ( AiAlgorithmsResp { Algorithms []string `json:"algorithms"` } + + AiJobLogReq { + TaskId string `path:"taskId"` + instanceNum string `path:"instanceNum"` + } + + AiJobLogResp { + Log string `json:"log"` + } ) \ No newline at end of file diff --git a/api/internal/scheduler/service/collector/collector.go b/api/internal/scheduler/service/collector/collector.go index a20b1d36..e313baff 100644 --- a/api/internal/scheduler/service/collector/collector.go +++ b/api/internal/scheduler/service/collector/collector.go @@ -6,6 +6,7 @@ type AiCollector interface { GetResourceStats(ctx context.Context) (*ResourceStats, error) GetDatasetsSpecs(ctx context.Context) ([]*DatasetsSpecs, error) GetAlgorithms(ctx context.Context) ([]*Algorithm, error) + GetTrainingTaskLog(ctx context.Context, taskId string, instanceNum string) (string, error) } type ResourceStats struct { diff --git a/api/internal/storeLink/modelarts.go b/api/internal/storeLink/modelarts.go index 6dffc2ec..5a9bed87 100644 --- a/api/internal/storeLink/modelarts.go +++ b/api/internal/storeLink/modelarts.go @@ -162,6 +162,10 @@ func (m *ModelArtsLink) GetAlgorithms(ctx context.Context) ([]*collector.Algorit return nil, nil } +func (m *ModelArtsLink) GetTrainingTaskLog(ctx context.Context, taskId string, instanceNum string) (string, error) { + return "", nil +} + func (m *ModelArtsLink) Execute(ctx context.Context, option *option.AiOption) (interface{}, error) { err := m.GenerateSubmitParams(ctx, option) if err != nil { diff --git a/api/internal/storeLink/octopus.go b/api/internal/storeLink/octopus.go index b643c1d6..e052f637 100644 --- a/api/internal/storeLink/octopus.go +++ b/api/internal/storeLink/octopus.go @@ -337,6 +337,25 @@ func (o *OctopusLink) GetAlgorithms(ctx context.Context) ([]*collector.Algorithm return algorithms, nil } +func (o *OctopusLink) GetTrainingTaskLog(ctx context.Context, taskId string, instanceNum string) (string, error) { + instance, err := strconv.ParseInt(instanceNum, 10, 32) + if err != nil { + return "", err + } + req := &octopus.GetTrainJobLogReq{ + Platform: o.platform, + TaskId: taskId, + TaskNum: "task0", + Num: int32(instance), + } + resp, err := o.octopusRpc.GetTrainJobLog(ctx, req) + if err != nil { + return "", err + } + + return resp.Content, nil +} + func (o *OctopusLink) Execute(ctx context.Context, option *option.AiOption) (interface{}, error) { err := o.GenerateSubmitParams(ctx, option) if err != nil { diff --git a/api/internal/storeLink/shuguangai.go b/api/internal/storeLink/shuguangai.go index 53f9bf52..b07c3401 100644 --- a/api/internal/storeLink/shuguangai.go +++ b/api/internal/storeLink/shuguangai.go @@ -447,6 +447,24 @@ func (s *ShuguangAi) GetAlgorithms(ctx context.Context) ([]*collector.Algorithm, return algorithms, nil } +func (s *ShuguangAi) GetTrainingTaskLog(ctx context.Context, taskId string, instanceNum string) (string, error) { + req := &hpcAC.GetInstanceLogReq{ + TaskId: taskId, + InstanceNum: instanceNum, + LineCount: 1000, + StartLineNum: -1, + } + resp, err := s.aCRpc.GetInstanceLog(ctx, req) + if err != nil { + return "", err + } + if resp.Code != "0" { + return "", errors.New(resp.Msg) + } + + return resp.Data.Content, nil +} + func (s *ShuguangAi) Execute(ctx context.Context, option *option.AiOption) (interface{}, error) { err := s.GenerateSubmitParams(ctx, option) if err != nil { diff --git a/go.mod b/go.mod index 03670445..a46abb60 100644 --- a/go.mod +++ b/go.mod @@ -24,9 +24,9 @@ require ( github.com/robfig/cron/v3 v3.0.1 github.com/rs/zerolog v1.28.0 github.com/zeromicro/go-zero v1.6.3 - gitlink.org.cn/JointCloud/pcm-ac v0.0.0-20240407112649-e479e74b58c8 + gitlink.org.cn/JointCloud/pcm-ac v0.0.0-20240420083915-58d6e2958aeb gitlink.org.cn/JointCloud/pcm-kubernetes v0.0.0-20240301071143-347480abff2c - gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240407105727-38e45468eaa8 + gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240424085753-6899615e9142 gitlink.org.cn/JointCloud/pcm-openstack v0.0.0-20240403033338-e7edabad4203 gitlink.org.cn/JointCloud/pcm-slurm v0.0.0-20240301080743-8b94bbaf57f5 gitlink.org.cn/jcce-pcm/pcm-participant-ceph v0.0.0-20230904090036-24fc730ec87d diff --git a/go.sum b/go.sum index cdd78495..31133cce 100644 --- a/go.sum +++ b/go.sum @@ -1080,10 +1080,15 @@ github.com/zeromicro/go-zero v1.6.3 h1:OL0NnHD5LdRNDolfcK9vUkJt7K8TcBE3RkzfM8poO github.com/zeromicro/go-zero v1.6.3/go.mod h1:XZL435ZxVi9MSXXtw2MRQhHgx6OoX3++MRMOE9xU70c= gitlink.org.cn/JointCloud/pcm-ac v0.0.0-20240407112649-e479e74b58c8 h1:cX6U2gUcp/sIP3TKFv4q/1O8gp10q+M3k5Ql15yaEMI= gitlink.org.cn/JointCloud/pcm-ac v0.0.0-20240407112649-e479e74b58c8/go.mod h1:w3Nb5TNymCItQ7K3x4Q0JLuoq9OerwAzAWT2zsPE9Xo= +gitlink.org.cn/JointCloud/pcm-ac v0.0.0-20240420083915-58d6e2958aeb h1:k6mNEWKp+haQUaK2dWs/rI9OKgzJHY1/9KNKuBDN0Vw= +gitlink.org.cn/JointCloud/pcm-ac v0.0.0-20240420083915-58d6e2958aeb/go.mod h1:w3Nb5TNymCItQ7K3x4Q0JLuoq9OerwAzAWT2zsPE9Xo= gitlink.org.cn/JointCloud/pcm-kubernetes v0.0.0-20240301071143-347480abff2c h1:2Wl/hvaSFjh6fmCSIQhjkr9llMRREQeqcXNLZ/HPY18= gitlink.org.cn/JointCloud/pcm-kubernetes v0.0.0-20240301071143-347480abff2c/go.mod h1:lSRfGs+PxFvw7CcndHWRd6UlLlGrZn0b0hp5cfaMNGw= gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240407105727-38e45468eaa8 h1:jdwYydJxYPlfIS9yZvnNX1w08aJGYWq5ADD5EXLW3+Q= gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240407105727-38e45468eaa8/go.mod h1:QOD5+/l2D+AYBjF2h5T0mdJyfGAmF78QmeKdbBXbjLQ= +gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240422093351-5b8bac8bb953 h1:45omfrELx1Ealvs20NwFgdubCUnTyiatBAQyUwG6aAk= +gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240422093351-5b8bac8bb953/go.mod h1:QOD5+/l2D+AYBjF2h5T0mdJyfGAmF78QmeKdbBXbjLQ= +gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240424085753-6899615e9142/go.mod h1:QOD5+/l2D+AYBjF2h5T0mdJyfGAmF78QmeKdbBXbjLQ= gitlink.org.cn/JointCloud/pcm-openstack v0.0.0-20240403033338-e7edabad4203 h1:s6PsZ1+bev294IWdZRlV7mnOwI1+UzFcldVW/BqhQzI= gitlink.org.cn/JointCloud/pcm-openstack v0.0.0-20240403033338-e7edabad4203/go.mod h1:i2rrbMQ+Fve345BY9Heh4MUqVTAimZQElQhzzRee5B8= gitlink.org.cn/JointCloud/pcm-slurm v0.0.0-20240301080743-8b94bbaf57f5 h1:+/5vnzkJBfMRnya1NrhOzlroUtRa5ePiYbPKlHLoLV0= From 8fd635b4a7bdf58a8d9fb39362523e7d69b10e36 Mon Sep 17 00:00:00 2001 From: zhangwei <894646498@qq.com> Date: Thu, 25 Apr 2024 10:09:57 +0800 Subject: [PATCH 03/13] query task num Former-commit-id: 2e88ecb4d707b7d9f662146415a6999610fe5e53 --- api/desc/monitoring/pcm-monitoring.api | 14 +++++++- api/desc/pcm.api | 13 +++++--- .../handler/monitoring/tasknumhandler.go | 25 ++++++++++++++ api/internal/handler/routes.go | 7 +++- .../logic/monitoring/alertruleslogic.go | 2 +- .../logic/monitoring/createalertrulelogic.go | 2 ++ api/internal/logic/monitoring/tasknumlogic.go | 33 +++++++++++++++++++ api/internal/types/types.go | 13 ++++++++ 8 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 api/internal/handler/monitoring/tasknumhandler.go create mode 100644 api/internal/logic/monitoring/tasknumlogic.go diff --git a/api/desc/monitoring/pcm-monitoring.api b/api/desc/monitoring/pcm-monitoring.api index 06f84557..cdd39fdc 100644 --- a/api/desc/monitoring/pcm-monitoring.api +++ b/api/desc/monitoring/pcm-monitoring.api @@ -58,4 +58,16 @@ type ( type SyncClusterAlertReq { AlertRecordsMap map[string]interface{} `json:"alertRecordsMap"` -} \ No newline at end of file +} + +type ( + taskNumReq { + clusterId string `form:"clusterId"` + } + taskNumResp { + current int `json:"current"` + today int `json:"today"` + history int `json:"history"` + failed int `json:"failed"` + } +) \ No newline at end of file diff --git a/api/desc/pcm.api b/api/desc/pcm.api index 2c76692c..51e5502c 100644 --- a/api/desc/pcm.api +++ b/api/desc/pcm.api @@ -132,11 +132,11 @@ service pcm { @doc "paging queries the task list" @handler pageListTaskHandler - get /core/task/list (pageTaskReq) returns(PageResult) + get /core/task/list (pageTaskReq) returns (PageResult) @doc "Statistical task status" @handler countTaskStatus - get /core/task/countTaskStatus () returns(TaskStatusResp) + get /core/task/countTaskStatus () returns (TaskStatusResp) } //hpc二级接口 @@ -210,7 +210,7 @@ service pcm { @doc "Create cloud computing common tasks" @handler commitGeneralTask - post /cloud/task/create (GeneralTaskReq) returns() + post /cloud/task/create (GeneralTaskReq) returns () } //智算二级接口 @@ -975,7 +975,7 @@ service pcm { @doc "alert rules" @handler alertRulesHandler - get /monitoring/alert/rule (AlertRulesReq)returns (AlertRulesResp) + get /monitoring/alert/rule (AlertRulesReq) returns (AlertRulesResp) @doc "cluster resource load" @handler clustersLoadHandler @@ -991,5 +991,8 @@ service pcm { @doc "Synchronize Cluster alert Information" @handler syncClusterAlertHandler - post /core/syncClusterAlert (SyncClusterAlertReq) + post /monitoring/syncClusterAlert (SyncClusterAlertReq) + + @handler taskNumHandler + get /monitoring/task/num (taskNumReq) returns (taskNumResp) } \ No newline at end of file diff --git a/api/internal/handler/monitoring/tasknumhandler.go b/api/internal/handler/monitoring/tasknumhandler.go new file mode 100644 index 00000000..4b7751bc --- /dev/null +++ b/api/internal/handler/monitoring/tasknumhandler.go @@ -0,0 +1,25 @@ +package monitoring + +import ( + "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/repository/result" + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/logic/monitoring" + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/svc" + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/types" +) + +func TaskNumHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.TaskNumReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := monitoring.NewTaskNumLogic(r.Context(), svcCtx) + resp, err := l.TaskNum(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/api/internal/handler/routes.go b/api/internal/handler/routes.go index a68efc58..9fe292b5 100644 --- a/api/internal/handler/routes.go +++ b/api/internal/handler/routes.go @@ -1244,9 +1244,14 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { }, { Method: http.MethodPost, - Path: "/core/syncClusterAlert", + Path: "/monitoring/syncClusterAlert", Handler: monitoring.SyncClusterAlertHandler(serverCtx), }, + { + Method: http.MethodGet, + Path: "/monitoring/task/num", + Handler: monitoring.TaskNumHandler(serverCtx), + }, }, rest.WithPrefix("/pcm/v1"), ) diff --git a/api/internal/logic/monitoring/alertruleslogic.go b/api/internal/logic/monitoring/alertruleslogic.go index d7d2dde8..7c63dcff 100644 --- a/api/internal/logic/monitoring/alertruleslogic.go +++ b/api/internal/logic/monitoring/alertruleslogic.go @@ -29,7 +29,7 @@ func (l *AlertRulesLogic) AlertRules(req *types.AlertRulesReq) (resp *types.Aler var alertRules []types.AlertRule sql := fmt.Sprintf("SELECT ar.*,GROUP_CONCAT(tc.`name` ORDER BY tc.`name` ASC SEPARATOR ',') as cluster_name FROM alert_rule ar JOIN t_cluster tc ON ar.cluster_id = tc.id WHERE ar.alert_type = %s AND ar.deleted_at IS NULL AND tc.deleted_at IS NULL GROUP BY ar.id", req.AlertType) if req.AdapterId != "" { - sql = fmt.Sprintf("SELECT tar.*,GROUP_CONCAT( tc.`name` ORDER BY tc.`name` ASC SEPARATOR ',' ) AS cluster_name FROM talert_rule ar JOIN t_cluster tc ON ar.cluster_id = tc.id JOIN t_adapter ta ON ta.id = tc.adapter_id WHERE tar.alert_type = %s AND ta.id = %s AND ar.deleted_at IS NULL AND tc.deleted_at IS NULL GROUP BY tar.id", req.AlertType, req.AdapterId) + sql = fmt.Sprintf("SELECT ar.*,GROUP_CONCAT( tc.`name` ORDER BY tc.`name` ASC SEPARATOR ',' ) AS cluster_name FROM alert_rule ar JOIN t_cluster tc ON ar.cluster_id = tc.id JOIN t_adapter ta ON ta.id = tc.adapter_id WHERE ar.alert_type = %s AND ta.id = %s AND ar.deleted_at IS NULL AND tc.deleted_at IS NULL GROUP BY ar.id", req.AlertType, req.AdapterId) } if req.ClusterId != "" { sql = fmt.Sprintf("SELECT ar.*,GROUP_CONCAT(tc.`name` ORDER BY tc.`name` ASC SEPARATOR ',') as cluster_name FROM alert_rule ar JOIN t_cluster tc ON ar.cluster_id = tc.id WHERE ar.alert_type = %s AND ar.cluster_id = %s AND ar.deleted_at IS NULL AND tc.deleted_at IS NULL GROUP BY ar.id", req.AlertType, req.ClusterId) diff --git a/api/internal/logic/monitoring/createalertrulelogic.go b/api/internal/logic/monitoring/createalertrulelogic.go index fadf50c3..c9685c98 100644 --- a/api/internal/logic/monitoring/createalertrulelogic.go +++ b/api/internal/logic/monitoring/createalertrulelogic.go @@ -11,6 +11,7 @@ import ( v12 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/json" + "strconv" ) type CreateAlertRuleLogic struct { @@ -38,6 +39,7 @@ func (l *CreateAlertRuleLogic) CreateAlertRule(req *types.CreateAlertRuleReq) er // save to db var alertRule models.AlertRule tool.Convert(req, &alertRule) + alertRule.ClusterId, _ = strconv.ParseInt(req.CLusterId, 10, 64) alertRule.Id = tool.GenSnowflakeID() tx := l.svcCtx.DbEngin.Save(&alertRule) if tx.Error != nil { diff --git a/api/internal/logic/monitoring/tasknumlogic.go b/api/internal/logic/monitoring/tasknumlogic.go new file mode 100644 index 00000000..0b7f1659 --- /dev/null +++ b/api/internal/logic/monitoring/tasknumlogic.go @@ -0,0 +1,33 @@ +package monitoring + +import ( + "context" + + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/svc" + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type TaskNumLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewTaskNumLogic(ctx context.Context, svcCtx *svc.ServiceContext) *TaskNumLogic { + return &TaskNumLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *TaskNumLogic) TaskNum(req *types.TaskNumReq) (resp *types.TaskNumResp, err error) { + resp = &types.TaskNumResp{} + l.svcCtx.DbEngin.Raw("SELECT COUNT(id) from task_cloud where cluster_id = ? and status = 'running'", req.ClusterId).Scan(resp.Current) + l.svcCtx.DbEngin.Raw("SELECT COUNT(id) from task_cloud where cluster_id = '' and DATE(start_time) = CURDATE()", req.ClusterId).Scan(resp.Today) + l.svcCtx.DbEngin.Raw("SELECT COUNT(id) from task_cloud where cluster_id = ?", req.ClusterId).Scan(resp.History) + l.svcCtx.DbEngin.Raw("SELECT COUNT(id) from task_cloud where cluster_id = ? and status = 'failed'", req.ClusterId).Scan(resp.Failed) + return resp, nil +} diff --git a/api/internal/types/types.go b/api/internal/types/types.go index 59dd185d..b4e691db 100644 --- a/api/internal/types/types.go +++ b/api/internal/types/types.go @@ -5548,6 +5548,8 @@ type CreateAlertRuleReq struct { type AlertRulesReq struct { AlertType string `form:"alertType"` + AdapterId string `form:"adapterId,optional"` + ClusterId string `form:"clusterId,optional"` } type AlertRulesResp struct { @@ -5589,3 +5591,14 @@ type AlertListResp struct { type SyncClusterAlertReq struct { AlertRecordsMap map[string]interface{} `json:"alertRecordsMap"` } + +type TaskNumReq struct { + ClusterId string `form:"clusterId"` +} + +type TaskNumResp struct { + Current int `json:"current"` + Today int `json:"today"` + History int `json:"history"` + Failed int `json:"failed"` +} From 189c833f5da3e8c8097ea58cc4f4fda261a29895 Mon Sep 17 00:00:00 2001 From: tzwang Date: Thu, 25 Apr 2024 16:03:13 +0800 Subject: [PATCH 04/13] generate getJobLog api Former-commit-id: cf3cfd9b6f4ced4a41800863238490a797964c65 --- api/internal/handler/routes.go | 5 +++++ api/internal/types/types.go | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/api/internal/handler/routes.go b/api/internal/handler/routes.go index a68efc58..0138989a 100644 --- a/api/internal/handler/routes.go +++ b/api/internal/handler/routes.go @@ -1145,6 +1145,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/schedule/ai/getAlgorithms/:adapterId/:resourceType/:taskType/:dataset", Handler: schedule.ScheduleGetAlgorithmsHandler(serverCtx), }, + { + Method: http.MethodGet, + Path: "/schedule/ai/getJobLog/:taskId/:instanceNum", + Handler: schedule.ScheduleGetAiJobLogLogHandler(serverCtx), + }, { Method: http.MethodPost, Path: "/schedule/submit", diff --git a/api/internal/types/types.go b/api/internal/types/types.go index 59dd185d..53285b9b 100644 --- a/api/internal/types/types.go +++ b/api/internal/types/types.go @@ -5535,6 +5535,15 @@ type AiAlgorithmsResp struct { Algorithms []string `json:"algorithms"` } +type AiJobLogReq struct { + TaskId string `path:"taskId"` + InstanceNum string `path:"instanceNum"` +} + +type AiJobLogResp struct { + Log string `json:"log"` +} + type CreateAlertRuleReq struct { CLusterId string `json:"clusterId"` ClusterName string `json:"clusterName"` From 1281f6d61b80f7686b4f9e141b7cf173d36a8b8b Mon Sep 17 00:00:00 2001 From: tzwang Date: Thu, 25 Apr 2024 16:04:22 +0800 Subject: [PATCH 05/13] generate getJobLog api Former-commit-id: 922c4149bb05dbe2b0881db2fd3e2646f5cb0d08 --- .../schedule/schedulegetaijoblogloglogic.go | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 api/internal/logic/schedule/schedulegetaijoblogloglogic.go diff --git a/api/internal/logic/schedule/schedulegetaijoblogloglogic.go b/api/internal/logic/schedule/schedulegetaijoblogloglogic.go new file mode 100644 index 00000000..e2bb9e5c --- /dev/null +++ b/api/internal/logic/schedule/schedulegetaijoblogloglogic.go @@ -0,0 +1,30 @@ +package schedule + +import ( + "context" + + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/svc" + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type ScheduleGetAiJobLogLogLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewScheduleGetAiJobLogLogLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ScheduleGetAiJobLogLogLogic { + return &ScheduleGetAiJobLogLogLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *ScheduleGetAiJobLogLogLogic) ScheduleGetAiJobLogLog(req *types.AiJobLogReq) (resp *types.AiJobLogResp, err error) { + // todo: add your logic here and delete this line + + return +} From f3ce064dae88bba7f35416d6d61e186954dc3234 Mon Sep 17 00:00:00 2001 From: tzwang Date: Thu, 25 Apr 2024 16:51:59 +0800 Subject: [PATCH 06/13] updated getJobLog api logic Former-commit-id: ff312781e1ec873ab7a6637cead3f466809cd001 --- api/desc/pcm.api | 2 +- api/desc/schedule/pcm-schedule.api | 2 ++ api/internal/handler/routes.go | 2 +- .../logic/schedule/schedulegetaijoblogloglogic.go | 10 ++++++++-- api/internal/types/types.go | 2 ++ 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/api/desc/pcm.api b/api/desc/pcm.api index cf485b54..26baa9c8 100644 --- a/api/desc/pcm.api +++ b/api/desc/pcm.api @@ -923,7 +923,7 @@ service pcm { get /schedule/ai/getAlgorithms/:adapterId/:resourceType/:taskType/:dataset (AiAlgorithmsReq) returns (AiAlgorithmsResp) @handler ScheduleGetAiJobLogLogHandler - get /schedule/ai/getJobLog/:taskId/:instanceNum (AiJobLogReq) returns (AiJobLogResp) + get /schedule/ai/getJobLog/:adapterId/:taskId/:instanceNum (AiJobLogReq) returns (AiJobLogResp) @handler ScheduleSubmitHandler post /schedule/submit (ScheduleReq) returns (ScheduleResp) diff --git a/api/desc/schedule/pcm-schedule.api b/api/desc/schedule/pcm-schedule.api index d3d61990..02783746 100644 --- a/api/desc/schedule/pcm-schedule.api +++ b/api/desc/schedule/pcm-schedule.api @@ -72,6 +72,8 @@ type ( } AiJobLogReq { + AdapterId string `path:"adapterId"` + ClusterId string `path:"clusterId"` TaskId string `path:"taskId"` instanceNum string `path:"instanceNum"` } diff --git a/api/internal/handler/routes.go b/api/internal/handler/routes.go index 0138989a..a3ade3e1 100644 --- a/api/internal/handler/routes.go +++ b/api/internal/handler/routes.go @@ -1147,7 +1147,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { }, { Method: http.MethodGet, - Path: "/schedule/ai/getJobLog/:taskId/:instanceNum", + Path: "/schedule/ai/getJobLog/:adapterId/:taskId/:instanceNum", Handler: schedule.ScheduleGetAiJobLogLogHandler(serverCtx), }, { diff --git a/api/internal/logic/schedule/schedulegetaijoblogloglogic.go b/api/internal/logic/schedule/schedulegetaijoblogloglogic.go index e2bb9e5c..da5a0c7a 100644 --- a/api/internal/logic/schedule/schedulegetaijoblogloglogic.go +++ b/api/internal/logic/schedule/schedulegetaijoblogloglogic.go @@ -24,7 +24,13 @@ func NewScheduleGetAiJobLogLogLogic(ctx context.Context, svcCtx *svc.ServiceCont } func (l *ScheduleGetAiJobLogLogLogic) ScheduleGetAiJobLogLog(req *types.AiJobLogReq) (resp *types.AiJobLogResp, err error) { - // todo: add your logic here and delete this line + resp = &types.AiJobLogResp{} - return + log, err := l.svcCtx.Scheduler.AiService.AiCollectorAdapterMap[req.AdapterId][req.ClusterId].GetTrainingTaskLog(l.ctx, req.TaskId, req.InstanceNum) + if err != nil { + return nil, err + } + + resp.Log = log + return resp, nil } diff --git a/api/internal/types/types.go b/api/internal/types/types.go index 53285b9b..52164d6e 100644 --- a/api/internal/types/types.go +++ b/api/internal/types/types.go @@ -5536,6 +5536,8 @@ type AiAlgorithmsResp struct { } type AiJobLogReq struct { + AdapterId string `path:"adapterId"` + ClusterId string `path:"clusterId"` TaskId string `path:"taskId"` InstanceNum string `path:"instanceNum"` } From b919452c437893e7beec85b9e7ca7769e0a4ddf3 Mon Sep 17 00:00:00 2001 From: tzwang Date: Thu, 25 Apr 2024 18:08:11 +0800 Subject: [PATCH 07/13] added getJobLog api handler Former-commit-id: d03433d970f407855b183f46bdeebc9cabddfda6 --- .../schedule/schedulegetaijoblogloghandler.go | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 api/internal/handler/schedule/schedulegetaijoblogloghandler.go diff --git a/api/internal/handler/schedule/schedulegetaijoblogloghandler.go b/api/internal/handler/schedule/schedulegetaijoblogloghandler.go new file mode 100644 index 00000000..9eecc66d --- /dev/null +++ b/api/internal/handler/schedule/schedulegetaijoblogloghandler.go @@ -0,0 +1,28 @@ +package schedule + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/logic/schedule" + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/svc" + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/types" +) + +func ScheduleGetAiJobLogLogHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.AiJobLogReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := schedule.NewScheduleGetAiJobLogLogLogic(r.Context(), svcCtx) + resp, err := l.ScheduleGetAiJobLogLog(&req) + if err != nil { + httpx.ErrorCtx(r.Context(), w, err) + } else { + httpx.OkJsonCtx(r.Context(), w, resp) + } + } +} From 10c719fc01eca23538c2fc4ba6a4b1dad488050f Mon Sep 17 00:00:00 2001 From: tzwang Date: Thu, 25 Apr 2024 18:28:30 +0800 Subject: [PATCH 08/13] updated getAiJobLog handler Former-commit-id: caaa3466f447309bf339b31ad8cf3323ffd9f9b1 --- api/desc/pcm.api | 2 +- api/internal/svc/servicecontext.go | 4 ---- go.sum | 7 +------ 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/api/desc/pcm.api b/api/desc/pcm.api index 26baa9c8..12d338a0 100644 --- a/api/desc/pcm.api +++ b/api/desc/pcm.api @@ -923,7 +923,7 @@ service pcm { get /schedule/ai/getAlgorithms/:adapterId/:resourceType/:taskType/:dataset (AiAlgorithmsReq) returns (AiAlgorithmsResp) @handler ScheduleGetAiJobLogLogHandler - get /schedule/ai/getJobLog/:adapterId/:taskId/:instanceNum (AiJobLogReq) returns (AiJobLogResp) + get /schedule/ai/getJobLog/:adapterId/:clusterId/:taskId/:instanceNum (AiJobLogReq) returns (AiJobLogResp) @handler ScheduleSubmitHandler post /schedule/submit (ScheduleReq) returns (ScheduleResp) diff --git a/api/internal/svc/servicecontext.go b/api/internal/svc/servicecontext.go index 0c73eb17..1aca2ac4 100644 --- a/api/internal/svc/servicecontext.go +++ b/api/internal/svc/servicecontext.go @@ -117,10 +117,6 @@ func NewServiceContext(c config.Config) *ServiceContext { }) // scheduler - //octopusRpc := octopusclient.NewOctopus(zrpc.MustNewClient(c.OctopusRpcConf)) - //aCRpc := hpcacclient.NewHpcAC(zrpc.MustNewClient(c.ACRpcConf)) - //modelArtsRpc := modelartsservice.NewModelArtsService(zrpc.MustNewClient(c.ModelArtsRpcConf)) - //modelArtsImgRpc := imagesservice.NewImagesService(zrpc.MustNewClient(c.ModelArtsImgRpcConf)) storage := &database.AiStorage{DbEngin: dbEngin} aiService, err := service.NewAiService(&c, storage) if err != nil { diff --git a/go.sum b/go.sum index 31133cce..6f886672 100644 --- a/go.sum +++ b/go.sum @@ -1078,16 +1078,11 @@ github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7 github.com/zeromicro/go-zero v1.5.1/go.mod h1:bGYm4XWsGN9GhDsO2O2BngpVoWjf3Eog2a5hUOMhlXs= github.com/zeromicro/go-zero v1.6.3 h1:OL0NnHD5LdRNDolfcK9vUkJt7K8TcBE3RkzfM8poOVw= github.com/zeromicro/go-zero v1.6.3/go.mod h1:XZL435ZxVi9MSXXtw2MRQhHgx6OoX3++MRMOE9xU70c= -gitlink.org.cn/JointCloud/pcm-ac v0.0.0-20240407112649-e479e74b58c8 h1:cX6U2gUcp/sIP3TKFv4q/1O8gp10q+M3k5Ql15yaEMI= -gitlink.org.cn/JointCloud/pcm-ac v0.0.0-20240407112649-e479e74b58c8/go.mod h1:w3Nb5TNymCItQ7K3x4Q0JLuoq9OerwAzAWT2zsPE9Xo= gitlink.org.cn/JointCloud/pcm-ac v0.0.0-20240420083915-58d6e2958aeb h1:k6mNEWKp+haQUaK2dWs/rI9OKgzJHY1/9KNKuBDN0Vw= gitlink.org.cn/JointCloud/pcm-ac v0.0.0-20240420083915-58d6e2958aeb/go.mod h1:w3Nb5TNymCItQ7K3x4Q0JLuoq9OerwAzAWT2zsPE9Xo= gitlink.org.cn/JointCloud/pcm-kubernetes v0.0.0-20240301071143-347480abff2c h1:2Wl/hvaSFjh6fmCSIQhjkr9llMRREQeqcXNLZ/HPY18= gitlink.org.cn/JointCloud/pcm-kubernetes v0.0.0-20240301071143-347480abff2c/go.mod h1:lSRfGs+PxFvw7CcndHWRd6UlLlGrZn0b0hp5cfaMNGw= -gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240407105727-38e45468eaa8 h1:jdwYydJxYPlfIS9yZvnNX1w08aJGYWq5ADD5EXLW3+Q= -gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240407105727-38e45468eaa8/go.mod h1:QOD5+/l2D+AYBjF2h5T0mdJyfGAmF78QmeKdbBXbjLQ= -gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240422093351-5b8bac8bb953 h1:45omfrELx1Ealvs20NwFgdubCUnTyiatBAQyUwG6aAk= -gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240422093351-5b8bac8bb953/go.mod h1:QOD5+/l2D+AYBjF2h5T0mdJyfGAmF78QmeKdbBXbjLQ= +gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240424085753-6899615e9142 h1:+po0nesBDSWsgCySBG7eEXk7i9Ytd58wqvjL1M9y6d8= gitlink.org.cn/JointCloud/pcm-octopus v0.0.0-20240424085753-6899615e9142/go.mod h1:QOD5+/l2D+AYBjF2h5T0mdJyfGAmF78QmeKdbBXbjLQ= gitlink.org.cn/JointCloud/pcm-openstack v0.0.0-20240403033338-e7edabad4203 h1:s6PsZ1+bev294IWdZRlV7mnOwI1+UzFcldVW/BqhQzI= gitlink.org.cn/JointCloud/pcm-openstack v0.0.0-20240403033338-e7edabad4203/go.mod h1:i2rrbMQ+Fve345BY9Heh4MUqVTAimZQElQhzzRee5B8= From f0a707689c1e2a96b2a3562dcec9ec797c7aedae Mon Sep 17 00:00:00 2001 From: tzwang Date: Fri, 26 Apr 2024 10:38:49 +0800 Subject: [PATCH 09/13] updated getJobLog api Former-commit-id: 23ffca2a8dce387c765515b27628b7116f84ef51 --- api/internal/handler/routes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/internal/handler/routes.go b/api/internal/handler/routes.go index a3ade3e1..5402a03d 100644 --- a/api/internal/handler/routes.go +++ b/api/internal/handler/routes.go @@ -1147,7 +1147,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { }, { Method: http.MethodGet, - Path: "/schedule/ai/getJobLog/:adapterId/:taskId/:instanceNum", + Path: "/schedule/ai/getJobLog/:adapterId/:clusterId/:taskId/:instanceNum", Handler: schedule.ScheduleGetAiJobLogLogHandler(serverCtx), }, { From 2210db4d3cfac5086bb3b25d3c16fd0c6d7d3a8f Mon Sep 17 00:00:00 2001 From: zhangwei <894646498@qq.com> Date: Fri, 26 Apr 2024 16:27:26 +0800 Subject: [PATCH 10/13] adapter info Former-commit-id: c717f0f1d0eabd7121ed7d43a8e22e82603b8d64 --- api/desc/monitoring/pcm-monitoring.api | 10 ++++++ api/desc/pcm.api | 3 ++ .../handler/monitoring/adapterinfohandler.go | 25 +++++++++++++++ api/internal/handler/routes.go | 5 +++ .../logic/monitoring/adapterinfologic.go | 31 +++++++++++++++++++ api/internal/types/types.go | 9 ++++++ 6 files changed, 83 insertions(+) create mode 100644 api/internal/handler/monitoring/adapterinfohandler.go create mode 100644 api/internal/logic/monitoring/adapterinfologic.go diff --git a/api/desc/monitoring/pcm-monitoring.api b/api/desc/monitoring/pcm-monitoring.api index cdd39fdc..8dc7cdd9 100644 --- a/api/desc/monitoring/pcm-monitoring.api +++ b/api/desc/monitoring/pcm-monitoring.api @@ -70,4 +70,14 @@ type ( history int `json:"history"` failed int `json:"failed"` } +) + +type ( + adapterInfoReq{ + clusterId string `form:"clusterId"` + } + adapterInfoResp{ + name string `json:"name"` + version string `json:"version"` + } ) \ No newline at end of file diff --git a/api/desc/pcm.api b/api/desc/pcm.api index 51e5502c..de215d2f 100644 --- a/api/desc/pcm.api +++ b/api/desc/pcm.api @@ -995,4 +995,7 @@ service pcm { @handler taskNumHandler get /monitoring/task/num (taskNumReq) returns (taskNumResp) + + @handler adapterInfoHandler + get /monitoring/adapter/info (adapterInfoReq) returns (adapterInfoResp) } \ No newline at end of file diff --git a/api/internal/handler/monitoring/adapterinfohandler.go b/api/internal/handler/monitoring/adapterinfohandler.go new file mode 100644 index 00000000..4869213f --- /dev/null +++ b/api/internal/handler/monitoring/adapterinfohandler.go @@ -0,0 +1,25 @@ +package monitoring + +import ( + "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/repository/result" + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/logic/monitoring" + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/svc" + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/types" +) + +func AdapterInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.AdapterInfoReq + if err := httpx.Parse(r, &req); err != nil { + httpx.ErrorCtx(r.Context(), w, err) + return + } + + l := monitoring.NewAdapterInfoLogic(r.Context(), svcCtx) + resp, err := l.AdapterInfo(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/api/internal/handler/routes.go b/api/internal/handler/routes.go index 9fe292b5..599422d5 100644 --- a/api/internal/handler/routes.go +++ b/api/internal/handler/routes.go @@ -1252,6 +1252,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/monitoring/task/num", Handler: monitoring.TaskNumHandler(serverCtx), }, + { + Method: http.MethodGet, + Path: "/monitoring/adapter/info", + Handler: monitoring.AdapterInfoHandler(serverCtx), + }, }, rest.WithPrefix("/pcm/v1"), ) diff --git a/api/internal/logic/monitoring/adapterinfologic.go b/api/internal/logic/monitoring/adapterinfologic.go new file mode 100644 index 00000000..1afc91e4 --- /dev/null +++ b/api/internal/logic/monitoring/adapterinfologic.go @@ -0,0 +1,31 @@ +package monitoring + +import ( + "context" + + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/svc" + "gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type AdapterInfoLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewAdapterInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdapterInfoLogic { + return &AdapterInfoLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *AdapterInfoLogic) AdapterInfo(req *types.AdapterInfoReq) (resp *types.AdapterInfoResp, err error) { + // todo: add your logic here and delete this line + resp = &types.AdapterInfoResp{} + l.svcCtx.DbEngin.Raw("select ta.name , ta.version from t_adapter ta,t_cluster tc where tc.id = ? and tc.adapter_id = ta.id", req.ClusterId).Scan(resp) + return resp, nil +} diff --git a/api/internal/types/types.go b/api/internal/types/types.go index b4e691db..ab192993 100644 --- a/api/internal/types/types.go +++ b/api/internal/types/types.go @@ -5602,3 +5602,12 @@ type TaskNumResp struct { History int `json:"history"` Failed int `json:"failed"` } + +type AdapterInfoReq struct { + ClusterId string `form:"clusterId"` +} + +type AdapterInfoResp struct { + Name string `json:"name"` + Version string `json:"version"` +} From d8e07f0055bd349c760313a4cd9d22223723e3df Mon Sep 17 00:00:00 2001 From: zhouqunjie Date: Sun, 28 Apr 2024 15:22:30 +0800 Subject: [PATCH 11/13] deploy doc Former-commit-id: 961558d9f1095d9a921c4e163ef32ff0e272263a --- docs/pcm_deploy.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 docs/pcm_deploy.md diff --git a/docs/pcm_deploy.md b/docs/pcm_deploy.md new file mode 100644 index 00000000..e59f3077 --- /dev/null +++ b/docs/pcm_deploy.md @@ -0,0 +1,38 @@ + + +## 1 安装部署kubekey +通过以下的命令,可以下载 KubeKey 的最新版本。您可以更改命令中的版本号来下载特定的版本。 + +``` +export KKZONE=cn +curl -sfL https://get-kk.kubesphere.io | VERSION=v3.0.7 sh - +``` + +## 2 安装部署k8s集群 +``` +./kk create cluster +``` +执行可能会提示部分软件未安装,直接yum安装即可 +![输入图片说明](/imgs/2024-04-28/qF082JVaumRARK1J.png) +然后重新执行创建集群命令,执行成功后可以验证环境 +![输入图片说明](/imgs/2024-04-28/FoVNPbwm1pnt839Z.png) + +## 3 部署鉴权、pcm-coordinator、前端服务 +鉴权: +kubectl apply -f pcm-auth.yaml +C端: +kubectl apply -f pcm-core-api.yaml +kubectl apply -f pcm-core-rpc.yaml +前端: +kubectl apply -f pcm-rip.yaml + +## 4 配置驱动器、集群信息 +新建一个适配器,配置成功后可以获取到对应的adapterId +![输入图片说明](/imgs/2024-04-28/Dtu4KC835jSfcf5R.png) +将对应的id填写到对应的P端配置信息中(configmap 内容) +![输入图片说明](/imgs/2024-04-28/zuFWMVKAycNlPXOF.png) +## 5 部署P端服务 +P端: +kubectl apply -f pcm-hpc.yaml +kubectl apply -f pcm-kubernetes.yaml +## 7.系统使用 \ No newline at end of file From 9ed059527e8e35773bffc3ce22ea218df67de474 Mon Sep 17 00:00:00 2001 From: zhouqunjie Date: Sun, 28 Apr 2024 15:29:41 +0800 Subject: [PATCH 12/13] deploy doc Former-commit-id: 90a7d4a91426dc383319c9ee3e87b93420025728 --- docs/pcm_deploy.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/pcm_deploy.md b/docs/pcm_deploy.md index e59f3077..f0bd5e46 100644 --- a/docs/pcm_deploy.md +++ b/docs/pcm_deploy.md @@ -18,6 +18,9 @@ curl -sfL https://get-kk.kubesphere.io | VERSION=v3.0.7 sh - ![输入图片说明](/imgs/2024-04-28/FoVNPbwm1pnt839Z.png) ## 3 部署鉴权、pcm-coordinator、前端服务 + +yaml文件下载链接:https://pan.baidu.com/s/1VU1zE2xcFkrz9Hz2MkgDaQ + 鉴权: kubectl apply -f pcm-auth.yaml C端: From fc88ab014af37843e1c63ca4cfc97bcaddba23d5 Mon Sep 17 00:00:00 2001 From: zhouqunjie <450705171@qq.com> Date: Mon, 29 Apr 2024 10:17:26 +0800 Subject: [PATCH 13/13] ADD file via upload Former-commit-id: 5b67f6b63a0ed0d69d91aace24e70aa92227d499 --- deploy/pcm-yaml.zip | Bin 0 -> 9690 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 deploy/pcm-yaml.zip diff --git a/deploy/pcm-yaml.zip b/deploy/pcm-yaml.zip new file mode 100644 index 0000000000000000000000000000000000000000..2deae5923859a18e05965434816efc0150ddb04f GIT binary patch literal 9690 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 Do)Rpd literal 0 HcmV?d00001