Reviewed-on: https://git.openi.org.cn/OpenI/aiforge/pulls/950 Reviewed-by: lewis <747342561@qq.com>pull/961/head
@@ -176,10 +176,10 @@ func ObsModelDownload(JobName string, fileName string) (io.ReadCloser, error) { | |||||
} | } | ||||
} | } | ||||
func GetObsListObject(jobName, parentDir string, versionOutputPath string) ([]FileInfo, error) { | |||||
func GetObsListObject(jobName, parentDir, versionName string) ([]FileInfo, error) { | |||||
input := &obs.ListObjectsInput{} | input := &obs.ListObjectsInput{} | ||||
input.Bucket = setting.Bucket | input.Bucket = setting.Bucket | ||||
input.Prefix = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, versionOutputPath, parentDir), "/") | |||||
input.Prefix = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, versionName, parentDir), "/") | |||||
strPrefix := strings.Split(input.Prefix, "/") | strPrefix := strings.Split(input.Prefix, "/") | ||||
output, err := ObsCli.ListObjects(input) | output, err := ObsCli.ListObjects(input) | ||||
fileInfos := make([]FileInfo, 0) | fileInfos := make([]FileInfo, 0) | ||||
@@ -275,8 +275,34 @@ func GetObsCreateSignedUrl(jobName, parentDir, fileName string) (string, error) | |||||
log.Error("CreateSignedUrl failed:", err.Error()) | log.Error("CreateSignedUrl failed:", err.Error()) | ||||
return "", err | return "", err | ||||
} | } | ||||
log.Info("SignedUrl:%s", output.SignedUrl) | |||||
return output.SignedUrl, nil | |||||
} | |||||
func GetObsCreateSignedUrlByBucketAndKey(bucket, key string) (string, error) { | |||||
input := &obs.CreateSignedUrlInput{} | |||||
input.Bucket = bucket | |||||
input.Key = key | |||||
input.Expires = 60 * 60 | |||||
input.Method = obs.HttpMethodGet | |||||
comma := strings.LastIndex(key, "/") | |||||
filename := key | |||||
if comma != -1 { | |||||
filename = key[comma+1:] | |||||
} | |||||
reqParams := make(map[string]string) | |||||
filename = url.QueryEscape(filename) | |||||
reqParams["response-content-disposition"] = "attachment; filename=\"" + filename + "\"" | |||||
input.QueryParams = reqParams | |||||
output, err := ObsCli.CreateSignedUrl(input) | |||||
if err != nil { | |||||
log.Error("CreateSignedUrl failed:", err.Error()) | |||||
return "", err | |||||
} | |||||
return output.SignedUrl, nil | return output.SignedUrl, nil | ||||
} | } | ||||
func ObsGetPreSignedUrl(uuid, fileName string) (string, error) { | func ObsGetPreSignedUrl(uuid, fileName string) (string, error) { | ||||
@@ -311,3 +337,20 @@ func ObsCreateObject(path string) error { | |||||
return nil | return nil | ||||
} | } | ||||
func ObsDownloadAFile(bucket string, key string) (io.ReadCloser, error) { | |||||
input := &obs.GetObjectInput{} | |||||
input.Bucket = bucket | |||||
input.Key = key | |||||
output, err := ObsCli.GetObject(input) | |||||
if err == nil { | |||||
log.Info("StorageClass:%s, ETag:%s, ContentType:%s, ContentLength:%d, LastModified:%s\n", | |||||
output.StorageClass, output.ETag, output.ContentType, output.ContentLength, output.LastModified) | |||||
return output.Body, nil | |||||
} else if obsError, ok := err.(obs.ObsError); ok { | |||||
log.Error("Code:%s, Message:%s", obsError.Code, obsError.Message) | |||||
return nil, obsError | |||||
} else { | |||||
return nil, err | |||||
} | |||||
} |
@@ -7,6 +7,7 @@ package repo | |||||
import ( | import ( | ||||
"net/http" | "net/http" | ||||
"path" | |||||
"strconv" | "strconv" | ||||
"strings" | "strings" | ||||
@@ -14,6 +15,7 @@ import ( | |||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/modelarts" | "code.gitea.io/gitea/modules/modelarts" | ||||
"code.gitea.io/gitea/modules/setting" | |||||
"code.gitea.io/gitea/modules/storage" | "code.gitea.io/gitea/modules/storage" | ||||
) | ) | ||||
@@ -302,8 +304,7 @@ func ModelList(ctx *context.APIContext) { | |||||
log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error()) | log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error()) | ||||
return | return | ||||
} | } | ||||
VersionOutputPath := modelarts.GetVersionOutputPathByTotalVersionCount(task.TotalVersionCount) | |||||
models, err := storage.GetObsListObject(task.JobName, parentDir, VersionOutputPath) | |||||
models, err := storage.GetObsListObject(task.JobName, parentDir, versionName) | |||||
if err != nil { | if err != nil { | ||||
log.Info("get TrainJobListModel failed:", err) | log.Info("get TrainJobListModel failed:", err) | ||||
ctx.ServerError("GetObsListObject:", err) | ctx.ServerError("GetObsListObject:", err) | ||||
@@ -321,27 +322,61 @@ func ModelList(ctx *context.APIContext) { | |||||
}) | }) | ||||
} | } | ||||
func ModelDownload(ctx *context.APIContext) { | |||||
func ModelDownload(ctx *context.Context) { | |||||
var ( | var ( | ||||
err error | err error | ||||
) | ) | ||||
var jobID = ctx.Params(":jobid") | var jobID = ctx.Params(":jobid") | ||||
versionName := ctx.Query("version_name") | versionName := ctx.Query("version_name") | ||||
// versionName := "V0001" | |||||
parentDir := ctx.Query("parent_dir") | parentDir := ctx.Query("parent_dir") | ||||
fileName := ctx.Query("file_name") | fileName := ctx.Query("file_name") | ||||
log.Info("DownloadSingleModelFile start.") | |||||
// id := ctx.Params(":ID") | |||||
// path := Model_prefix + models.AttachmentRelativePath(id) + "/" + parentDir + fileName | |||||
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | ||||
if err != nil { | if err != nil { | ||||
log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error()) | log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error()) | ||||
return | return | ||||
} | } | ||||
VersionOutputPath := modelarts.GetVersionOutputPathByTotalVersionCount(task.TotalVersionCount) | |||||
parentDir = VersionOutputPath + "/" + parentDir | |||||
url, err := storage.GetObsCreateSignedUrl(task.JobName, parentDir, fileName) | |||||
if err != nil { | |||||
log.Error("GetObsCreateSignedUrl failed: %v", err.Error(), ctx.Data["msgID"]) | |||||
ctx.ServerError("GetObsCreateSignedUrl", err) | |||||
return | |||||
path := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, task.JobName, setting.OutPutPath, versionName, parentDir, fileName), "/") | |||||
log.Info("Download path is:%s", path) | |||||
if setting.PROXYURL != "" { | |||||
body, err := storage.ObsDownloadAFile(setting.Bucket, path) | |||||
if err != nil { | |||||
log.Info("download error.") | |||||
} else { | |||||
//count++ | |||||
// models.ModifyModelDownloadCount(id) | |||||
defer body.Close() | |||||
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+fileName) | |||||
ctx.Resp.Header().Set("Content-Type", "application/octet-stream") | |||||
p := make([]byte, 1024) | |||||
var readErr error | |||||
var readCount int | |||||
// 读取对象内容 | |||||
for { | |||||
readCount, readErr = body.Read(p) | |||||
if readCount > 0 { | |||||
ctx.Resp.Write(p[:readCount]) | |||||
//fmt.Printf("%s", p[:readCount]) | |||||
} | |||||
if readErr != nil { | |||||
break | |||||
} | |||||
} | |||||
} | |||||
} else { | |||||
url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path) | |||||
if err != nil { | |||||
log.Error("GetObsCreateSignedUrl failed: %v", err.Error(), ctx.Data["msgID"]) | |||||
ctx.ServerError("GetObsCreateSignedUrl", err) | |||||
return | |||||
} | |||||
//count++ | |||||
// models.ModifyModelDownloadCount(id) | |||||
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) | |||||
} | } | ||||
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) | |||||
} | } |
@@ -369,6 +369,7 @@ func trainJobNewDataPrepare(ctx *context.Context) error { | |||||
} | } | ||||
ctx.Data["Branches"] = Branches | ctx.Data["Branches"] = Branches | ||||
ctx.Data["BranchesCount"] = len(Branches) | ctx.Data["BranchesCount"] = len(Branches) | ||||
ctx.Data["params"] = "" | |||||
configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom) | configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom) | ||||
if err != nil { | if err != nil { | ||||
@@ -380,7 +381,92 @@ func trainJobNewDataPrepare(ctx *context.Context) error { | |||||
return nil | return nil | ||||
} | } | ||||
func ErrorNewDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) error { | |||||
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 | |||||
//} | |||||
t := time.Now() | |||||
var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||||
ctx.Data["job_name"] = jobName | |||||
attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||||
if err != nil { | |||||
ctx.ServerError("GetAllUserAttachments failed:", err) | |||||
return err | |||||
} | |||||
ctx.Data["attachments"] = attachs | |||||
var resourcePools modelarts.ResourcePool | |||||
if err = json.Unmarshal([]byte(setting.ResourcePools), &resourcePools); err != nil { | |||||
ctx.ServerError("json.Unmarshal failed:", err) | |||||
return err | |||||
} | |||||
ctx.Data["resource_pools"] = resourcePools.Info | |||||
var engines modelarts.Engine | |||||
if err = json.Unmarshal([]byte(setting.Engines), &engines); err != nil { | |||||
ctx.ServerError("json.Unmarshal failed:", err) | |||||
return err | |||||
} | |||||
ctx.Data["engines"] = engines.Info | |||||
var versionInfos modelarts.VersionInfo | |||||
if err = json.Unmarshal([]byte(setting.EngineVersions), &versionInfos); err != nil { | |||||
ctx.ServerError("json.Unmarshal failed:", err) | |||||
return err | |||||
} | |||||
ctx.Data["engine_versions"] = versionInfos.Version | |||||
var flavorInfos modelarts.Flavor | |||||
if err = json.Unmarshal([]byte(setting.TrainJobFLAVORINFOS), &flavorInfos); err != nil { | |||||
ctx.ServerError("json.Unmarshal failed:", err) | |||||
return err | |||||
} | |||||
ctx.Data["flavor_infos"] = flavorInfos.Info | |||||
outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath | |||||
ctx.Data["train_url"] = outputObsPath | |||||
Branches, err := ctx.Repo.GitRepo.GetBranches() | |||||
if err != nil { | |||||
ctx.ServerError("GetBranches error:", err) | |||||
return err | |||||
} | |||||
ctx.Data["Branches"] = Branches | |||||
ctx.Data["BranchesCount"] = len(Branches) | |||||
configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom) | |||||
if err != nil { | |||||
ctx.ServerError("getConfigList failed:", err) | |||||
return err | |||||
} | |||||
var Parameters modelarts.Parameters | |||||
if err = json.Unmarshal([]byte(form.Params), &Parameters); err != nil { | |||||
ctx.ServerError("json.Unmarshal failed:", err) | |||||
return err | |||||
} | |||||
ctx.Data["params"] = Parameters.Parameter | |||||
ctx.Data["config_list"] = configList.ParaConfigs | |||||
ctx.Data["bootFile"] = form.BootFile | |||||
ctx.Data["uuid"] = form.Attachment | |||||
ctx.Data["branch_name"] = form.BranchName | |||||
return nil | |||||
} | |||||
func TrainJobNewVersion(ctx *context.Context) { | func TrainJobNewVersion(ctx *context.Context) { | ||||
err := trainJobNewVersionDataPrepare(ctx) | err := trainJobNewVersionDataPrepare(ctx) | ||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("get new train-job info failed", err) | ctx.ServerError("get new train-job info failed", err) | ||||
@@ -394,6 +480,12 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||||
var jobID = ctx.Params(":jobid") | var jobID = ctx.Params(":jobid") | ||||
// var versionName = ctx.Params(":version-name") | // var versionName = ctx.Params(":version-name") | ||||
var versionName = ctx.Query("version_name") | var versionName = ctx.Query("version_name") | ||||
// canNewJob, err := canUserCreateTrainJobVersion(ctx, jobID) | |||||
// if err != nil { | |||||
// ctx.ServerError("get can info failed", err) | |||||
// return err | |||||
// } | |||||
// ctx.Data["canNewJob"] = canNewJob | |||||
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | ||||
if err != nil { | if err != nil { | ||||
@@ -455,7 +547,8 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||||
ctx.ServerError("GetBranches error:", err) | ctx.ServerError("GetBranches error:", err) | ||||
return err | return err | ||||
} | } | ||||
ctx.Data["branches"] = Branches | |||||
ctx.Data["branch"] = Branches | |||||
ctx.Data["branch_name"] = task.BranchName | ctx.Data["branch_name"] = task.BranchName | ||||
ctx.Data["description"] = task.Description | ctx.Data["description"] = task.Description | ||||
ctx.Data["boot_file"] = task.BootFile | ctx.Data["boot_file"] = task.BootFile | ||||
@@ -477,7 +570,7 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||||
return nil | return nil | ||||
} | } | ||||
func ErrorDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) error { | |||||
func VersionErrorDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) error { | |||||
ctx.Data["PageIsCloudBrain"] = true | ctx.Data["PageIsCloudBrain"] = true | ||||
var jobID = ctx.Params(":jobid") | var jobID = ctx.Params(":jobid") | ||||
// var versionName = ctx.Params(":version-name") | // var versionName = ctx.Params(":version-name") | ||||
@@ -580,7 +673,6 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||||
isSaveParam := form.IsSaveParam | isSaveParam := form.IsSaveParam | ||||
repo := ctx.Repo.Repository | repo := ctx.Repo.Repository | ||||
codeLocalPath := setting.JobPath + jobName + modelarts.CodePath | codeLocalPath := setting.JobPath + jobName + modelarts.CodePath | ||||
// codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath + VersionOutputPath + "/" | |||||
codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath | codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath | ||||
outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath + VersionOutputPath + "/" | outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath + VersionOutputPath + "/" | ||||
logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath + VersionOutputPath + "/" | logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath + VersionOutputPath + "/" | ||||
@@ -593,7 +685,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||||
if err := paramCheckCreateTrainJob(form); err != nil { | if err := paramCheckCreateTrainJob(form); err != nil { | ||||
log.Error("paramCheckCreateTrainJob failed:(%v)", err) | log.Error("paramCheckCreateTrainJob failed:(%v)", err) | ||||
trainJobNewDataPrepare(ctx) | |||||
ErrorNewDataPrepare(ctx, form) | |||||
ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobNew, &form) | ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobNew, &form) | ||||
return | return | ||||
} | } | ||||
@@ -792,7 +884,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||||
if err := paramCheckCreateTrainJob(form); err != nil { | if err := paramCheckCreateTrainJob(form); err != nil { | ||||
log.Error("paramCheckCreateTrainJob failed:(%v)", err) | log.Error("paramCheckCreateTrainJob failed:(%v)", err) | ||||
ErrorDataPrepare(ctx, form) | |||||
VersionErrorDataPrepare(ctx, form) | |||||
ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobVersionNew, &form) | ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobVersionNew, &form) | ||||
return | return | ||||
} | } | ||||
@@ -815,7 +907,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||||
Branch: branch_name, | Branch: branch_name, | ||||
}); err != nil { | }); err != nil { | ||||
log.Error("创建任务失败,任务名称已存在!: %s (%v)", repo.FullName(), err) | log.Error("创建任务失败,任务名称已存在!: %s (%v)", repo.FullName(), err) | ||||
ErrorDataPrepare(ctx, form) | |||||
VersionErrorDataPrepare(ctx, form) | |||||
ctx.RenderWithErr("创建任务失败,任务名称已存在!", tplModelArtsTrainJobVersionNew, &form) | ctx.RenderWithErr("创建任务失败,任务名称已存在!", tplModelArtsTrainJobVersionNew, &form) | ||||
return | return | ||||
} | } | ||||
@@ -823,14 +915,14 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||||
//todo: upload code (send to file_server todo this work?) | //todo: upload code (send to file_server todo this work?) | ||||
if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.OutputPath + VersionOutputPath + "/"); err != nil { | if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.OutputPath + VersionOutputPath + "/"); err != nil { | ||||
log.Error("Failed to obsMkdir_output: %s (%v)", repo.FullName(), err) | log.Error("Failed to obsMkdir_output: %s (%v)", repo.FullName(), err) | ||||
ErrorDataPrepare(ctx, form) | |||||
VersionErrorDataPrepare(ctx, form) | |||||
ctx.RenderWithErr("Failed to obsMkdir_output", tplModelArtsTrainJobVersionNew, &form) | ctx.RenderWithErr("Failed to obsMkdir_output", tplModelArtsTrainJobVersionNew, &form) | ||||
return | return | ||||
} | } | ||||
if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.LogPath + VersionOutputPath + "/"); err != nil { | if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.LogPath + VersionOutputPath + "/"); err != nil { | ||||
log.Error("Failed to obsMkdir_log: %s (%v)", repo.FullName(), err) | log.Error("Failed to obsMkdir_log: %s (%v)", repo.FullName(), err) | ||||
ErrorDataPrepare(ctx, form) | |||||
VersionErrorDataPrepare(ctx, form) | |||||
ctx.RenderWithErr("Failed to obsMkdir_log", tplModelArtsTrainJobVersionNew, &form) | ctx.RenderWithErr("Failed to obsMkdir_log", tplModelArtsTrainJobVersionNew, &form) | ||||
return | return | ||||
} | } | ||||
@@ -839,7 +931,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||||
// if err := uploadCodeToObs(codeLocalPath, jobName, ""); err != nil { | // if err := uploadCodeToObs(codeLocalPath, jobName, ""); err != nil { | ||||
if err := uploadCodeToObs(codeLocalPath, jobName, parentDir); err != nil { | if err := uploadCodeToObs(codeLocalPath, jobName, parentDir); err != nil { | ||||
log.Error("Failed to uploadCodeToObs: %s (%v)", repo.FullName(), err) | log.Error("Failed to uploadCodeToObs: %s (%v)", repo.FullName(), err) | ||||
ErrorDataPrepare(ctx, form) | |||||
VersionErrorDataPrepare(ctx, form) | |||||
ctx.RenderWithErr("Failed to uploadCodeToObs", tplModelArtsTrainJobVersionNew, &form) | ctx.RenderWithErr("Failed to uploadCodeToObs", tplModelArtsTrainJobVersionNew, &form) | ||||
return | return | ||||
} | } | ||||
@@ -859,7 +951,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||||
err := json.Unmarshal([]byte(params), ¶meters) | err := json.Unmarshal([]byte(params), ¶meters) | ||||
if err != nil { | if err != nil { | ||||
log.Error("Failed to Unmarshal params: %s (%v)", params, err) | log.Error("Failed to Unmarshal params: %s (%v)", params, err) | ||||
ErrorDataPrepare(ctx, form) | |||||
VersionErrorDataPrepare(ctx, form) | |||||
ctx.RenderWithErr("运行参数错误", tplModelArtsTrainJobVersionNew, &form) | ctx.RenderWithErr("运行参数错误", tplModelArtsTrainJobVersionNew, &form) | ||||
return | return | ||||
} | } | ||||
@@ -878,7 +970,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||||
if isSaveParam == "on" { | if isSaveParam == "on" { | ||||
if form.ParameterTemplateName == "" { | if form.ParameterTemplateName == "" { | ||||
log.Error("ParameterTemplateName is empty") | log.Error("ParameterTemplateName is empty") | ||||
ErrorDataPrepare(ctx, form) | |||||
VersionErrorDataPrepare(ctx, form) | |||||
ctx.RenderWithErr("保存作业参数时,作业参数名称不能为空", tplModelArtsTrainJobVersionNew, &form) | ctx.RenderWithErr("保存作业参数时,作业参数名称不能为空", tplModelArtsTrainJobVersionNew, &form) | ||||
return | return | ||||
} | } | ||||
@@ -902,7 +994,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||||
if err != nil { | if err != nil { | ||||
log.Error("Failed to CreateTrainJobConfig: %v", err) | log.Error("Failed to CreateTrainJobConfig: %v", err) | ||||
ErrorDataPrepare(ctx, form) | |||||
VersionErrorDataPrepare(ctx, form) | |||||
ctx.RenderWithErr("保存作业参数失败:"+err.Error(), tplModelArtsTrainJobVersionNew, &form) | ctx.RenderWithErr("保存作业参数失败:"+err.Error(), tplModelArtsTrainJobVersionNew, &form) | ||||
return | return | ||||
} | } | ||||
@@ -949,7 +1041,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||||
err = modelarts.GenerateTrainJobVersion(ctx, req, jobID) | err = modelarts.GenerateTrainJobVersion(ctx, req, jobID) | ||||
if err != nil { | if err != nil { | ||||
log.Error("GenerateTrainJob failed:%v", err.Error()) | log.Error("GenerateTrainJob failed:%v", err.Error()) | ||||
ErrorDataPrepare(ctx, form) | |||||
VersionErrorDataPrepare(ctx, form) | |||||
ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobVersionNew, &form) | ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobVersionNew, &form) | ||||
return | return | ||||
} | } | ||||
@@ -1220,6 +1312,18 @@ func canUserCreateTrainJob(uid int64) (bool, error) { | |||||
return org.IsOrgMember(uid) | return org.IsOrgMember(uid) | ||||
} | } | ||||
func canUserCreateTrainJobVersion(ctx *context.Context, jobID string) (bool, error) { | |||||
var versionName = "V0001" | |||||
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | |||||
if err != nil { | |||||
return false, err | |||||
} | |||||
if ctx.User.ID == task.User.ID { | |||||
return true, nil | |||||
} | |||||
return false, err | |||||
} | |||||
func TrainJobGetConfigList(ctx *context.Context) { | func TrainJobGetConfigList(ctx *context.Context) { | ||||
ctx.Data["PageIsTrainJob"] = true | ctx.Data["PageIsTrainJob"] = true | ||||
@@ -307,9 +307,9 @@ | |||||
<!-- 任务名 --> | <!-- 任务名 --> | ||||
<div class="five wide column"> | <div class="five wide column"> | ||||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 15px;"> | |||||
<span class="fitted" style="vertical-align: middle;">{{svg "octicon-tasklist" 16}}</span> | |||||
<span class="fitted text_over" style="width: 90%;vertical-align: middle;margin-left: 0.4rem;">{{.JobName}}</span> | |||||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 14px;"> | |||||
<span class="fitted text_over" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||||
</a> | </a> | ||||
</div> | </div> | ||||
@@ -380,7 +380,7 @@ | |||||
{{end}} | {{end}} | ||||
</form> | </form> | ||||
</div> | </div> | ||||
<div class="ui compact buttons" style="margin-right:10px;"> | |||||
<div class="ui compact buttons"> | |||||
<!-- 模型下载 --> | <!-- 模型下载 --> | ||||
<a class="ui basic blue button" href="{{$.Link}}/{{.JobID}}/models" target="_blank"> | <a class="ui basic blue button" href="{{$.Link}}/{{.JobID}}/models" target="_blank"> | ||||
{{$.i18n.Tr "repo.download"}} | {{$.i18n.Tr "repo.download"}} | ||||
@@ -399,11 +399,11 @@ | |||||
<form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post"> | <form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post"> | ||||
{{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | {{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | ||||
<a id="model-delete-{{.JobID}}" class="ui compact {{if not .CanDel}}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||||
<a id="model-delete-{{.JobID}}" class="ui basic blue button {{if not .CanDel}}disabled {{end}}" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||||
{{$.i18n.Tr "repo.delete"}} | {{$.i18n.Tr "repo.delete"}} | ||||
</a> | </a> | ||||
{{else}} | {{else}} | ||||
<a class="ui compact disabled button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||||
<a class="ui basic blue button disabled" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||||
{{$.i18n.Tr "repo.delete"}} | {{$.i18n.Tr "repo.delete"}} | ||||
</a> | </a> | ||||
{{end}} | {{end}} | ||||
@@ -93,7 +93,7 @@ | |||||
<div class="ui tabular stackable menu navbar"> | <div class="ui tabular stackable menu navbar"> | ||||
{{if .Permission.CanRead $.UnitTypeCode}} | {{if .Permission.CanRead $.UnitTypeCode}} | ||||
<div class="dropdown-menu"> | <div class="dropdown-menu"> | ||||
<a class="{{if or .PageIsViewCode .PageIsReleaseList .PageIsWiki .PageIsActivity .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}"> | |||||
<a class="{{if or .PageIsViewCode .PageIsReleaseList .PageIsWiki .PageIsActivity .PageIsViewCode}}active{{end}} item hover_active" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}"> | |||||
<span>{{svg "octicon-code" 16}} {{.i18n.Tr "repo.code"}} <i class="dropdown icon"></i></span> | <span>{{svg "octicon-code" 16}} {{.i18n.Tr "repo.code"}} <i class="dropdown icon"></i></span> | ||||
</a> | </a> | ||||
<div class="dropdown-content"> | <div class="dropdown-content"> | ||||
@@ -243,7 +243,7 @@ | |||||
}) | }) | ||||
$('.question.circle.icon').hover(function(){ | $('.question.circle.icon').hover(function(){ | ||||
$(this).popup('show') | $(this).popup('show') | ||||
$('.ui.popup.mini.top.center').css({"border-color":'rgba(50, 145, 248, 100)',"color":"rgba(3, 102, 214, 100)","border-radius":"5px"}) | |||||
$('.ui.popup.mini.top.center').css({"border-color":'rgba(50, 145, 248, 100)',"color":"rgba(3, 102, 214, 100)","border-radius":"5px","border-shadow":"none"}) | |||||
}); | }); | ||||
</script> | </script> |
@@ -280,9 +280,9 @@ | |||||
<!-- 任务名 --> | <!-- 任务名 --> | ||||
<div class="six wide column"> | <div class="six wide column"> | ||||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 15px;"> | |||||
<span class="fitted" style="vertical-align: middle;">{{svg "octicon-tasklist" 16}}</span> | |||||
<span class="fitted" style="width: 90%;vertical-align: middle;margin-left: 0.4rem;">{{.JobName}}</span> | |||||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 14px;"> | |||||
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||||
</a> | </a> | ||||
</div> | </div> | ||||
@@ -352,11 +352,11 @@ | |||||
<form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post"> | <form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post"> | ||||
{{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | {{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | ||||
<a id="model-delete-{{.JobID}}" class="ui compact {{if eq .Status "RUNNING" "CREATING" "WAITING" "STARTING" "STOPPING" }}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||||
<a id="model-delete-{{.JobID}}" class="ui basic blue button {{if eq .Status "RUNNING" "CREATING" "WAITING" "STARTING" "STOPPING" }}disabled {{end}}" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||||
{{$.i18n.Tr "repo.delete"}} | {{$.i18n.Tr "repo.delete"}} | ||||
</a> | </a> | ||||
{{else}} | {{else}} | ||||
<a class="ui compact disabled button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||||
<a class="ui basic blue button disabled" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||||
{{$.i18n.Tr "repo.delete"}} | {{$.i18n.Tr "repo.delete"}} | ||||
</a> | </a> | ||||
{{end}} | {{end}} | ||||
@@ -321,9 +321,9 @@ | |||||
<!-- 任务名 --> | <!-- 任务名 --> | ||||
<div class="three wide column padding0"> | <div class="three wide column padding0"> | ||||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 12px;"> | |||||
<span class="fitted" style="vertical-align: middle;">{{svg "octicon-tasklist" 16}}</span> | |||||
<span class="fitted" style="width: 90%;vertical-align: middle;margin-left: 0.4rem;">{{.JobName}}</span> | |||||
<a class="title" href="{{$.Link}}/{{.JobID}}" title="{{.JobName}}" style="font-size: 14px;"> | |||||
<span class="fitted" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | |||||
</a> | </a> | ||||
</div> | </div> | ||||
<!-- 版本数量 --> | <!-- 版本数量 --> | ||||
@@ -366,8 +366,9 @@ | |||||
</div> | </div> | ||||
<div class="three wide column text center padding0"> | <div class="three wide column text center padding0"> | ||||
<div class="ui compact buttons"> | |||||
<form id="stopForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/stop" method="post"> | |||||
<!-- <div class="ui compact buttons"> | |||||
<form id="stopForm-{{.JobID}}" action="/api/v1/repos{{$.Link}}/{{.JobID}}/stop_version" method="post"> | |||||
<input type="hidden" name="version_name" value="{{.VersionName}}"> | |||||
{{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | {{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | ||||
<a style="padding: 0.5rem 1rem;" id="stop-model-debug-{{.JobID}}" class="ui basic {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED"}}disabled {{else}}blue {{end}}button" onclick="document.getElementById('stopForm-{{.JobID}}').submit();"> | <a style="padding: 0.5rem 1rem;" id="stop-model-debug-{{.JobID}}" class="ui basic {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED"}}disabled {{else}}blue {{end}}button" onclick="document.getElementById('stopForm-{{.JobID}}').submit();"> | ||||
@@ -379,7 +380,7 @@ | |||||
</a> | </a> | ||||
{{end}} | {{end}} | ||||
</form> | </form> | ||||
</div> | |||||
</div> --> | |||||
<!-- 模型下载 --> | <!-- 模型下载 --> | ||||
<!-- <div class="ui compact buttons"> | <!-- <div class="ui compact buttons"> | ||||
<a style="padding: 0.5rem;" class="ui basic blue button" href="{{$.Link}}/{{.JobID}}/models" target="_blank"> | <a style="padding: 0.5rem;" class="ui basic blue button" href="{{$.Link}}/{{.JobID}}/models" target="_blank"> | ||||
@@ -387,14 +388,27 @@ | |||||
</a> | </a> | ||||
</div> --> | </div> --> | ||||
<!-- 删除任务 --> | <!-- 删除任务 --> | ||||
<div class="ui compact buttons"> | |||||
{{$.CsrfTokenHtml}} | |||||
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | |||||
<a style="padding: 0.5rem 1rem;" id="{{.VersionName}}-stop" class="ui basic {{if eq .Status "KILLED" "FAILED" "START_FAILED" "KILLING" "COMPLETED"}}disabled {{else}} blue {{end}}button" onclick="stopVersion({{.VersionName}},{{.JobID}})"> | |||||
{{$.i18n.Tr "repo.stop"}} | |||||
</a> | |||||
{{else}} | |||||
<a style="padding: 0.5rem 1rem;" id="{{.VersionName}}-stop" class="ui basic disabled button"> | |||||
{{$.i18n.Tr "repo.stop"}} | |||||
</a> | |||||
{{end}} | |||||
</div> | |||||
<form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post"> | <form class="ui compact buttons" id="delForm-{{.JobID}}" action="{{$.Link}}/{{.JobID}}/del" method="post"> | ||||
{{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
{{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | {{if $.Permission.CanWrite $.UnitTypeCloudBrain}} | ||||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="model-delete-{{.JobID}}" class="ui compact {{if or (eq .Status "RUNNING") (eq .Status "INIT") (eq .Status "CREATING") (eq .Status "WAITING") }}disabled {{else}}red {{end}}button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="model-delete-{{.JobID}}" class="ui basic blue button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||||
{{$.i18n.Tr "repo.delete"}} | {{$.i18n.Tr "repo.delete"}} | ||||
</a> | </a> | ||||
{{else}} | {{else}} | ||||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" class="ui compact disabled button" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||||
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" class="ui basic button disabled" onclick="assertDelete(this)" style="border-radius: .28571429rem;"> | |||||
{{$.i18n.Tr "repo.delete"}} | {{$.i18n.Tr "repo.delete"}} | ||||
</a> | </a> | ||||
{{end}} | {{end}} | ||||
@@ -527,33 +541,7 @@ | |||||
$('#' + jobID+ '-text').text(status) | $('#' + jobID+ '-text').text(status) | ||||
} | } | ||||
if(status==="RUNNING"){ | |||||
$('#model-debug-'+jobID).removeClass('disabled') | |||||
$('#model-debug-'+jobID).addClass('blue') | |||||
// $('#duration-'+jobID).text(duration) | |||||
} | |||||
if(status!=="RUNNING"){ | |||||
$('#model-debug-'+jobID).removeClass('blue') | |||||
$('#model-debug-'+jobID).addClass('disabled') | |||||
} | |||||
if(status!=="KILLED" || status!=="FAILED"){ | |||||
$('#stop-model-debug-'+jobID).removeClass('disabled') | |||||
$('#stop-model-debug-'+jobID).addClass('blue') | |||||
$('#model-delete-'+jobID).removeClass('red') | |||||
$('#model-delete-'+jobID).addClass('disabled') | |||||
} | |||||
if(status=="KILLED" || status=="FAILED" || status=="KILLING" || status=="COMPLETED"){ | |||||
$('#stop-model-debug-'+jobID).removeClass('blue') | |||||
$('#stop-model-debug-'+jobID).addClass('disabled') | |||||
$('#model-delete-'+jobID).removeClass('disabled') | |||||
$('#model-delete-'+jobID).addClass('red') | |||||
} | |||||
if(status=="START_FAILED"){ | |||||
$('#stop-model-debug-'+jobID).removeClass('blue') | |||||
$('#stop-model-debug-'+jobID).addClass('disabled') | |||||
} | |||||
}).fail(function(err) { | }).fail(function(err) { | ||||
console.log(err); | console.log(err); | ||||
}); | }); | ||||
@@ -589,7 +577,36 @@ | |||||
modal.style.display = "none"; | modal.style.display = "none"; | ||||
} | } | ||||
} | } | ||||
function stopVersion(version_name,jobID){ | |||||
const url = '/api/v1/repos/{{$.RepoRelPath}}/modelarts/train-job/'+jobID+'/stop_version' | |||||
$.post(url,{version_name:version_name},(data)=>{ | |||||
if(data.StatusOK===0){ | |||||
$('#'+version_name+'-stop').removeClass('blue') | |||||
$('#'+version_name+'-stop').addClass('disabled') | |||||
refreshStatus(version_name,jobID) | |||||
} | |||||
}).fail(function(err) { | |||||
console.log(err); | |||||
}); | |||||
} | |||||
function refreshStatus(version_name,jobID){ | |||||
const url = '/api/v1/repos/{{$.RepoRelPath}}/modelarts/train-job/'+jobID+'?version_name='+version_name | |||||
$.get(url,(data)=>{ | |||||
$(`#${jobID}-icon`).attr("class",data.JobStatus) | |||||
// detail status and duration | |||||
$(`#${jobID}-text`).text(data.JobStatus) | |||||
}).fail(function(err) { | |||||
console.log(err); | |||||
}); | |||||
} | |||||
// 显示弹窗,弹出相应的信息 | // 显示弹窗,弹出相应的信息 | ||||
function showmask() { | function showmask() { | ||||
$('#imageModal').css('display', 'none') | $('#imageModal').css('display', 'none') | ||||
@@ -159,12 +159,12 @@ | |||||
<input type="hidden" id="ai_flaver_name" name="flaver_names" value=""> | <input type="hidden" id="ai_flaver_name" name="flaver_names" value=""> | ||||
<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | <h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | ||||
<div class="required unite min_title inline field"> | <div class="required unite min_title inline field"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||||
<input style="width: 60%;" name="job_name" id="trainjob_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.job_name}}" tabindex="3" autofocus required maxlength="255"> | <input style="width: 60%;" name="job_name" id="trainjob_job_name" placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.job_name}}" tabindex="3" autofocus required maxlength="255"> | ||||
</div> | </div> | ||||
<div class="unite min_title inline field"> | <div class="unite min_title inline field"> | ||||
<label for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}} </label> | |||||
<label style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}} </label> | |||||
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="255" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 256)"></textarea> | <textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="255" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 256)"></textarea> | ||||
</div> | </div> | ||||
<div class="ui divider"></div> | <div class="ui divider"></div> | ||||
@@ -173,8 +173,11 @@ | |||||
<div class="required unite min_title inline field"> | <div class="required unite min_title inline field"> | ||||
<label>{{.i18n.Tr "repo.modelarts.code_version"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label> | |||||
<select class="ui dropdown width80 left2" id="code_version" name="branch_name"> | <select class="ui dropdown width80 left2" id="code_version" name="branch_name"> | ||||
{{if .branch_name}} | |||||
<option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option> | |||||
{{end}} | |||||
{{range $k, $v :=.Branches}} | {{range $k, $v :=.Branches}} | ||||
<option name="branch_name" value="{{$v}}">{{$v}}</option> | <option name="branch_name" value="{{$v}}">{{$v}}</option> | ||||
{{end}} | {{end}} | ||||
@@ -184,7 +187,7 @@ | |||||
<div class="required unite min_title inline fields" style="width: 90%;"> | <div class="required unite min_title inline fields" style="width: 90%;"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </label> | |||||
<div class="field" style="flex: 1.5;"> | <div class="field" style="flex: 1.5;"> | ||||
<select class="ui dropdown width" id="trainjob_engines" > | <select class="ui dropdown width" id="trainjob_engines" > | ||||
{{range .engines}} | {{range .engines}} | ||||
@@ -205,7 +208,7 @@ | |||||
</div> | </div> | ||||
<div class="inline unite min_title field required"> | <div class="inline unite min_title field required"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||||
{{if .bootFile}} | {{if .bootFile}} | ||||
<input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" > | <input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="{{.bootFile}}" tabindex="3" autofocus required maxlength="255" > | ||||
{{else}} | {{else}} | ||||
@@ -216,7 +219,7 @@ | |||||
</span> | </span> | ||||
</div> | </div> | ||||
<div class="required unite min_title inline field"> | <div class="required unite min_title inline field"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label> | |||||
<select class="ui dropdown width80" id="trainjob_datasets" name="attachment" placeholder="选择数据集"> | <select class="ui dropdown width80" id="trainjob_datasets" name="attachment" placeholder="选择数据集"> | ||||
{{if $.uuid}} | {{if $.uuid}} | ||||
<option name="attachment" value="{{$.uuid}}">{{$.datasetName}}</option> | <option name="attachment" value="{{$.uuid}}">{{$.datasetName}}</option> | ||||
@@ -229,15 +232,32 @@ | |||||
</div> | </div> | ||||
<div class="inline unite min_title field"> | <div class="inline unite min_title field"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||||
<span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | <span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | ||||
<input id="store_run_para" type="hidden" name="run_para_list"> | <input id="store_run_para" type="hidden" name="run_para_list"> | ||||
<div class="dynamic field" style="margin-top: 1rem;"></div> | |||||
<div class="dynamic field" style="margin-top: 1rem;"> | |||||
{{if ne 0 (len .params)}} | |||||
{{range $k ,$v := .params}} | |||||
<div class="two fields width85" id="para{{$k}}"> | |||||
<div class="field"> | |||||
<input type="text" name="shipping_first-name" value={{$v.Label}} required> | |||||
</div> | |||||
<div class="field"> | |||||
<input type="text" name="shipping_last-name" value={{$v.Value}} required> | |||||
</div> | |||||
<span> | |||||
<i class="trash icon"></i> | |||||
</span> | |||||
</div> | |||||
{{end}} | |||||
{{end}} | |||||
</div> | |||||
</div> | </div> | ||||
<div class="required field " style="display: none;"> | <div class="required field " style="display: none;"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label> | |||||
<select class="ui dropdown" id="trainjob_resource_pool" style='width:385px' name="pool_id"> | <select class="ui dropdown" id="trainjob_resource_pool" style='width:385px' name="pool_id"> | ||||
{{range .resource_pools}} | {{range .resource_pools}} | ||||
<option value="{{.ID}}">{{.Value}}</option> | <option value="{{.ID}}">{{.Value}}</option> | ||||
@@ -246,7 +266,7 @@ | |||||
</div> | </div> | ||||
<div class="required grouped fields" style="display: none;"> | <div class="required grouped fields" style="display: none;"> | ||||
<label for="resource_type">{{.i18n.Tr "repo.modelarts.train_job.resource_type"}}</label> | |||||
<label style="font-weight: normal;" for="resource_type">{{.i18n.Tr "repo.modelarts.train_job.resource_type"}}</label> | |||||
<div class="field"> | <div class="field"> | ||||
<div class="ui grid"> | <div class="ui grid"> | ||||
<div class="column"> | <div class="column"> | ||||
@@ -262,7 +282,7 @@ | |||||
</div> | </div> | ||||
<div class="required unite min_title inline field" id="flaver_name"> | <div class="required unite min_title inline field" id="flaver_name"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||||
<select class="ui dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor"> | <select class="ui dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor"> | ||||
{{range .flavor_infos}} | {{range .flavor_infos}} | ||||
<option name="flavor" value="{{.Code}}">{{.Value}}</option> | <option name="flavor" value="{{.Code}}">{{.Value}}</option> | ||||
@@ -270,7 +290,7 @@ | |||||
</select> | </select> | ||||
</div> | </div> | ||||
<div class="inline required unite min_title field"> | <div class="inline required unite min_title field"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label> | |||||
<div class="ui labeled input" style="width: 5%;"> | <div class="ui labeled input" style="width: 5%;"> | ||||
@@ -38,7 +38,7 @@ | |||||
<!-- 任务名 --> | <!-- 任务名 --> | ||||
<div class="five wide column"> | <div class="five wide column"> | ||||
<a class="title" href="{{$.Link}}/{{.JobID}}"> | <a class="title" href="{{$.Link}}/{{.JobID}}"> | ||||
<span class="fitted">{{svg "octicon-tasklist" 16}}</span> | |||||
<span class="fitted">{{.JobName}}</span> | <span class="fitted">{{.JobName}}</span> | ||||
</a> | </a> | ||||
</div> | </div> | ||||
@@ -226,9 +226,9 @@ td, th { | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="{{if eq $k 0}}active{{end}} content accordion-border"> | |||||
<div class="{{if eq $k 0}}active{{end}} content"> | |||||
<div class="content-pad"> | <div class="content-pad"> | ||||
<div class="ui pointing secondary menu"> | |||||
<div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | |||||
<a class="active item" data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | <a class="active item" data-tab="first{{$k}}">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | ||||
<a class="item" data-tab="second{{$k}}" onclick="loadLog({{.VersionName}})">{{$.i18n.Tr "repo.modelarts.log"}}</a> | <a class="item" data-tab="second{{$k}}" onclick="loadLog({{.VersionName}})">{{$.i18n.Tr "repo.modelarts.log"}}</a> | ||||
@@ -414,17 +414,14 @@ td, th { | |||||
<div class="ui message message{{.VersionName}}" style="display: none;"> | <div class="ui message message{{.VersionName}}" style="display: none;"> | ||||
<div id="header"></div> | <div id="header"></div> | ||||
</div> | </div> | ||||
<div class="ui top attached segment" style="background: #f0f0f0;"> | |||||
<!-- <div class="ui top attached segment" style="background: #f0f0f0;"> | |||||
<div class="center aligned"> | <div class="center aligned"> | ||||
<label>{{$.i18n.Tr "repo.modelarts.log"}}:</label> | <label>{{$.i18n.Tr "repo.modelarts.log"}}:</label> | ||||
<!-- <span class="fitted file_name">{{.}}</span> --> | |||||
<!-- <input type="hidden" name="file_name" value> | |||||
<input type="hidden" name="start_line" value> | |||||
<input type="hidden" name="end_line" value> --> | |||||
</div> | </div> | ||||
</div> | |||||
<div class="ui attached segment log" onscroll="logScroll({{.VersionName}})" id="log{{.VersionName}}" style="height: 300px !important; overflow: auto;"> | |||||
</div> --> | |||||
<div class="ui attached log" onscroll="logScroll({{.VersionName}})" id="log{{.VersionName}}" style="height: 300px !important; overflow: auto;"> | |||||
<!-- <input type="hidden" class="version_name" name="version_name" value={{.VersionName}}> --> | <!-- <input type="hidden" class="version_name" name="version_name" value={{.VersionName}}> --> | ||||
<input type="hidden" name="end_line" value> | <input type="hidden" name="end_line" value> | ||||
<input type="hidden" name="start_line" value> | <input type="hidden" name="start_line" value> | ||||
@@ -660,6 +657,12 @@ td, th { | |||||
} | } | ||||
} | } | ||||
function downloadModelFile(version_name,parentDir,filename){ | |||||
$.get(`/api/v1/repos/${userName}/${repoPath}/modelarts/train-job/${jobID}/model_download?version_name=${version_name}&file_name=${filename}`, (data) => { | |||||
console.log(data) | |||||
}) | |||||
} | |||||
function renderDir(data,version_name){ | function renderDir(data,version_name){ | ||||
let html="" | let html="" | ||||
html += "<div class='ui grid' style='margin:0;'>" | html += "<div class='ui grid' style='margin:0;'>" | ||||
@@ -677,10 +680,10 @@ td, th { | |||||
html += "<span class='octicon octicon-file-directory'>" | html += "<span class='octicon octicon-file-directory'>" | ||||
html += "</span>" | html += "</span>" | ||||
if(data.Dirs[i].IsDir){ | if(data.Dirs[i].IsDir){ | ||||
html += `<a onclick="loadModelFile('${version_name}','${data.Dirs[i].ParenDir}','${data.Dirs[i].FileName}','folder')">` | |||||
html += `<a onclick="loadModelFile('${version_name}','${data.Dirs[i].ParenDir}','${data.Dirs[i].ParenDir}','folder')">` | |||||
html += "<span class='fitted'><i class='folder icon' width='16' height='16' aria-hidden='true'></i>" + data.Dirs[i].FileName + "</span>" | html += "<span class='fitted'><i class='folder icon' width='16' height='16' aria-hidden='true'></i>" + data.Dirs[i].FileName + "</span>" | ||||
}else{ | }else{ | ||||
html += `<a href='${location.href}/download_model?parentDir=&fileName=${data.Dirs[i].FileName}&jobName=${data.task.JobName}'>` | |||||
html += `<a onclick="downloadModelFile('${version_name}','${data.Dirs[i].ParenDir}','${data.Dirs[i].ParenDir}')">` | |||||
html += "<span class='fitted'><i class='file icon' width='16' height='16' aria-hidden='true'></i>" + data.Dirs[i].FileName + "</span>" | html += "<span class='fitted'><i class='file icon' width='16' height='16' aria-hidden='true'></i>" + data.Dirs[i].FileName + "</span>" | ||||
} | } | ||||
html += '</a>' | html += '</a>' | ||||
@@ -161,18 +161,18 @@ | |||||
<input type="hidden" id="ai_flaver_name" name="flaver_names" value=""> | <input type="hidden" id="ai_flaver_name" name="flaver_names" value=""> | ||||
<h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | <h4 class="unite title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4> | ||||
<div class="required unite min_title inline field"> | <div class="required unite min_title inline field"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label> | |||||
<input type="hidden" style="width: 60%;" name="job_name" id="trainjob_job_name" value="{{.job_name}}"> | <input type="hidden" style="width: 60%;" name="job_name" id="trainjob_job_name" value="{{.job_name}}"> | ||||
<input style="width: 60%;" value="{{.job_name}}" tabindex="3" disabled > | <input style="width: 60%;" value="{{.job_name}}" tabindex="3" disabled > | ||||
</div> | </div> | ||||
<div class="required unite min_title inline field"> | <div class="required unite min_title inline field"> | ||||
<label>{{.i18n.Tr "repo.modelarts.parents_version"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.parents_version"}}</label> | |||||
<input id="parents_version" style="width: 60%;" value="" tabindex="3" disabled > | <input id="parents_version" style="width: 60%;" value="" tabindex="3" disabled > | ||||
</div> | </div> | ||||
<div class="unite min_title inline field"> | <div class="unite min_title inline field"> | ||||
<label for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}} </label> | |||||
<label style="font-weight: normal;" for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}} </label> | |||||
<textarea style="width: 80%;" id="description" value="{{.description}}" name="description" rows="3" maxlength="255" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 256)">{{.description}}</textarea> | <textarea style="width: 80%;" id="description" value="{{.description}}" name="description" rows="3" maxlength="255" placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}} onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 256)">{{.description}}</textarea> | ||||
</div> | </div> | ||||
<div class="ui divider"></div> | <div class="ui divider"></div> | ||||
@@ -181,7 +181,7 @@ | |||||
<div class="required unite min_title inline field"> | <div class="required unite min_title inline field"> | ||||
<label>{{.i18n.Tr "repo.modelarts.code_version"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.code_version"}}</label> | |||||
<select class="ui dropdown width80 left2" id="code_version" name="branch_name"> | <select class="ui dropdown width80 left2" id="code_version" name="branch_name"> | ||||
{{if .branch_name}} | {{if .branch_name}} | ||||
<option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option> | <option name="branch_name" value="{{.branch_name}}">{{.branch_name}}</option> | ||||
@@ -198,7 +198,7 @@ | |||||
<div class="required unite min_title inline fields" style="width: 90%;"> | <div class="required unite min_title inline fields" style="width: 90%;"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.AI_driver"}} </label> | |||||
<div class="field" style="flex: 1.5;"> | <div class="field" style="flex: 1.5;"> | ||||
<select class="ui dropdown width" id="trainjob_engines" > | <select class="ui dropdown width" id="trainjob_engines" > | ||||
{{range .engines}} | {{range .engines}} | ||||
@@ -224,7 +224,7 @@ | |||||
</div> | </div> | ||||
<div class="inline unite min_title field required"> | <div class="inline unite min_title field required"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.start_file"}}</label> | |||||
{{if .boot_file}} | {{if .boot_file}} | ||||
<input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="{{.boot_file}}" tabindex="3" autofocus required maxlength="255" > | <input style="width: 33.5%;" name="boot_file" id="trainjob_boot_file" value="{{.boot_file}}" tabindex="3" autofocus required maxlength="255" > | ||||
{{else}} | {{else}} | ||||
@@ -235,7 +235,7 @@ | |||||
</span> | </span> | ||||
</div> | </div> | ||||
<div class="required unite min_title inline field"> | <div class="required unite min_title inline field"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.dataset"}}</label> | |||||
<select class="ui dropdown width80" id="trainjob_datasets" name="attachment" placeholder="选择数据集"> | <select class="ui dropdown width80" id="trainjob_datasets" name="attachment" placeholder="选择数据集"> | ||||
{{if .dataset_name}} | {{if .dataset_name}} | ||||
<option name="attachment" value="{{.uuid}}">{{.dataset_name}}</option> | <option name="attachment" value="{{.uuid}}">{{.dataset_name}}</option> | ||||
@@ -250,7 +250,7 @@ | |||||
</div> | </div> | ||||
<div class="inline unite min_title field"> | <div class="inline unite min_title field"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</label> | |||||
<span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | <span id="add_run_para" style="margin-left: 0.5rem;cursor:pointer;color: rgba(3, 102, 214, 100);font-size: 14px;line-height: 26px;font-family: SourceHanSansSC-medium;"><i class="plus square outline icon"></i>{{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}</span> | ||||
<input id="store_run_para" type="hidden" name="run_para_list"> | <input id="store_run_para" type="hidden" name="run_para_list"> | ||||
<div class="dynamic field" style="margin-top: 1rem;"> | <div class="dynamic field" style="margin-top: 1rem;"> | ||||
@@ -275,7 +275,7 @@ | |||||
<div class="required field " style="display: none;"> | <div class="required field " style="display: none;"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.resource_pool"}}</label> | |||||
<select class="ui dropdown" id="trainjob_resource_pool" style='width:385px' name="pool_id"> | <select class="ui dropdown" id="trainjob_resource_pool" style='width:385px' name="pool_id"> | ||||
{{range .resource_pools}} | {{range .resource_pools}} | ||||
<option value="{{.ID}}">{{.Value}}</option> | <option value="{{.ID}}">{{.Value}}</option> | ||||
@@ -284,7 +284,7 @@ | |||||
</div> | </div> | ||||
<div class="required grouped fields" style="display: none;"> | <div class="required grouped fields" style="display: none;"> | ||||
<label for="resource_type">{{.i18n.Tr "repo.modelarts.train_job.resource_type"}}</label> | |||||
<label style="font-weight: normal;" for="resource_type">{{.i18n.Tr "repo.modelarts.train_job.resource_type"}}</label> | |||||
<div class="field"> | <div class="field"> | ||||
<div class="ui grid"> | <div class="ui grid"> | ||||
<div class="column"> | <div class="column"> | ||||
@@ -300,7 +300,7 @@ | |||||
</div> | </div> | ||||
<div class="required unite min_title inline field" id="flaver_name"> | <div class="required unite min_title inline field" id="flaver_name"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.standard"}}</label> | |||||
<select class="ui dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor"> | <select class="ui dropdown width81" id="trainjob-flavor" style='width:385px' name="flavor"> | ||||
{{if .flavor_name}} | {{if .flavor_name}} | ||||
<option name="flavor" value="{{.flavor_code}}">{{.flavor_name}}</option> | <option name="flavor" value="{{.flavor_code}}">{{.flavor_name}}</option> | ||||
@@ -313,7 +313,7 @@ | |||||
</select> | </select> | ||||
</div> | </div> | ||||
<div class="inline required unite min_title field"> | <div class="inline required unite min_title field"> | ||||
<label>{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label> | |||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.amount_of_compute_node"}}</label> | |||||
<div class="ui labeled input" style="width: 5%;"> | <div class="ui labeled input" style="width: 5%;"> | ||||
@@ -291,9 +291,28 @@ footer .column{margin-bottom:0!important; padding-bottom:0!important;} | |||||
display: inline-block; | display: inline-block; | ||||
margin-top: 4px; | margin-top: 4px; | ||||
} | } | ||||
.hover_active{ | |||||
} | |||||
.dropdown-menu:hover .dropdown-content { | .dropdown-menu:hover .dropdown-content { | ||||
display: block; | display: block; | ||||
} | } | ||||
.dropdown-menu:hover .hover_active { | |||||
background: #fff !important; | |||||
border-color: #d4d4d5 !important; | |||||
font-weight: 700 !important; | |||||
// margin-bottom: -1px; | |||||
-webkit-box-shadow: none !important; | |||||
box-shadow: none !important; | |||||
border-radius: .28571429rem .28571429rem 0 0!important; | |||||
color: rgba(0,0,0,.95); | |||||
border-top-width: 1px; | |||||
} | |||||
.dropdown-menu:hover .dropdown-content { | |||||
display: block; | |||||
} | |||||
.dropdown-content{ | .dropdown-content{ | ||||
display: none; | display: none; | ||||
position: absolute; | position: absolute; | ||||