diff --git a/docs/开源社区与云脑平台对接方案.docx b/docs/开源社区与云脑平台对接方案.docx index 8db5c651a..20966e992 100755 Binary files a/docs/开源社区与云脑平台对接方案.docx and b/docs/开源社区与云脑平台对接方案.docx differ diff --git a/models/cloudbrain.go b/models/cloudbrain.go old mode 100644 new mode 100755 index 997cf41cf..dffb4dd0c --- a/models/cloudbrain.go +++ b/models/cloudbrain.go @@ -1,6 +1,7 @@ package models import ( + "code.gitea.io/gitea/modules/log" "encoding/json" "errors" "fmt" @@ -27,6 +28,7 @@ type Cloudbrain struct { Status string `xorm:"INDEX"` UserID int64 `xorm:"INDEX"` RepoID int64 `xorm:"INDEX"` + SubTaskName string `xorm:"INDEX"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` @@ -52,6 +54,17 @@ type TaskRole struct { Command string `json:"command"` NeedIBDevice bool `json:"needIBDevice"` IsMainRole bool `json:"isMainRole"` + UseNNI bool `json:"useNNI"` +} + +type StHostPath struct { + Path string `json:"path"` + MountPath string `json:"mountPath"` + ReadOnly bool `json:"readOnly"` +} + +type Volume struct { + HostPath StHostPath `json:"hostPath"` } type CreateJobParams struct { @@ -60,6 +73,7 @@ type CreateJobParams struct { GpuType string `json:"gpuType"` Image string `json:"image"` TaskRoles []TaskRole `json:"taskRoles"` + Volumes []Volume `json:"volumes"` } type CreateJobResult struct { @@ -74,6 +88,12 @@ type GetJobResult struct { Payload map[string]interface{} `json:"payload"` } +type GetImagesResult struct { + Code string `json:"code"` + Msg string `json:"msg"` + Payload map[string]ImageInfo `json:"payload"` +} + type CloudbrainsOptions struct { ListOptions RepoID int64 // include all repos if empty @@ -173,6 +193,36 @@ func ConvertToJobResultPayload(input map[string]interface{}) (JobResultPayload, return jobResultPayload, err } +type ImagesResultPayload struct { + Images []struct { + ID int `json:"id"` + Name string `json:"name"` + Place string `json:"place"` + Description string `json:"description"` + Provider string `json:"provider"` + Createtime string `json:"createtime"` + Remark string `json:"remark"` + } `json:"taskStatuses"` +} +type ImageInfo struct { + ID int `json:"id"` + Name string `json:"name"` + Place string `json:"place"` + Description string `json:"description"` + Provider string `json:"provider"` + Createtime string `json:"createtime"` + Remark string `json:"remark"` +} + + +func ConvertToImagesResultPayload(input map[string]ImageInfo) (ImagesResultPayload, error) { + for _,info := range input { + log.Info(info.Name) + } + var res ImagesResultPayload + return res, nil +} + func Cloudbrains(opts *CloudbrainsOptions) ([]*Cloudbrain, int64, error) { sess := x.NewSession() defer sess.Close() diff --git a/modules/cloudbrain/cloudbrain.go b/modules/cloudbrain/cloudbrain.go index 96a6f2957..6639797c0 100755 --- a/modules/cloudbrain/cloudbrain.go +++ b/modules/cloudbrain/cloudbrain.go @@ -3,20 +3,32 @@ package cloudbrain import ( "errors" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" +) + +const ( + Command = `pip3 install jupyterlab==1.1.4;service ssh stop;jupyter lab --no-browser --ip=0.0.0.0 --allow-root --notebook-dir=\"/userhome\" --port=80 --NotebookApp.token=\"\" --LabApp.allow_origin=\"self https://cloudbrain.pcl.ac.cn\"` + CodeMountPath = "/code" + DataSetMountPath = "/dataset" + ModelMountPath = "/model" + + SubTaskName = "task1" + + DebugGPUType = "DEBUG" - "code.gitea.io/gitea/models" ) func GenerateTask(ctx *context.Context, jobName, image, command string) error { jobResult, err := CreateJob(jobName, models.CreateJobParams{ JobName: jobName, RetryCount: 1, - GpuType: "dgx", + GpuType: DebugGPUType, Image: image, TaskRoles: []models.TaskRole{ { - Name: "task1", + Name: SubTaskName, TaskNumber: 1, MinSucceededTaskCount: 1, MinFailedTaskCount: 1, @@ -27,6 +39,30 @@ func GenerateTask(ctx *context.Context, jobName, image, command string) error { Command: command, NeedIBDevice: false, IsMainRole: false, + UseNNI: false, + }, + }, + Volumes: []models.Volume{ + { + HostPath: models.StHostPath{ + Path: "", + MountPath: CodeMountPath, + ReadOnly: true, + }, + }, + { + HostPath: models.StHostPath{ + Path: "", + MountPath: DataSetMountPath, + ReadOnly: false, + }, + }, + { + HostPath: models.StHostPath{ + Path: "", + MountPath: ModelMountPath, + ReadOnly: true, + }, }, }, }) @@ -34,6 +70,7 @@ func GenerateTask(ctx *context.Context, jobName, image, command string) error { return err } if jobResult.Code != "S000" { + log.Error("CreateJob(%s) failed:%s", jobName, jobResult.Msg) return errors.New(jobResult.Msg) } @@ -44,6 +81,7 @@ func GenerateTask(ctx *context.Context, jobName, image, command string) error { RepoID: ctx.Repo.Repository.ID, JobID: jobID, JobName: jobName, + SubTaskName: SubTaskName, }) if err != nil { diff --git a/modules/cloudbrain/resty.go b/modules/cloudbrain/resty.go old mode 100644 new mode 100755 index 88134bab7..b49caedb6 --- a/modules/cloudbrain/resty.go +++ b/modules/cloudbrain/resty.go @@ -118,3 +118,34 @@ sendjob: return &getJobResult, nil } + +func GetImages() (*models.GetImagesResult, error) { + checkSetting() + client := getRestyClient() + var getImagesResult models.GetImagesResult + + retry := 0 + +sendjob: + res, err := client.R(). + SetHeader("Content-Type", "application/json"). + SetAuthToken(TOKEN). + SetResult(&getImagesResult). + Get(HOST + "/rest-server/api/v1/image/list/") + + if err != nil { + return nil, fmt.Errorf("resty GetJob: %s", err) + } + + if getImagesResult.Code == "S401" && retry < 1 { + retry++ + _ = loginCloudbrain() + goto sendjob + } + + if getImagesResult.Code != "S000" { + return &getImagesResult, fmt.Errorf("getImgesResult err: %s", res.String()) + } + + return &getImagesResult, nil +} diff --git a/routers/repo/cloudbrain.go b/routers/repo/cloudbrain.go old mode 100644 new mode 100755 index e258eadd7..5b54f3791 --- a/routers/repo/cloudbrain.go +++ b/routers/repo/cloudbrain.go @@ -68,8 +68,23 @@ func CloudBrainNew(ctx *context.Context) { t := time.Now() var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[:5] ctx.Data["job_name"] = jobName - ctx.Data["image"] = "192.168.202.74:5000/user-images/deepo:v2.0" - ctx.Data["command"] = `pip3 install jupyterlab==1.1.4;service ssh stop;jupyter lab --no-browser --ip=0.0.0.0 --allow-root --notebook-dir=\"/userhome\" --port=80 --NotebookApp.token=\"\" --LabApp.allow_origin=\"self https://cloudbrain.pcl.ac.cn\"` + + result, err := cloudbrain.GetImages() + if err != nil { + ctx.Data["error"] = err.Error() + } + + if result != nil { + //models.ConvertToImagesResultPayload(result.Payload) + ctx.Data["image"] = result.Payload + } else { + ctx.Data["image"] = "192.168.202.74:5000/user-images/deepo:v2.0" + } + + ctx.Data["command"] = cloudbrain.Command + ctx.Data["code_path"] = cloudbrain.CodeMountPath + ctx.Data["dataset_path"] = cloudbrain.DataSetMountPath + ctx.Data["model_path"] = cloudbrain.ModelMountPath ctx.HTML(200, tplCloudBrainNew) } diff --git a/templates/repo/cloudbrain/index.tmpl b/templates/repo/cloudbrain/index.tmpl old mode 100644 new mode 100755 index 05e98506e..d1e9ababb --- a/templates/repo/cloudbrain/index.tmpl +++ b/templates/repo/cloudbrain/index.tmpl @@ -35,25 +35,39 @@ {{range .Tasks}}
-
+ -
+
{{.Status}}
{{svg "octicon-flame" 16}} {{TimeSinceUnix .CreatedUnix $.Lang}}
-
{{end}} diff --git a/templates/repo/cloudbrain/new.tmpl b/templates/repo/cloudbrain/new.tmpl old mode 100644 new mode 100755 index 944d7b25f..cfaead632 --- a/templates/repo/cloudbrain/new.tmpl +++ b/templates/repo/cloudbrain/new.tmpl @@ -16,20 +16,46 @@

+
+ <--> +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
- +
- Cancel + {{.i18n.Tr "repo.cloudbrain.cancel"}}