Browse Source

image list

master
yuyuanshifu 4 years ago
parent
commit
5c52eceec5
7 changed files with 184 additions and 10 deletions
  1. BIN
      docs/开源社区与云脑平台对接方案.docx
  2. +50
    -0
      models/cloudbrain.go
  3. +41
    -3
      modules/cloudbrain/cloudbrain.go
  4. +31
    -0
      modules/cloudbrain/resty.go
  5. +17
    -2
      routers/repo/cloudbrain.go
  6. +17
    -3
      templates/repo/cloudbrain/index.tmpl
  7. +28
    -2
      templates/repo/cloudbrain/new.tmpl

BIN
docs/开源社区与云脑平台对接方案.docx View File


+ 50
- 0
models/cloudbrain.go View File

@@ -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()


+ 41
- 3
modules/cloudbrain/cloudbrain.go View File

@@ -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 {


+ 31
- 0
modules/cloudbrain/resty.go View File

@@ -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
}

+ 17
- 2
routers/repo/cloudbrain.go View File

@@ -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)
}



+ 17
- 3
templates/repo/cloudbrain/index.tmpl View File

@@ -35,25 +35,39 @@
{{range .Tasks}}
<div class="ui grid item">
<div class="row">
<div class="seven wide column">
<div class="five wide column">
<a class="title" href="{{$.Link}}/{{.JobID}}">
<span class="fitted">{{svg "octicon-tasklist" 16}}</span>
<span class="fitted">{{.JobName}}</span>
</a>
</div>
<div class="four wide column job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}">
<div class="three wide column job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}">
{{.Status}}
</div>
<div class="three wide column">
<span class="ui text center">{{svg "octicon-flame" 16}} {{TimeSinceUnix .CreatedUnix $.Lang}}</span>
</div>
<div class="two wide column">
<div class="one wide column">
<span class="ui text center clipboard">
<a class="title" href="{{$.Link}}/{{.JobID}}">
<span class="fitted">查看</span>
</a>
</span>
</div>
<div class="one wide column">
<span class="ui text center clipboard">
<a class="title" href="{{$.Link}}/{{.JobID}}">
<span class="fitted">调试</span>
</a>
</span>
</div>
<div class="two wide column">
<span class="ui text center clipboard">
<a class="title" href="{{$.Link}}/{{.JobID}}">
<span class="fitted">镜像提交</span>
</a>
</span>
</div>
</div>
</div>
{{end}}


+ 28
- 2
templates/repo/cloudbrain/new.tmpl View File

@@ -16,20 +16,46 @@
<input name="job_name" id="cloudbrain_job_name" placeholder="任务名称" value="{{.job_name}}" tabindex="3" autofocus required maxlength="255">
</div>
<br>
<!-->
<div class="inline required field">
<label>镜像</label>
<input name="image" id="cloudbrain_image" placeholder="输入镜像" value="{{.image}}" tabindex="3" autofocus required maxlength="255">
</div>
<-->
<div class="inline required field">
<label>镜像</label>
<select id="cloudbrain_image" style='width:385px'>
{{range .image}}
<option name="image">{{.Place}}</option>
{{end}}
</select>
</div>
<div class="inline required field">
<label>数据集</label>
<input name="dataset" id="cloudbrain_dataset" placeholder="选择数据集" value="{{.image}}" tabindex="3" autofocus required maxlength="255">
</div>
<div class="inline required field">
<label>数据集存放路径</label>
<input name="dataset_path" id="cloudbrain_dataset_path" value="{{.dataset_path}}" tabindex="3" autofocus required maxlength="255" disabled="disabled" style="background:#CCCCCC">
</div>
<div class="inline required field">
<label>模型存放路径</label>
<input name="model_path" id="cloudbrain_model_path" value="{{.model_path}}" tabindex="3" autofocus required maxlength="255" disabled="disabled" style="background:#CCCCCC">
</div>
<div class="inline required field">
<label>代码存放路径</label>
<input name="code_path" id="cloudbrain_code_path" value="{{.code_path}}" tabindex="3" autofocus required maxlength="255" disabled="disabled" style="background:#CCCCCC">
</div>
<div class="inline required field">
<label>启动命令</label>
<textarea name="command" rows="10">{{.command}}</textarea>
<textarea name="command" rows="10" disabled="disabled" style="background:#CCCCCC">{{.command}}</textarea>
</div>
<div class="inline field">
<label></label>
<button class="ui green button">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
<a class="ui button" href="/">Cancel</a>
<a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
</div>
</div>
</form>


Loading…
Cancel
Save