Browse Source

Merge pull request 'download model' (#640) from download-cb2-model into V20211101

Reviewed-on: https://git.openi.org.cn/OpenI/aiforge/pulls/640
Reviewed-by: zhoupzh <zhoupzh@pcl.ac.cn>
tags/v1.21.12.1
zhoupzh 3 years ago
parent
commit
47b5ae9144
9 changed files with 141 additions and 103 deletions
  1. +26
    -21
      modules/storage/obs.go
  2. +1
    -41
      routers/repo/cloudbrain.go
  3. +1
    -10
      routers/repo/dir.go
  4. +52
    -26
      routers/repo/modelarts.go
  5. +1
    -1
      routers/routes/routes.go
  6. +2
    -2
      templates/repo/modelarts/notebook/index.tmpl
  7. +2
    -2
      templates/repo/modelarts/trainjob/index.tmpl
  8. +27
    -0
      templates/repo/modelarts/trainjob/models/dir_list.tmpl
  9. +29
    -0
      templates/repo/modelarts/trainjob/models/index.tmpl

+ 26
- 21
modules/storage/obs.go View File

@@ -5,7 +5,6 @@
package storage

import (
"fmt"
"io"
"path"
"strconv"
@@ -18,6 +17,15 @@ import (
"code.gitea.io/gitea/modules/setting"
)

type FileInfo struct {
FileName string `json:"FileName"`
ModTime string `json:"ModTime"`
IsDir bool `json:"IsDir"`
Size int64 `json:"Size"`
ParenDir string `json:"ParenDir"`
UUID string `json:"UUID"`
}

//check if has the object
//todo:修改查询方式
func ObsHasObject(path string) (bool, error) {
@@ -141,8 +149,7 @@ func ObsDownload(uuid string, fileName string) (io.ReadCloser, error) {
output.StorageClass, output.ETag, output.ContentType, output.ContentLength, output.LastModified)
return output.Body, nil
} else if obsError, ok := err.(obs.ObsError); ok {
fmt.Printf("Code:%s\n", obsError.Code)
fmt.Printf("Message:%s\n", obsError.Message)
log.Error("Code:%s, Message:%s", obsError.Code, obsError.Message)
return nil, obsError
} else {
return nil, err
@@ -160,40 +167,38 @@ func ObsModelDownload(JobName string, fileName string) (io.ReadCloser, error) {
output.StorageClass, output.ETag, output.ContentType, output.ContentLength, output.LastModified)
return output.Body, nil
} else if obsError, ok := err.(obs.ObsError); ok {
fmt.Printf("Code:%s\n", obsError.Code)
fmt.Printf("Message:%s\n", obsError.Message)
log.Error("Code:%s, Message:%s", obsError.Code, obsError.Message)
return nil, obsError
} else {
return nil, err
}
}

func GetObsListObject(jobName string) ([]string, error) {
// jobName = "liuzx202110271830856"
func GetObsListObject(jobName, parentDir string) ([]FileInfo, error) {
input := &obs.ListObjectsInput{}
input.Bucket = setting.Bucket
input.Prefix = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath), "/")
log.Info("input.Prefix:", input.Prefix)
input.Prefix = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, parentDir), "/")
output, err := ObsCli.ListObjects(input)
log.Info("output.Prefix:", output)
ModelListArr := make([]string, 0)
fileInfos := make([]FileInfo, 0)
if err == nil {
fmt.Printf("RequestId:%s\n", output.RequestId)
for index, val := range output.Contents {
fmt.Printf("Content[%d]-OwnerId:%s, ETag:%s, Key:%s, LastModified:%s, Size:%d\n",
log.Info("Content[%d]-OwnerId:%s, ETag:%s, Key:%s, LastModified:%s, Size:%d\n",
index, val.Owner.ID, val.ETag, val.Key, val.LastModified, val.Size)
str1 := strings.Split(val.Key, "/")
ModelList := str1[len(str1)-1]
ModelListArr = append(ModelListArr, ModelList)
log.Info("ModelListArr.Prefix:", ModelListArr)
fileName := str1[len(str1)-1]
log.Info("", fileName)
fileInfo := FileInfo{
ModTime: val.LastModified.Format("2006-01-02 15:04:05"),
FileName: fileName,
Size: val.Size,
IsDir:false,
}
fileInfos = append(fileInfos, fileInfo)
}
return ModelListArr, err
return fileInfos, err
} else {
if obsError, ok := err.(obs.ObsError); ok {
fmt.Println(obsError.Code)
fmt.Println(obsError.Message)
} else {
fmt.Println(err)
log.Error("Code:%s, Message:%s", obsError.Code, obsError.Message)
}
return nil, err
}


+ 1
- 41
routers/repo/cloudbrain.go View File

@@ -510,7 +510,7 @@ func CloudBrainShowModels(ctx *context.Context) {
return
}

var fileInfos []FileInfo
var fileInfos []storage.FileInfo
err = json.Unmarshal([]byte(dirs), &fileInfos)
if err != nil {
log.Error("json.Unmarshal failed:%v", err.Error(), ctx.Data["msgID"])
@@ -583,50 +583,10 @@ func CloudBrainDownloadModel(ctx *context.Context) {
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
}

// func TrainJobloadModel(ctx *context.Context) {
// parentDir := ctx.Query("parentDir")
// fileName := ctx.Query("fileName")
// jobName := ctx.Query("jobName")
// filePath := "jobs/" + jobName + "/model/" + parentDir
// url, err := storage.Attachments.PresignedGetURL(filePath, fileName)
// if err != nil {
// log.Error("PresignedGetURL failed: %v", err.Error(), ctx.Data["msgID"])
// ctx.ServerError("PresignedGetURL", err)
// return
// }

// http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
// }

func TrainJobListModel(ctx *context.Context) {
ctx.Data["PageIsCloudBrain"] = true
jobID := ctx.Params(":jobid")
task, err := models.GetCloudbrainByJobID(jobID)
if err != nil {
log.Error("no such job!", ctx.Data["err"])
ctx.ServerError("no such job:", err)
return
}
TrainJobListModel, err := storage.GetObsListObject(task.JobName)
log.Info("TrainJobListModel", TrainJobListModel)
fmt.Println("TrainJobListModel:", TrainJobListModel)
if err != nil {
log.Info("get TrainJobListModel failed:", err)
return
}
ctx.Data["task"] = task
ctx.Data["JobID"] = jobID
ctx.Data["ListModel"] = TrainJobListModel
ctx.HTML(200, tplModelArtsTrainJobListModel)
}

func TrainJobDownloadModel(ctx *context.Context) {
JobName := ctx.Query("JobName")
fileName := ctx.Query("file_name")

// JobName = "liuzx202110271830856"
// fileName = "Untitled.ipynb"

body, err := storage.ObsModelDownload(JobName, fileName)
if err != nil {
log.Info("download error.")


+ 1
- 10
routers/repo/dir.go View File

@@ -21,15 +21,6 @@ const (
tplDirIndex base.TplName = "repo/datasets/dirs/index"
)

type FileInfo struct {
FileName string `json:"FileName"`
ModTime string `json:"ModTime"`
IsDir bool `json:"IsDir"`
Size int64 `json:"Size"`
ParenDir string `json:"ParenDir"`
UUID string `json:"UUID"`
}

type RespGetDirs struct {
ResultCode string `json:"resultCode"`
FileInfos string `json:"fileInfos"`
@@ -59,7 +50,7 @@ func DeleteAllUnzipFile(attachment *models.Attachment, parentDir string) {
return
}

var fileInfos []FileInfo
var fileInfos []storage.FileInfo
err = json.Unmarshal([]byte(dirs), &fileInfos)
if err != nil {
log.Error("json.Unmarshal failed:", err.Error())


+ 52
- 26
routers/repo/modelarts.go View File

@@ -3,7 +3,6 @@ package repo
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
@@ -12,18 +11,18 @@ import (
"strings"
"time"

"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/modelarts"
"code.gitea.io/gitea/modules/obs"
"code.gitea.io/gitea/modules/storage"
"github.com/unknwon/com"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/modelarts"
"code.gitea.io/gitea/modules/obs"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"

"github.com/unknwon/com"
)

const (
@@ -39,7 +38,7 @@ const (
tplModelArtsTrainJobIndex base.TplName = "repo/modelarts/trainjob/index"
tplModelArtsTrainJobNew base.TplName = "repo/modelarts/trainjob/new"
tplModelArtsTrainJobShow base.TplName = "repo/modelarts/trainjob/show"
tplModelArtsTrainJobListModel base.TplName = "repo/modelarts/trainjob/list_model"
tplModelArtsTrainJobShowModels base.TplName = "repo/modelarts/trainjob/models/index"
)

// MustEnableDataset check if repository enable internal cb
@@ -492,13 +491,13 @@ func NotebookDel(ctx *context.Context) {
func TrainJobIndex(ctx *context.Context) {
MustEnableModelArts(ctx)

can, err := canUserCreateTrainJob(ctx.User.ID)
if err != nil {
ctx.ServerError("canUserCreateTrainJob", err)
return
}
ctx.Data["CanCreate"] = can
//can, err := canUserCreateTrainJob(ctx.User.ID)
//if err != nil {
// ctx.ServerError("canUserCreateTrainJob", err)
// return
//}
//
//ctx.Data["CanCreate"] = can

repo := ctx.Repo.Repository
page := ctx.QueryInt("page")
@@ -531,17 +530,17 @@ func TrainJobIndex(ctx *context.Context) {
func TrainJobNew(ctx *context.Context) {
ctx.Data["PageIsCloudBrain"] = true

can, err := canUserCreateTrainJob(ctx.User.ID)
if err != nil {
ctx.ServerError("canUserCreateTrainJob", err)
return
}
if !can {
log.Error("the user can not create train-job")
ctx.ServerError("the user can not create train-job", fmt.Errorf("the user can not create train-job"))
return
}
//can, err := canUserCreateTrainJob(ctx.User.ID)
//if err != nil {
// ctx.ServerError("canUserCreateTrainJob", err)
// return
//}
//
//if !can {
// log.Error("the user can not create train-job")
// ctx.ServerError("the user can not create train-job", fmt.Errorf("the user can not create train-job"))
// return
//}

t := time.Now()
var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
@@ -1060,3 +1059,30 @@ func getConfigList(perPage, page int, sortBy, order, searchContent, configType s

return list, nil
}

func TrainJobShowModels(ctx *context.Context) {
ctx.Data["PageIsCloudBrain"] = true

jobID := ctx.Params(":jobid")
parentDir := ctx.Query("parentDir")
dirArray := strings.Split(parentDir, "/")
task, err := models.GetCloudbrainByJobID(jobID)
if err != nil {
log.Error("no such job!", ctx.Data["msgID"])
ctx.ServerError("no such job:", err)
return
}

models, err := storage.GetObsListObject(task.JobName, parentDir)
if err != nil {
log.Info("get TrainJobListModel failed:", err)
ctx.ServerError("GetObsListObject:", err)
return
}

ctx.Data["Path"] = dirArray
ctx.Data["Dirs"] = models
ctx.Data["task"] = task
ctx.Data["JobID"] = jobID
ctx.HTML(200, tplModelArtsTrainJobShowModels)
}

+ 1
- 1
routers/routes/routes.go View File

@@ -991,7 +991,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/stop", reqRepoCloudBrainWriter, repo.TrainJobStop)
m.Post("/del", reqRepoCloudBrainWriter, repo.TrainJobDel)
m.Get("/log", reqRepoCloudBrainReader, repo.TrainJobGetLog)
m.Get("/models", reqRepoCloudBrainReader, repo.TrainJobListModel)
m.Get("/models", reqRepoCloudBrainReader, repo.TrainJobShowModels)
m.Get("/download_model", reqRepoCloudBrainReader, repo.TrainJobDownloadModel)
})
m.Get("/create", reqRepoCloudBrainReader, repo.TrainJobNew)


+ 2
- 2
templates/repo/modelarts/notebook/index.tmpl View File

@@ -423,7 +423,7 @@

// 加载任务状态
var timeid = window.setInterval(loadJobStatus, 15000);
$(document).ready(loadJobStatus);
$(document).ready(loadJobStatus);
function loadJobStatus() {
$(".job-status").each((index, job) => {
const jobID = job.dataset.jobid;
@@ -435,7 +435,7 @@
$.get(`/api/v1/repos/${repoPath}/modelarts/notebook/${jobID}`, (data) => {
const jobID = data.JobID
const status = data.JobStatus
if (status != job.textContent.trim() || status=='RUNNING') {
if (status != job.textContent.trim()) {
//$('#' + jobID).text(status)
//if (status == 'STOPPED') {
window.location.reload()


+ 2
- 2
templates/repo/modelarts/trainjob/index.tmpl View File

@@ -459,7 +459,7 @@

// 加载任务状态
var timeid = window.setInterval(loadJobStatus, 15000);
$(document).ready(loadJobStatus);
$(document).ready(loadJobStatus);
function loadJobStatus() {
$(".job-status").each((index, job) => {
const jobID = job.dataset.jobid;
@@ -473,7 +473,7 @@
$.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}`, (data) => {
const jobID = data.JobID
const status = data.JobStatus
if (status != job.textContent.trim() || status=='RUNNING') {
if (status != job.textContent.trim()) {
//$('#' + jobID).text(status)
//if (status == 'STOPPED') {
window.location.reload()


+ 27
- 0
templates/repo/modelarts/trainjob/models/dir_list.tmpl View File

@@ -0,0 +1,27 @@
{{if .Dirs}}
<table id="repo-files-table" class="ui single line table">
<tbody>
{{range .Dirs}}
<tr>
<td class="name four wide">
<span class="truncate">
<span class="octicon octicon-file-directory"></span>
<a class="title" href="{{if .IsDir}}{{$.RepoLink}}/cloudbrain/{{$.JobID}}/models?parentDir={{.ParenDir}}{{else}}{{$.RepoLink}}/cloudbrain/{{$.JobID}}/download_model?parentDir={{.ParenDir}}&fileName={{.FileName}}&jobName={{$.task.JobName}}{{end}}">
<span class="fitted">{{if .IsDir}} {{svg "octicon-file-directory" 16}}{{else}}{{svg "octicon-file" 16}}{{end}}</span> {{.FileName}}
</a>
</span>
</td>
<td class="message nine wide">
<span class="truncate has-emoji">
{{.Size | FileSize}}
</span>
</td>
<td class="text right age three wide">
<span class="time-since poping up">{{.ModTime}}</span>
</td>
</tr>
{{end}}
</tbody>
</table>

{{end}}

+ 29
- 0
templates/repo/modelarts/trainjob/models/index.tmpl View File

@@ -0,0 +1,29 @@
{{template "base/head" .}}
<div class="repository dataset dir-list view">
{{template "repo/header" .}}
<form class="ui container">
<div class="ui stackable grid {{if .Error}}hide{{end}}" id="dir-content">
<div class="row">
<div class="column sixteen wide">
<p>
{{ range $index, $item := .Path }}<a href='{{$.Link}}/?parentDir={{if gt $index 0}}{{DatasetPathJoin $.Path $index "/"}}{{else}}{{end}}'>{{ $item }}</a><span class="directory-seperator">/</span>{{ end }}
</p>
</div>
</div>
</div>

<div class="ui grid">
<div class="row">
<div class="ui sixteen wide column">
<div class="dir list">
{{template "repo/cloudbrain/models/dir_list" .}}
</div>
</div>
</div>
</div>
</form>
</div>



{{template "base/footer" .}}

Loading…
Cancel
Save