@@ -1,13 +1,19 @@ | |||
package modelarts | |||
import ( | |||
"encoding/base64" | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
"io/ioutil" | |||
"net/http" | |||
"os" | |||
"path" | |||
"strconv" | |||
"strings" | |||
"code.gitea.io/gitea/modules/cloudbrain" | |||
"code.gitea.io/gitea/modules/modelarts_cd" | |||
"code.gitea.io/gitea/models" | |||
@@ -276,7 +282,7 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description, flavor strin | |||
return nil | |||
} | |||
func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification) error { | |||
func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification, bootFile string) (string, error) { | |||
if poolInfos == nil { | |||
json.Unmarshal([]byte(setting.PoolInfos), &poolInfos) | |||
} | |||
@@ -284,7 +290,7 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc | |||
imageName, err := GetNotebookImageName(imageId) | |||
if err != nil { | |||
log.Error("GetNotebookImageName failed: %v", err.Error()) | |||
return err | |||
return "", err | |||
} | |||
createTime := timeutil.TimeStampNow() | |||
jobResult, err := createNotebook2(models.CreateNotebook2Params{ | |||
@@ -316,10 +322,10 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc | |||
}) | |||
if errTemp != nil { | |||
log.Error("InsertCloudbrainTemp failed: %v", errTemp.Error()) | |||
return errTemp | |||
return "", errTemp | |||
} | |||
} | |||
return err | |||
return "", err | |||
} | |||
task := &models.Cloudbrain{ | |||
Status: jobResult.Status, | |||
@@ -334,6 +340,7 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc | |||
Uuid: uuid, | |||
ComputeResource: models.NPUResource, | |||
Image: imageName, | |||
BootFile: bootFile, | |||
Description: description, | |||
CreatedUnix: createTime, | |||
UpdatedUnix: createTime, | |||
@@ -342,12 +349,12 @@ func GenerateNotebook2(ctx *context.Context, displayJobName, jobName, uuid, desc | |||
err = models.CreateCloudbrain(task) | |||
if err != nil { | |||
return err | |||
return "", err | |||
} | |||
stringId := strconv.FormatInt(task.ID, 10) | |||
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugNPUTask) | |||
return nil | |||
return jobResult.ID, nil | |||
} | |||
func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (jobId string, err error) { | |||
@@ -907,6 +914,11 @@ func HandleNotebookInfo(task *models.Cloudbrain) error { | |||
if task.FlavorCode == "" { | |||
task.FlavorCode = result.Flavor | |||
} | |||
if oldStatus != task.Status && task.Status == string(models.ModelArtsRunning) && task.BootFile != "" { | |||
uploadNoteBookFile(task, result) | |||
} | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.DisplayJobName, err) | |||
@@ -917,6 +929,51 @@ func HandleNotebookInfo(task *models.Cloudbrain) error { | |||
return nil | |||
} | |||
func uploadNoteBookFile(task *models.Cloudbrain, result *models.GetNotebook2Result) { | |||
jupyterUrl := result.Url + "?token=" + result.Token | |||
client := getRestyClient() | |||
res, err := client.R().Get(jupyterUrl) | |||
codePath := setting.JobPath + task.JobName + cloudbrain.CodeMountPath | |||
if err != nil { | |||
log.Error("browser jupyterUrl failed:%v", task.DisplayJobName, err) | |||
} else { | |||
cookies := res.Cookies() | |||
xsrf := "" | |||
for _, cookie := range cookies { | |||
if cookie.Name == "_xsrf" { | |||
xsrf = cookie.Value | |||
} | |||
} | |||
fileContents, err := ioutil.ReadFile(codePath + "/" + task.BootFile) | |||
if err != nil { | |||
log.Error("read jupyter file failed:%v", task.DisplayJobName, err) | |||
} | |||
base64Content := base64.StdEncoding.EncodeToString(fileContents) | |||
uploadUrl := result.Url + "/api/contents/" + path.Base(task.BootFile) | |||
res, err = client.R(). | |||
SetCookies(cookies). | |||
SetHeader("X-XSRFToken", xsrf). | |||
SetBody(map[string]interface{}{ | |||
"type": "file", | |||
"format": "base64", | |||
"name": path.Base(task.BootFile), | |||
"path": path.Base(task.BootFile), | |||
"content": base64Content}). | |||
Put(uploadUrl) | |||
if err != nil { | |||
log.Error("upload jupyter file failed:%v", task.DisplayJobName, err) | |||
} else if res.StatusCode() != http.StatusCreated { | |||
log.Error("upload jupyter file failed:%v", task.DisplayJobName, err) | |||
} | |||
} | |||
go os.RemoveAll(codePath) | |||
} | |||
func SyncTempStatusJob() { | |||
jobs, err := models.GetCloudBrainTempJobs() | |||
if err != nil { | |||
@@ -88,11 +88,11 @@ type Parameters struct { | |||
} `json:"parameter"` | |||
} | |||
func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification) error { | |||
func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, description, imageId string, spec *models.Specification, bootFile string) (string, error) { | |||
imageName, err := GetNotebookImageName(imageId) | |||
if err != nil { | |||
log.Error("GetNotebookImageName failed: %v", err.Error()) | |||
return err | |||
return "", err | |||
} | |||
createTime := timeutil.TimeStampNow() | |||
jobResult, err := createNotebook(models.CreateNotebookWithoutPoolParams{ | |||
@@ -123,10 +123,10 @@ func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, descr | |||
}) | |||
if errTemp != nil { | |||
log.Error("InsertCloudbrainTemp failed: %v", errTemp.Error()) | |||
return errTemp | |||
return "", errTemp | |||
} | |||
} | |||
return err | |||
return "", err | |||
} | |||
task := &models.Cloudbrain{ | |||
Status: jobResult.Status, | |||
@@ -145,16 +145,17 @@ func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, descr | |||
CreatedUnix: createTime, | |||
UpdatedUnix: createTime, | |||
Spec: spec, | |||
BootFile: bootFile, | |||
} | |||
err = models.CreateCloudbrain(task) | |||
if err != nil { | |||
return err | |||
return "", err | |||
} | |||
stringId := strconv.FormatInt(task.ID, 10) | |||
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugNPUTask) | |||
return nil | |||
return jobResult.ID, nil | |||
} | |||
func GetNotebookImageName(imageId string) (string, error) { | |||
@@ -175,41 +176,3 @@ func GetNotebookImageName(imageId string) (string, error) { | |||
return imageName, nil | |||
} | |||
/* | |||
func HandleNotebookInfo(task *models.Cloudbrain) error { | |||
result, err := GetNotebook(task.JobID) | |||
if err != nil { | |||
log.Error("GetNotebook2(%s) failed:%v", task.DisplayJobName, err) | |||
return err | |||
} | |||
if result != nil { | |||
oldStatus := task.Status | |||
task.Status = result.Status | |||
if task.StartTime == 0 && result.Lease.UpdateTime > 0 { | |||
task.StartTime = timeutil.TimeStamp(result.Lease.UpdateTime / 1000) | |||
} | |||
if task.EndTime == 0 && models.IsModelArtsDebugJobTerminal(task.Status) { | |||
task.EndTime = timeutil.TimeStampNow() | |||
} | |||
task.CorrectCreateUnix() | |||
task.ComputeAndSetDuration() | |||
if oldStatus != task.Status { | |||
notification.NotifyChangeCloudbrainStatus(task, oldStatus) | |||
} | |||
if task.FlavorCode == "" { | |||
task.FlavorCode = result.Flavor | |||
} | |||
err = models.UpdateJob(task) | |||
if err != nil { | |||
log.Error("UpdateJob(%s) failed:%v", task.DisplayJobName, err) | |||
return err | |||
} | |||
} | |||
return nil | |||
} | |||
*/ |
@@ -609,9 +609,9 @@ var ( | |||
AiCenterInfo string | |||
}{} | |||
C2NetInfos *C2NetSqInfos | |||
CenterInfos *AiCenterInfos | |||
C2NetMapInfo map[string]*C2NetSequenceInfo | |||
C2NetInfos *C2NetSqInfos | |||
CenterInfos *AiCenterInfos | |||
C2NetMapInfo map[string]*C2NetSequenceInfo | |||
//elk config | |||
ElkUrl string | |||
@@ -712,6 +712,16 @@ var ( | |||
TeamName string | |||
}{} | |||
FileNoteBook = struct { | |||
ProjectName string | |||
ImageGPU string | |||
SpecIdGPU int64 | |||
SpecIdCPU int64 | |||
ImageIdNPU string | |||
ImageNPU string | |||
SpecIdNPU int64 | |||
}{} | |||
ModelConvert = struct { | |||
GPU_PYTORCH_IMAGE string | |||
GpuQueue string | |||
@@ -1655,9 +1665,9 @@ func getGrampusConfig() { | |||
if err := json.Unmarshal([]byte(Grampus.C2NetSequence), &C2NetInfos); err != nil { | |||
log.Error("Unmarshal(C2NetSequence) failed:%v", err) | |||
} | |||
C2NetMapInfo=make(map[string]*C2NetSequenceInfo) | |||
for _,value :=range C2NetInfos.C2NetSqInfo{ | |||
C2NetMapInfo[value.Name]=value | |||
C2NetMapInfo = make(map[string]*C2NetSequenceInfo) | |||
for _, value := range C2NetInfos.C2NetSqInfo { | |||
C2NetMapInfo[value.Name] = value | |||
} | |||
} | |||
Grampus.SyncScriptProject = sec.Key("SYNC_SCRIPT_PROJECT").MustString("script_for_grampus") | |||
@@ -41,6 +41,14 @@ type CreateTrainJobOption struct { | |||
SpecId int64 `json:"spec_id" binding:"Required"` | |||
} | |||
type CreateFileNotebookJobOption struct { | |||
Type int `json:"type"` //0 CPU 1 GPU 2 NPU | |||
File string `json:"file" binding:"Required"` | |||
BranchName string `json:"branch_name" binding:"Required"` | |||
OwnerName string `json:"owner_name" binding:"Required"` | |||
ProjectName string `json:"project_name" binding:"Required"` | |||
} | |||
type Cloudbrain struct { | |||
ID int64 `json:"id"` | |||
JobID string `json:"job_id"` | |||
@@ -1007,6 +1007,7 @@ readme = README | |||
readme_helper = Select a README file template. | |||
auto_init = Initialize Repository (Adds .gitignore, License and README) | |||
create_repo = Create Repository | |||
failed_to_create_repo=Failed to create repository, please try again later. | |||
create_course = Publish Course | |||
failed_to_create_course=Failed to publish course, please try again later. | |||
default_branch = Default Branch | |||
@@ -1041,6 +1042,9 @@ model_experience = Model Experience | |||
model_noright=You have no right to do the operation. | |||
model_rename=Duplicate model name, please modify model name. | |||
notebook_file_not_exist=Notebook file does not exist. | |||
notebook_select_wrong=Please select a Notebook(.ipynb) file first. | |||
date=Date | |||
repo_add=Project Increment | |||
repo_total=Project Total | |||
@@ -1013,6 +1013,7 @@ readme=自述 | |||
readme_helper=选择自述文件模板。 | |||
auto_init=初始化存储库 (添加. gitignore、许可证和自述文件) | |||
create_repo=创建项目 | |||
failed_to_create_repo=创建项目失败,请稍后再试。 | |||
create_course=发布课程 | |||
failed_to_create_course=发布课程失败,请稍后再试。 | |||
default_branch=默认分支 | |||
@@ -1041,6 +1042,8 @@ model_experience = 模型体验 | |||
model_noright=您没有操作权限。 | |||
model_rename=模型名称重复,请修改模型名称 | |||
notebook_file_not_exist=Notebook文件不存在。 | |||
notebook_select_wrong=请先选择Notebook(.ipynb)文件。 | |||
date=日期 | |||
repo_add=新增项目 | |||
@@ -736,6 +736,12 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Get("/my_favorite", repo.MyFavoriteDatasetMultiple) | |||
}, reqToken(), repoAssignment()) | |||
m.Group("/file_notebook", func() { | |||
m.Post("/create", reqToken(), reqWeChat(), bind(api.CreateFileNotebookJobOption{}), repo.CreateFileNoteBook) | |||
}) | |||
m.Group("/repos", func() { | |||
m.Get("/search", repo.Search) | |||
@@ -79,6 +79,9 @@ func CloudBrainShow(ctx *context.APIContext) { | |||
ctx.JSON(http.StatusOK, models.BaseMessageWithDataApi{Code: 0, Message: "", Data: convert.ToCloudBrain(task)}) | |||
} | |||
func CreateFileNoteBook(ctx *context.APIContext, option api.CreateFileNotebookJobOption) { | |||
cloudbrainTask.FileNotebookCreate(ctx.Context, option) | |||
} | |||
func CreateCloudBrain(ctx *context.APIContext, option api.CreateTrainJobOption) { | |||
if option.Type == cloudbrainTask.TaskTypeCloudbrainOne { | |||
@@ -11,7 +11,8 @@ import ( | |||
"os" | |||
"strconv" | |||
"strings" | |||
"time" | |||
cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/aisafety" | |||
@@ -483,7 +484,6 @@ func isTaskNotFinished(status string) bool { | |||
} | |||
func AiSafetyCreateForGetGPU(ctx *context.Context) { | |||
t := time.Now() | |||
ctx.Data["PageIsCloudBrain"] = true | |||
ctx.Data["IsCreate"] = true | |||
ctx.Data["type"] = models.TypeCloudBrainOne | |||
@@ -497,7 +497,7 @@ func AiSafetyCreateForGetGPU(ctx *context.Context) { | |||
log.Info("GPUBaseDataSetUUID=" + setting.ModelSafetyTest.GPUBaseDataSetUUID) | |||
log.Info("GPUCombatDataSetName=" + setting.ModelSafetyTest.GPUCombatDataSetName) | |||
log.Info("GPUCombatDataSetUUID=" + setting.ModelSafetyTest.GPUCombatDataSetUUID) | |||
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name) | |||
ctx.Data["display_job_name"] = displayJobName | |||
prepareCloudbrainOneSpecs(ctx) | |||
queuesDetail, _ := cloudbrain.GetQueuesDetail() | |||
@@ -514,12 +514,11 @@ func AiSafetyCreateForGetGPU(ctx *context.Context) { | |||
} | |||
func AiSafetyCreateForGetNPU(ctx *context.Context) { | |||
t := time.Now() | |||
ctx.Data["PageIsCloudBrain"] = true | |||
ctx.Data["IsCreate"] = true | |||
ctx.Data["type"] = models.TypeCloudBrainTwo | |||
ctx.Data["compute_resource"] = models.NPUResource | |||
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name) | |||
ctx.Data["display_job_name"] = displayJobName | |||
ctx.Data["datasetType"] = models.TypeCloudBrainTwo | |||
ctx.Data["BaseDataSetName"] = setting.ModelSafetyTest.NPUBaseDataSetName | |||
@@ -2,7 +2,6 @@ package repo | |||
import ( | |||
"bufio" | |||
"code.gitea.io/gitea/modules/urfs_client/urchin" | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
@@ -16,6 +15,10 @@ import ( | |||
"time" | |||
"unicode/utf8" | |||
cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||
"code.gitea.io/gitea/modules/urfs_client/urchin" | |||
"code.gitea.io/gitea/modules/dataset" | |||
"code.gitea.io/gitea/services/cloudbrain/cloudbrainTask" | |||
@@ -91,28 +94,9 @@ func MustEnableCloudbrain(ctx *context.Context) { | |||
} | |||
} | |||
func cutString(str string, lens int) string { | |||
if len(str) < lens { | |||
return str | |||
} | |||
return str[:lens] | |||
} | |||
func jobNamePrefixValid(s string) string { | |||
lowStr := strings.ToLower(s) | |||
re := regexp.MustCompile(`[^a-z0-9_\\-]+`) | |||
removeSpecial := re.ReplaceAllString(lowStr, "") | |||
re = regexp.MustCompile(`^[_\\-]+`) | |||
return re.ReplaceAllString(removeSpecial, "") | |||
} | |||
func cloudBrainNewDataPrepare(ctx *context.Context, jobType string) error { | |||
ctx.Data["PageIsCloudBrain"] = true | |||
t := time.Now() | |||
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name) | |||
ctx.Data["display_job_name"] = displayJobName | |||
ctx.Data["command"] = cloudbrain.GetCloudbrainDebugCommand() | |||
@@ -11,7 +11,6 @@ import ( | |||
"path" | |||
"strconv" | |||
"strings" | |||
"time" | |||
"code.gitea.io/gitea/services/cloudbrain/cloudbrainTask" | |||
@@ -75,8 +74,7 @@ func GrampusTrainJobNPUNew(ctx *context.Context) { | |||
func grampusTrainJobNewDataPrepare(ctx *context.Context, processType string) error { | |||
ctx.Data["PageIsCloudBrain"] = true | |||
t := time.Now() | |||
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name) | |||
ctx.Data["display_job_name"] = displayJobName | |||
//get valid images | |||
@@ -15,6 +15,8 @@ import ( | |||
"time" | |||
"unicode/utf8" | |||
cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||
"code.gitea.io/gitea/services/cloudbrain/cloudbrainTask" | |||
"code.gitea.io/gitea/modules/dataset" | |||
@@ -128,8 +130,7 @@ func NotebookNew(ctx *context.Context) { | |||
func notebookNewDataPrepare(ctx *context.Context) error { | |||
ctx.Data["PageIsCloudBrain"] = true | |||
t := time.Now() | |||
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name) | |||
ctx.Data["display_job_name"] = displayJobName | |||
attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||
@@ -239,9 +240,9 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm | |||
} | |||
if setting.ModelartsCD.Enabled { | |||
err = modelarts_cd.GenerateNotebook(ctx, displayJobName, jobName, uuid, description, imageId, spec) | |||
_, err = modelarts_cd.GenerateNotebook(ctx, displayJobName, jobName, uuid, description, imageId, spec, "") | |||
} else { | |||
err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, uuid, description, imageId, spec) | |||
_, err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, uuid, description, imageId, spec, "") | |||
} | |||
if err != nil { | |||
@@ -714,8 +715,7 @@ func trainJobNewDataPrepare(ctx *context.Context) error { | |||
// return | |||
//} | |||
t := time.Now() | |||
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name) | |||
ctx.Data["display_job_name"] = displayJobName | |||
attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||
@@ -2351,8 +2351,7 @@ func inferenceJobNewDataPrepare(ctx *context.Context) error { | |||
ctx.Data["PageIsCloudBrain"] = true | |||
ctx.Data["newInference"] = true | |||
t := time.Now() | |||
var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
var displayJobName = cloudbrainService.GetDisplayJobName(ctx.User.Name) | |||
ctx.Data["display_job_name"] = displayJobName | |||
attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||
@@ -0,0 +1,330 @@ | |||
package cloudbrainTask | |||
import ( | |||
"fmt" | |||
"net/http" | |||
"os" | |||
"code.gitea.io/gitea/modules/modelarts" | |||
"code.gitea.io/gitea/modules/modelarts_cd" | |||
"code.gitea.io/gitea/modules/git" | |||
"code.gitea.io/gitea/modules/cloudbrain" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/redis/redis_key" | |||
"code.gitea.io/gitea/modules/redis/redis_lock" | |||
"code.gitea.io/gitea/modules/storage" | |||
"code.gitea.io/gitea/services/cloudbrain/resource" | |||
"code.gitea.io/gitea/services/reward/point/account" | |||
"code.gitea.io/gitea/modules/setting" | |||
cloudbrainService "code.gitea.io/gitea/services/cloudbrain" | |||
repo_service "code.gitea.io/gitea/services/repository" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/context" | |||
api "code.gitea.io/gitea/modules/structs" | |||
"code.gitea.io/gitea/modules/util" | |||
) | |||
func FileNotebookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption) { | |||
if ctx.Written() { | |||
return | |||
} | |||
//create repo if not exist | |||
repo, err := models.GetRepositoryByName(ctx.User.ID, setting.FileNoteBook.ProjectName) | |||
if repo == nil { | |||
repo, err = repo_service.CreateRepository(ctx.User, ctx.User, models.CreateRepoOptions{ | |||
Name: setting.FileNoteBook.ProjectName, | |||
Alias: "", | |||
Description: "", | |||
IssueLabels: "", | |||
Gitignores: "", | |||
License: "", | |||
Readme: "Default", | |||
IsPrivate: false, | |||
AutoInit: true, | |||
DefaultBranch: "master", | |||
}) | |||
} | |||
if err != nil { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("repo.failed_to_create_repo")) | |||
} | |||
} | |||
func cloudBrainFileNoteBookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption, repo *models.Repository) { | |||
displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name) | |||
jobName := util.ConvertDisplayJobNameToJobName(displayJobName) | |||
jobType := string(models.JobTypeDebug) | |||
codePath := getCodePath(jobName) | |||
lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), jobType, displayJobName)) | |||
defer lock.UnLock() | |||
isOk, err := lock.Lock(models.CloudbrainKeyDuration) | |||
if !isOk { | |||
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err"))) | |||
return | |||
} | |||
tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName) | |||
if err == nil { | |||
if len(tasks) != 0 { | |||
log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err"))) | |||
return | |||
} | |||
} else { | |||
if !models.IsErrJobNotExist(err) { | |||
log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error.")) | |||
return | |||
} | |||
} | |||
count, err := GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType) | |||
if err != nil { | |||
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error.")) | |||
return | |||
} else { | |||
if count >= 1 { | |||
log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain.morethanonejob"))) | |||
return | |||
} | |||
} | |||
repoPath := models.RepoPath(repo.OwnerName, repo.Name) | |||
gitRepo, err := git.OpenRepository(repoPath) | |||
if err != nil { | |||
ctx.Error(500, "RepoRef Invalid repo "+repoPath, err.Error()) | |||
return | |||
} | |||
// We opened it, we should close it | |||
defer func() { | |||
// If it's been set to nil then assume someone else has closed it. | |||
if ctx.Repo.GitRepo != nil { | |||
ctx.Repo.GitRepo.Close() | |||
} | |||
}() | |||
ctx.Repo = &context.Repository{ | |||
Repository: repo, | |||
GitRepo: gitRepo, | |||
} | |||
fileExist, err := ctx.Repo.FileExists(option.File, option.BranchName) | |||
if err != nil || !fileExist { | |||
log.Error("Get file error:", err, ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist"))) | |||
return | |||
} | |||
command := cloudbrain.GetCloudbrainDebugCommand() | |||
errStr := uploadCodeFile(repo, codePath, option.BranchName, option.File, jobName) | |||
if errStr != "" { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist"))) | |||
return | |||
} | |||
commitID, _ := ctx.Repo.GitRepo.GetBranchCommitID(option.BranchName) | |||
specId := setting.FileNoteBook.SpecIdGPU | |||
if option.Type == 0 { | |||
specId = setting.FileNoteBook.SpecIdCPU | |||
} | |||
spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{ | |||
JobType: models.JobType(jobType), | |||
ComputeResource: models.GPU, | |||
Cluster: models.OpenICluster, | |||
AiCenterCode: models.AICenterOfCloudBrainOne}) | |||
if err != nil || spec == nil { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.wrong_specification"))) | |||
return | |||
} | |||
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) { | |||
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance"))) | |||
return | |||
} | |||
req := cloudbrain.GenerateCloudBrainTaskReq{ | |||
Ctx: ctx, | |||
DisplayJobName: displayJobName, | |||
JobName: jobName, | |||
Image: setting.FileNoteBook.ImageGPU, | |||
Command: command, | |||
Uuids: "", | |||
DatasetNames: "", | |||
DatasetInfos: nil, | |||
CodePath: storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | |||
ModelPath: storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | |||
BenchmarkPath: storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), | |||
Snn4ImageNetPath: storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | |||
BrainScorePath: storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), | |||
JobType: jobType, | |||
Description: getDescription(option), | |||
BranchName: option.BranchName, | |||
BootFile: option.File, | |||
Params: "{\"parameter\":[]}", | |||
CommitID: commitID, | |||
BenchmarkTypeID: 0, | |||
BenchmarkChildTypeID: 0, | |||
ResultPath: storage.GetMinioPath(jobName, cloudbrain.ResultPath+"/"), | |||
Spec: spec, | |||
} | |||
jobId, err := cloudbrain.GenerateTask(req) | |||
if err != nil { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(err.Error())) | |||
return | |||
} | |||
ctx.JSON(http.StatusOK, models.BaseMessageApi{ | |||
Code: 0, | |||
Message: jobId, | |||
}) | |||
} | |||
func getCodePath(jobName string) string { | |||
return setting.JobPath + jobName + cloudbrain.CodeMountPath | |||
} | |||
func getDescription(option api.CreateFileNotebookJobOption) string { | |||
return option.OwnerName + "/" + option.ProjectName + "/" + option.File | |||
} | |||
func modelartsFileNoteBookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption, repo *models.Repository) { | |||
displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name) | |||
jobName := util.ConvertDisplayJobNameToJobName(displayJobName) | |||
lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeDebug), displayJobName)) | |||
isOk, err := lock.Lock(models.CloudbrainKeyDuration) | |||
if !isOk { | |||
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err"))) | |||
return | |||
} | |||
defer lock.UnLock() | |||
count, err := GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeDebug)) | |||
if err != nil { | |||
log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error.")) | |||
return | |||
} else { | |||
if count >= 1 { | |||
log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain.morethanonejob"))) | |||
return | |||
} | |||
} | |||
tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeDebug), displayJobName) | |||
if err == nil { | |||
if len(tasks) != 0 { | |||
log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err"))) | |||
return | |||
} | |||
} else { | |||
if !models.IsErrJobNotExist(err) { | |||
log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error.")) | |||
return | |||
} | |||
} | |||
repoPath := models.RepoPath(repo.OwnerName, repo.Name) | |||
gitRepo, err := git.OpenRepository(repoPath) | |||
if err != nil { | |||
ctx.Error(500, "RepoRef Invalid repo "+repoPath, err.Error()) | |||
return | |||
} | |||
// We opened it, we should close it | |||
defer func() { | |||
// If it's been set to nil then assume someone else has closed it. | |||
if ctx.Repo.GitRepo != nil { | |||
ctx.Repo.GitRepo.Close() | |||
} | |||
}() | |||
ctx.Repo = &context.Repository{ | |||
Repository: repo, | |||
GitRepo: gitRepo, | |||
} | |||
fileExist, err := ctx.Repo.FileExists(option.File, option.BranchName) | |||
if err != nil || !fileExist { | |||
log.Error("Get file error:", err, ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist"))) | |||
return | |||
} | |||
err = downloadCode(repo, getCodePath(jobName), option.BranchName) | |||
if err != nil { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.load_code_failed"))) | |||
return | |||
} | |||
var aiCenterCode = models.AICenterOfCloudBrainTwo | |||
if setting.ModelartsCD.Enabled { | |||
aiCenterCode = models.AICenterOfChengdu | |||
} | |||
spec, err := resource.GetAndCheckSpec(ctx.User.ID, setting.FileNoteBook.SpecIdNPU, models.FindSpecsOptions{ | |||
JobType: models.JobTypeDebug, | |||
ComputeResource: models.NPU, | |||
Cluster: models.OpenICluster, | |||
AiCenterCode: aiCenterCode}) | |||
if err != nil || spec == nil { | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.wrong_specification"))) | |||
return | |||
} | |||
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) { | |||
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance"))) | |||
return | |||
} | |||
var jobId string | |||
if setting.ModelartsCD.Enabled { | |||
jobId, err = modelarts_cd.GenerateNotebook(ctx, displayJobName, jobName, "", getDescription(option), setting.FileNoteBook.ImageIdNPU, spec, option.File) | |||
} else { | |||
jobId, err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, "", getDescription(option), setting.FileNoteBook.ImageIdNPU, spec, option.File) | |||
} | |||
if err != nil { | |||
log.Error("GenerateNotebook2 failed, %v", err, ctx.Data["MsgID"]) | |||
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(err.Error())) | |||
return | |||
} | |||
ctx.JSON(http.StatusOK, models.BaseMessageApi{ | |||
Code: 0, | |||
Message: jobId, | |||
}) | |||
} | |||
func uploadCodeFile(repo *models.Repository, codePath string, branchName string, filePath string, jobName string) string { | |||
err := downloadCode(repo, codePath, branchName) | |||
if err != nil { | |||
return "cloudbrain.load_code_failed" | |||
} | |||
err = uploadOneFileToMinio(codePath, filePath, jobName, cloudbrain.CodeMountPath+"/") | |||
if err != nil { | |||
return "cloudbrain.load_code_failed" | |||
} | |||
go os.RemoveAll(codePath) | |||
return "" | |||
} |
@@ -810,6 +810,18 @@ func uploadCodeToMinio(codePath, jobName, parentDir string) error { | |||
return nil | |||
} | |||
func uploadOneFileToMinio(codePath, filePath, jobName, parentDir string) error { | |||
destObject := setting.CBCodePathPrefix + jobName + parentDir + path.Base(filePath) | |||
sourceFile := codePath + filePath | |||
err := storage.Attachments.UploadObject(destObject, sourceFile) | |||
if err != nil { | |||
log.Error("UploadObject(%s) failed: %s", filePath, err.Error()) | |||
return err | |||
} | |||
return nil | |||
} | |||
func readDir(dirname string) ([]os.FileInfo, error) { | |||
f, err := os.Open(dirname) | |||
if err != nil { | |||
@@ -1,27 +1,31 @@ | |||
package cloudbrain | |||
import ( | |||
"regexp" | |||
"strconv" | |||
"strings" | |||
"time" | |||
"code.gitea.io/gitea/modules/context" | |||
"code.gitea.io/gitea/modules/setting" | |||
"strings" | |||
) | |||
func GetAiCenterShow(aiCenter string,ctx *context.Context) string{ | |||
func GetAiCenterShow(aiCenter string, ctx *context.Context) string { | |||
aiCenterInfo := strings.Split(aiCenter, "+") | |||
if len(aiCenterInfo) == 2{ | |||
if setting.C2NetMapInfo!=nil { | |||
if info,ok:=setting.C2NetMapInfo[aiCenterInfo[0]];ok { | |||
if len(aiCenterInfo) == 2 { | |||
if setting.C2NetMapInfo != nil { | |||
if info, ok := setting.C2NetMapInfo[aiCenterInfo[0]]; ok { | |||
if ctx.Language() == "zh-CN" { | |||
return info.Content | |||
} else { | |||
return info.ContentEN | |||
} | |||
}else{ | |||
} else { | |||
return aiCenterInfo[1] | |||
} | |||
}else{ | |||
} else { | |||
return aiCenterInfo[1] | |||
} | |||
@@ -29,5 +33,26 @@ func GetAiCenterShow(aiCenter string,ctx *context.Context) string{ | |||
return "" | |||
} | |||
func GetDisplayJobName(username string) string { | |||
t := time.Now() | |||
return jobNamePrefixValid(cutString(username, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
} | |||
func cutString(str string, lens int) string { | |||
if len(str) < lens { | |||
return str | |||
} | |||
return str[:lens] | |||
} | |||
func jobNamePrefixValid(s string) string { | |||
lowStr := strings.ToLower(s) | |||
re := regexp.MustCompile(`[^a-z0-9_\\-]+`) | |||
removeSpecial := re.ReplaceAllString(lowStr, "") | |||
re = regexp.MustCompile(`^[_\\-]+`) | |||
return re.ReplaceAllString(removeSpecial, "") | |||
} |