diff --git a/models/cloudbrain_static.go b/models/cloudbrain_static.go
index cb99f9ff5..a7678b267 100644
--- a/models/cloudbrain_static.go
+++ b/models/cloudbrain_static.go
@@ -1,7 +1,6 @@
package models
import (
- "fmt"
"strconv"
"time"
@@ -313,10 +312,6 @@ func InsertCloudbrainDurationStatistic(cloudbrainDurationStatistic *CloudbrainDu
return xStatistic.Insert(cloudbrainDurationStatistic)
}
-func GetDurationStatisticByDate(date string, hour int, aiCenterCode string, accCardType string) (*CloudbrainDurationStatistic, error) {
- cb := &CloudbrainDurationStatistic{DayTime: date, HourTime: hour, AiCenterCode: aiCenterCode, AccCardType: accCardType}
- return getDurationStatistic(cb)
-}
func getDurationStatistic(cb *CloudbrainDurationStatistic) (*CloudbrainDurationStatistic, error) {
has, err := x.Get(cb)
if err != nil {
@@ -327,26 +322,6 @@ func getDurationStatistic(cb *CloudbrainDurationStatistic) (*CloudbrainDurationS
return cb, nil
}
-func DeleteCloudbrainDurationStatisticHour(date string, hour int, aiCenterCode string, accCardType string) error {
- sess := xStatistic.NewSession()
- defer sess.Close()
- if err := sess.Begin(); err != nil {
- return fmt.Errorf("Begin: %v", err)
- }
-
- if _, err := sess.Where("day_time = ? AND hour_time = ? AND ai_center_code = ? AND acc_card_type = ?", date, hour, aiCenterCode, accCardType).Delete(&CloudbrainDurationStatistic{}); err != nil {
- return fmt.Errorf("Delete: %v", err)
- }
-
- if err := sess.Commit(); err != nil {
- sess.Close()
- return fmt.Errorf("Commit: %v", err)
- }
-
- sess.Close()
- return nil
-}
-
func GetCanUseCardInfo() ([]*ResourceQueue, error) {
sess := x.NewSession()
defer sess.Close()
@@ -402,11 +377,11 @@ func GetDurationRecordUpdateTime() ([]*CloudbrainDurationStatistic, error) {
return CloudbrainDurationStatistics, nil
}
-func DeleteCloudbrainDurationStatistic() error {
+func DeleteCloudbrainDurationStatistic(beginTime timeutil.TimeStamp, endTime timeutil.TimeStamp) error {
sess := xStatistic.NewSession()
defer sess.Close()
- if _, err := sess.Exec("TRUNCATE TABLE cloudbrain_duration_statistic"); err != nil {
- log.Info("TRUNCATE cloudbrain_duration_statistic error.")
+ if _, err := sess.Exec("DELETE FROM cloudbrain_duration_statistic WHERE cloudbrain_duration_statistic.date_time BETWEEN ? AND ?", beginTime, endTime); err != nil {
+ log.Info("DELETE cloudbrain_duration_statistic data error.")
return err
}
return nil
diff --git a/models/repo.go b/models/repo.go
index f0760108b..832e3fc37 100755
--- a/models/repo.go
+++ b/models/repo.go
@@ -1279,7 +1279,7 @@ func CreateRepository(ctx DBContext, doer, u *User, repo *Repository, opts ...Cr
}
if setting.Service.AutoWatchNewRepos {
- if err = watchRepo(ctx.e, doer.ID, repo.ID, true); err != nil {
+ if err = watchRepo(ctx.e, doer.ID, repo.ID, true, ReceiveAllNotification); err != nil {
return fmt.Errorf("watchRepo: %v", err)
}
}
diff --git a/models/repo_watch.go b/models/repo_watch.go
index 573a2d78a..7c43ee352 100644
--- a/models/repo_watch.go
+++ b/models/repo_watch.go
@@ -24,6 +24,14 @@ const (
RepoWatchModeAuto // 3
)
+// NotifyType specifies what kind of watch the user has on a repository
+type NotifyType int8
+
+const (
+ RejectAllNotification NotifyType = 0
+ ReceiveAllNotification NotifyType = 9
+)
+
var ActionChan = make(chan *Action, 200)
var ActionChan4Task = make(chan Action, 200)
@@ -34,6 +42,7 @@ type Watch struct {
RepoID int64 `xorm:"UNIQUE(watch)"`
Mode RepoWatchMode `xorm:"SMALLINT NOT NULL DEFAULT 1"`
CreatedUnix int64 `xorm:"created"`
+ NotifyType NotifyType `xorm:"SMALLINT NOT NULL DEFAULT 0"`
}
// getWatch gets what kind of subscription a user has on a given repository; returns dummy record if none found
@@ -60,8 +69,20 @@ func IsWatching(userID, repoID int64) bool {
return err == nil && isWatchMode(watch.Mode)
}
+// GetWatchNotifyType
+func GetWatchNotifyType(userID, repoID int64) NotifyType {
+ watch, err := getWatch(x, userID, repoID)
+ if err != nil {
+ return RejectAllNotification
+ }
+ return watch.NotifyType
+}
+
func watchRepoMode(e Engine, watch Watch, mode RepoWatchMode) (err error) {
if watch.Mode == mode {
+ if _, err := e.ID(watch.ID).Cols("notify_type").Update(watch); err != nil {
+ return err
+ }
return nil
}
if mode == RepoWatchModeAuto && (watch.Mode == RepoWatchModeDont || isWatchMode(watch.Mode)) {
@@ -109,7 +130,7 @@ func WatchRepoMode(userID, repoID int64, mode RepoWatchMode) (err error) {
return watchRepoMode(x, watch, mode)
}
-func watchRepo(e Engine, userID, repoID int64, doWatch bool) (err error) {
+func watchRepo(e Engine, userID, repoID int64, doWatch bool, notifyTypes ...NotifyType) (err error) {
var watch Watch
if watch, err = getWatch(e, userID, repoID); err != nil {
return err
@@ -119,14 +140,19 @@ func watchRepo(e Engine, userID, repoID int64, doWatch bool) (err error) {
} else if !doWatch {
err = watchRepoMode(e, watch, RepoWatchModeNone)
} else {
+ notifyType := RejectAllNotification
+ if len(notifyTypes) > 0 {
+ notifyType = notifyTypes[0]
+ }
+ watch.NotifyType = notifyType
err = watchRepoMode(e, watch, RepoWatchModeNormal)
}
return err
}
// WatchRepo watch or unwatch repository.
-func WatchRepo(userID, repoID int64, watch bool) (err error) {
- return watchRepo(x, userID, repoID, watch)
+func WatchRepo(userID, repoID int64, watch bool, notifyType ...NotifyType) (err error) {
+ return watchRepo(x, userID, repoID, watch, notifyType...)
}
func getWatchers(e Engine, repoID int64) ([]*Watch, error) {
@@ -156,6 +182,7 @@ func getRepoWatchersIDs(e Engine, repoID int64) ([]int64, error) {
return ids, e.Table("watch").
Where("watch.repo_id=?", repoID).
And("watch.mode<>?", RepoWatchModeDont).
+ And("watch.notify_type > ?", RejectAllNotification).
Select("user_id").
Find(&ids)
}
diff --git a/models/resource_specification.go b/models/resource_specification.go
index 7a11edd05..2f815818b 100644
--- a/models/resource_specification.go
+++ b/models/resource_specification.go
@@ -298,6 +298,15 @@ func ResourceSpecOffShelf(id int64) (int64, error) {
return n, err
}
+func GetResourceSpecificationByIds(ids []int64) ([]*Specification, error) {
+ r := make([]*Specification, 0)
+ err := x.In("resource_specification.id", ids).
+ Join("INNER", "resource_queue", "resource_queue.id = resource_specification.queue_id").
+ Find(&r)
+ return r, err
+
+}
+
func GetResourceSpecification(r *ResourceSpecification) (*ResourceSpecification, error) {
has, err := x.Get(r)
if err != nil {
diff --git a/models/user.go b/models/user.go
index b21858e37..c421455bc 100755
--- a/models/user.go
+++ b/models/user.go
@@ -346,7 +346,7 @@ func (u *User) DashboardLink() string {
if u.IsOrganization() {
return setting.AppSubURL + "/org/" + u.Name + "/dashboard/"
}
- return setting.AppSubURL + "/"
+ return setting.AppSubURL + "/dashboard"
}
// HomeLink returns the user or organization home page link.
diff --git a/models/user_mail.go b/models/user_mail.go
index 8bf74b81b..8388da068 100755
--- a/models/user_mail.go
+++ b/models/user_mail.go
@@ -216,6 +216,27 @@ func (email *EmailAddress) updateActivation(e Engine, activate bool) error {
return updateUserCols(e, user, "rands")
}
+// UpdateEmailAddress update an email address of given user.
+func (email *EmailAddress) UpdateEmailAddress(newEmailAddress string) error {
+ return email.updateEmailAddress(x, newEmailAddress)
+}
+func (email *EmailAddress) updateEmailAddress(e Engine, newEmailAddress string) error {
+ user, err := getUserByID(e, email.UID)
+ if err != nil {
+ return err
+ }
+ if user.Rands, err = GetUserSalt(); err != nil {
+ return err
+ }
+ user.Email = newEmailAddress
+ user.AvatarEmail = newEmailAddress
+ email.Email = newEmailAddress
+ if _, err := e.ID(email.ID).Cols("email").Update(email); err != nil {
+ return err
+ }
+ return updateUserCols(e, user, "email", "avatar_email")
+}
+
// DeleteEmailAddress deletes an email address of given user.
func DeleteEmailAddress(email *EmailAddress) (err error) {
var deleted int64
diff --git a/modules/auth/user_form.go b/modules/auth/user_form.go
index ad78607ab..521585264 100755
--- a/modules/auth/user_form.go
+++ b/modules/auth/user_form.go
@@ -88,6 +88,10 @@ type RegisterForm struct {
Agree bool
}
+type UpdateEmailForm struct {
+ NewEmail string `binding:"Required;MaxSize(254)"`
+}
+
// Validate valideates the fields
func (f *RegisterForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
diff --git a/modules/cloudbrain/cloudbrain.go b/modules/cloudbrain/cloudbrain.go
index 8d4e57670..f8a6525d2 100755
--- a/modules/cloudbrain/cloudbrain.go
+++ b/modules/cloudbrain/cloudbrain.go
@@ -145,7 +145,7 @@ func isAdminOrImageCreater(ctx *context.Context, image *models.Image, err error)
func AdminOrOwnerOrJobCreaterRight(ctx *context.Context) {
var id = ctx.Params(":id")
- job, err := models.GetCloudbrainByID(id)
+ job, err := GetCloudBrainByIdOrJobId(id)
if err != nil {
log.Error("GetCloudbrainByID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -161,7 +161,7 @@ func AdminOrOwnerOrJobCreaterRight(ctx *context.Context) {
func AdminOrJobCreaterRight(ctx *context.Context) {
var id = ctx.Params(":id")
- job, err := models.GetCloudbrainByID(id)
+ job, err := GetCloudBrainByIdOrJobId(id)
if err != nil {
log.Error("GetCloudbrainByID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -177,7 +177,7 @@ func AdminOrJobCreaterRight(ctx *context.Context) {
func AdminOrOwnerOrJobCreaterRightForTrain(ctx *context.Context) {
var jobID = ctx.Params(":jobid")
- job, err := models.GetCloudbrainByJobID(jobID)
+ job, err := GetCloudBrainByIdOrJobId(jobID)
if err != nil {
log.Error("GetCloudbrainByJobID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -193,7 +193,7 @@ func AdminOrOwnerOrJobCreaterRightForTrain(ctx *context.Context) {
func AdminOrJobCreaterRightForTrain(ctx *context.Context) {
var jobID = ctx.Params(":jobid")
- job, err := models.GetCloudbrainByJobID(jobID)
+ job, err := GetCloudBrainByIdOrJobId(jobID)
if err != nil {
log.Error("GetCloudbrainByJobID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
@@ -652,3 +652,16 @@ func IsElementExist(s []string, str string) bool {
}
return false
}
+
+func GetCloudBrainByIdOrJobId(id string) (*models.Cloudbrain,error) {
+ _, err := strconv.ParseInt(id, 10, 64)
+ var job *models.Cloudbrain
+ if err != nil {
+
+ job, err = models.GetCloudbrainByJobID(id)
+ } else {
+ job, err = models.GetCloudbrainByID(id)
+
+ }
+ return job,err
+}
diff --git a/modules/context/repo.go b/modules/context/repo.go
index 7c425c8c0..3bdc34f0d 100755
--- a/modules/context/repo.go
+++ b/modules/context/repo.go
@@ -474,6 +474,7 @@ func RepoAssignment() macaron.Handler {
if ctx.IsSigned {
ctx.Data["IsWatchingRepo"] = models.IsWatching(ctx.User.ID, repo.ID)
+ ctx.Data["WatchNotifyType"] = models.GetWatchNotifyType(ctx.User.ID, repo.ID)
ctx.Data["IsStaringRepo"] = models.IsStaring(ctx.User.ID, repo.ID)
ctx.Data["IsStaringDataset"] = models.IsDatasetStaringByRepoId(ctx.User.ID, repo.ID)
diff --git a/modules/modelarts/modelarts.go b/modules/modelarts/modelarts.go
index dd502dfd0..b59be307b 100755
--- a/modules/modelarts/modelarts.go
+++ b/modules/modelarts/modelarts.go
@@ -1,13 +1,18 @@
package modelarts
import (
+ "encoding/base64"
"encoding/json"
"errors"
"fmt"
+ "io/ioutil"
+ "net/http"
"path"
"strconv"
"strings"
+ "code.gitea.io/gitea/modules/cloudbrain"
+
"code.gitea.io/gitea/modules/modelarts_cd"
"code.gitea.io/gitea/models"
@@ -23,7 +28,7 @@ const (
//notebook
storageTypeOBS = "obs"
autoStopDuration = 4 * 60 * 60
- autoStopDurationMs = 4 * 60 * 60 * 1000
+ AutoStopDurationMs = 4 * 60 * 60 * 1000
MORDELART_USER_IMAGE_ENGINE_ID = -1
DataSetMountPath = "/home/ma-user/work"
NotebookEnv = "Python3"
@@ -276,7 +281,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,autoStopDurationInMs int64) (string, error) {
if poolInfos == nil {
json.Unmarshal([]byte(setting.PoolInfos), &poolInfos)
}
@@ -284,14 +289,14 @@ 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{
JobName: jobName,
Description: description,
Flavor: spec.SourceSpecId,
- Duration: autoStopDurationMs,
+ Duration: autoStopDurationInMs,
ImageID: imageId,
PoolID: poolInfos.PoolInfo[0].PoolId,
Feature: models.NotebookFeature,
@@ -316,10 +321,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 +339,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 +348,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 +913,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 +928,81 @@ func HandleNotebookInfo(task *models.Cloudbrain) error {
return nil
}
+func uploadNoteBookFile(task *models.Cloudbrain, result *models.GetNotebook2Result) {
+ jupyterUrl := result.Url + "?token=" + result.Token
+
+ cookies, xsrf := getCookiesAndCsrf(jupyterUrl)
+ if xsrf == "" {
+ log.Error("browser jupyterUrl failed:%v", task.DisplayJobName)
+ } else {
+
+ codePath := setting.JobPath + task.JobName + cloudbrain.CodeMountPath
+ 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)
+ client := getRestyClient()
+ uploadUrl := getJupyterBaseUrl(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)
+ }
+
+ }
+
+}
+
+func getJupyterBaseUrl(url string) string {
+ jupyterUrlLength := len(url)
+ baseUrl := url[0 : jupyterUrlLength-len(path.Base(url))]
+ return baseUrl
+}
+
+func getCookiesAndCsrf(jupyterUrl string) ([]*http.Cookie, string) {
+ log.Info("jupyter url:"+jupyterUrl)
+ var cookies []*http.Cookie
+ const retryTimes = 10
+ for i := 0; i < retryTimes; i++ {
+ res, err := http.Get(jupyterUrl)
+ if err != nil {
+ log.Error("browser jupyterUrl failed.",err)
+ if i==retryTimes-1{
+ return cookies, ""
+ }
+
+ } else {
+ cookies = res.Cookies()
+ xsrf := ""
+ for _, cookie := range cookies {
+ if cookie.Name == "_xsrf" {
+ xsrf = cookie.Value
+ break
+ }
+
+ }
+ if xsrf != "" {
+ return cookies, xsrf
+ }
+
+ }
+ }
+ return cookies, ""
+
+}
+
func SyncTempStatusJob() {
jobs, err := models.GetCloudBrainTempJobs()
if err != nil {
diff --git a/modules/modelarts/resty.go b/modules/modelarts/resty.go
index c38300606..3ccba9011 100755
--- a/modules/modelarts/resty.go
+++ b/modules/modelarts/resty.go
@@ -280,7 +280,7 @@ sendjob:
SetHeader("Content-Type", "application/json").
SetAuthToken(TOKEN).
SetResult(&result).
- Post(HOST + "/v1/" + setting.ProjectID + urlNotebook2 + "/" + jobID + "/" + param.Action + "?duration=" + strconv.Itoa(autoStopDurationMs))
+ Post(HOST + "/v1/" + setting.ProjectID + urlNotebook2 + "/" + jobID + "/" + param.Action + "?duration=" + strconv.Itoa(AutoStopDurationMs))
if err != nil {
return &result, fmt.Errorf("resty ManageNotebook2: %v", err)
diff --git a/modules/modelarts_cd/modelarts.go b/modules/modelarts_cd/modelarts.go
index 330b048ca..93032fa89 100755
--- a/modules/modelarts_cd/modelarts.go
+++ b/modules/modelarts_cd/modelarts.go
@@ -88,18 +88,18 @@ 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,autoStopDurationInMs int64) (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{
JobName: jobName,
Description: description,
Flavor: spec.SourceSpecId,
- Duration: autoStopDurationMs,
+ Duration: autoStopDurationInMs,
ImageID: imageId,
Feature: models.NotebookFeature,
Volume: models.VolumeReq{
@@ -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
-}
-
-*/
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index e237d5a8a..374e6a99d 100755
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -715,6 +715,21 @@ var (
TeamName string
}{}
+ FileNoteBook = struct {
+ ProjectName string
+ ImageGPU string
+ SpecIdGPU int64
+ SpecIdCPU int64
+ ImageIdNPU string
+ SpecIdNPU int64
+ ImageIdNPUCD string
+ SpecIdNPUCD int64
+ ImageCPUDescription string
+ ImageGPUDescription string
+ ImageNPUDescription string
+ ImageNPUCDDescription string
+ }{}
+
ModelConvert = struct {
GPU_PYTORCH_IMAGE string
GpuQueue string
@@ -1580,6 +1595,20 @@ func NewContext() {
Course.OrgName = sec.Key("org_name").MustString("")
Course.TeamName = sec.Key("team_name").MustString("")
+ sec = Cfg.Section("file_notebook")
+ FileNoteBook.ProjectName = sec.Key("project_name").MustString("openi-notebook")
+ FileNoteBook.ImageIdNPU = sec.Key("imageid_npu").MustString("")
+ FileNoteBook.ImageGPU = sec.Key("image_gpu").MustString("")
+ FileNoteBook.SpecIdCPU = sec.Key("specid_cpu").MustInt64(-1)
+ FileNoteBook.SpecIdGPU = sec.Key("specid_gpu").MustInt64(-1)
+ FileNoteBook.SpecIdNPU = sec.Key("specid_npu").MustInt64(-1)
+ FileNoteBook.ImageIdNPUCD = sec.Key("imageid_npu_cd").MustString("")
+ FileNoteBook.SpecIdNPUCD = sec.Key("specid_npu_cd").MustInt64(-1)
+ FileNoteBook.ImageCPUDescription = sec.Key("image_cpu_desc").MustString("")
+ FileNoteBook.ImageGPUDescription = sec.Key("image_gpu_desc").MustString("")
+ FileNoteBook.ImageNPUDescription = sec.Key("image_npu_desc").MustString("")
+ FileNoteBook.ImageNPUCDDescription = sec.Key("image_npu_cd_desc").MustString("")
+
getGrampusConfig()
getModelartsCDConfig()
getModelConvertConfig()
diff --git a/modules/structs/cloudbrain.go b/modules/structs/cloudbrain.go
index 866c85dad..9ea5601c9 100644
--- a/modules/structs/cloudbrain.go
+++ b/modules/structs/cloudbrain.go
@@ -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"`
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index 3e424454b..c314127f1 100755
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -151,6 +151,9 @@ func NewFuncMap() []template.FuncMap {
"EscapePound": func(str string) string {
return strings.NewReplacer("%", "%25", "#", "%23", " ", "%20", "?", "%3F").Replace(str)
},
+ "IpynbBool":func(str string) bool{
+ return strings.Contains(str, ".ipynb")
+ },
"nl2br": func(text string) template.HTML {
return template.HTML(strings.Replace(template.HTMLEscapeString(text), "\n", "
", -1))
},
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index f3381d2ed..3f52cedbe 100755
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -397,9 +397,12 @@ authorize_application_created_by = This application was created by %s.
authorize_application_description = If you grant the access, it will be able to access and write to all your account information, including private repos and organisations.
authorize_title = Authorize "%s" to access your account?
authorization_failed = Authorization failed
-authorization_failed_desc = The authorization failed because we detected an invalid request. Please contact the maintainer of the app you've tried to authorize.
+authorization_failed_desc = The authorization failed because we detected an invalid request. Please contact the maintainer of the app you have tried to authorize.
disable_forgot_password_mail = Account recovery is disabled. Please contact your site administrator.
sspi_auth_failed = SSPI authentication failed
+change_email = Change email
+change_email_address = Change email address
+new_email_address = New email address
[phone]
format_err=The format of phone number is wrong.
query_err=Fail to query phone number, please try again later.
@@ -1015,6 +1018,8 @@ 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.
+failed_to_create_notebook_repo=Failed to create %s repository, please check whether you have the same name project, if yes please update or delete it first.
create_course = Publish Course
failed_to_create_course=Failed to publish course, please try again later.
default_branch = Default Branch
@@ -1049,6 +1054,10 @@ 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.
+notebook_file_no_right=You have no right to access the Notebook(.ipynb) file.
+
date=Date
repo_add=Project Increment
repo_total=Project Total
@@ -1228,7 +1237,7 @@ cloudbrain.benchmark.evaluate_test=Test Script
cloudbrain.benchmark.types={"type":[{"id":1,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=detection","first":"Target detection","second":[{"id":1,"value":"None","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"yangzhx","repo_name":"detection_benchmark_script"}]},{"id":2,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=reid","first":"Target re-identification","second":[{"id":1,"value":"Vehicle re-identification","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"},{"id":2,"value":"Image-based person re-identification","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"JiahongXu","repo_name":"benchmark_reID_script"}]},{"id":3,"rank_link":"https://git.openi.org.cn/benchmark/?username=admin&algType=tracking","first":"Multi-target tracking","second":[{"id":1,"value":"None","attachment":"84cf39c4-d8bc-41aa-aaa3-182ce289b105","owner":"lix07","repo_name":"MOT_benchmark_script"}]}]}
cloudbrain.morethanonejob=You already have a running or waiting task, create it after that task is over.
cloudbrain.morethanonejob1=You have created an equivalent task that is waiting or running, please wait for the task to finish before creating it.
-cloudbrain.morethanonejob2=You can view all your Cloud Brain tasks in Home > Cloudbrain Task .
+cloudbrain.morethanonejob2=You can view all your Cloud Brain tasks in Home > Cloudbrain Task .
modelarts.infer_job_model = Model
modelarts.infer_job_model_file = Model File
@@ -1402,6 +1411,11 @@ star = Star
fork = Fork
download_archive = Download Repository
star_fail=Failed to %s the dataset.
+watched=Watched
+notWatched=Not watched
+un_watch=Unwatch
+watch_all=Watch all
+watch_no_notify=Watch but not notify
no_desc = No Description
no_label = No labels
@@ -1443,6 +1457,7 @@ blame = Blame
normal_view = Normal View
line = line
lines = lines
+notebook_open = Open in Notebook
editor.new_file = New File
editor.upload_file = Upload File
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index f4017be27..3e26ae251 100755
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -403,6 +403,9 @@ authorization_failed=授权失败
authorization_failed_desc=授权失败,这是一个无效的请求。请联系尝试授权应用的管理员。
disable_forgot_password_mail = Account recovery is disabled. Please contact your site administrator.
sspi_auth_failed=SSPI 认证失败
+change_email=修改邮箱
+change_email_address=修改邮箱地址
+new_email_address=新邮箱地址
[phone]
format_err=手机号格式错误。
query_err=查询手机号失败,请稍后再试。
@@ -1020,6 +1023,8 @@ readme=自述
readme_helper=选择自述文件模板。
auto_init=初始化存储库 (添加. gitignore、许可证和自述文件)
create_repo=创建项目
+failed_to_create_repo=创建项目失败,请稍后再试。
+failed_to_create_notebook_repo=创建项目%s失败,请检查您是否有同名的项目,如果有请先手工修改或删除后重试。
create_course=发布课程
failed_to_create_course=发布课程失败,请稍后再试。
default_branch=默认分支
@@ -1048,6 +1053,9 @@ model_experience = 模型体验
model_noright=您没有操作权限。
model_rename=模型名称重复,请修改模型名称
+notebook_file_not_exist=Notebook文件不存在。
+notebook_select_wrong=请先选择Notebook(.ipynb)文件。
+notebook_file_no_right=您没有这个Notebook文件的读权限。
date=日期
repo_add=新增项目
@@ -1418,6 +1426,11 @@ star=点赞
fork=派生
download_archive=下载此项目
star_fail=%s失败。
+watched=已关注
+notWatched=未关注
+un_watch=不关注
+watch_all=关注所有动态
+watch_no_notify=关注但不提醒动态
no_desc=暂无描述
@@ -1461,6 +1474,8 @@ normal_view=普通视图
line=行
lines=行
+notebook_open = 在Notebook中打开
+
editor.new_file=新建文件
editor.upload_file=上传文件
editor.edit_file=编辑文件
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 2afbb9b7d..14badfdb4 100755
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -737,6 +737,12 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/my_favorite", repo.MyFavoriteDatasetMultiple)
}, reqToken(), repoAssignment())
+ m.Group("/file_notebook", func() {
+ m.Get("", reqToken(), repo.GetFileNoteBookInfo)
+ m.Post("/create", reqToken(), reqWeChat(), bind(api.CreateFileNotebookJobOption{}), repo.CreateFileNoteBook)
+
+ })
+
m.Group("/repos", func() {
m.Get("/search", repo.Search)
diff --git a/routers/api/v1/repo/cloudbrain.go b/routers/api/v1/repo/cloudbrain.go
index f2a784f16..f1b2751f8 100755
--- a/routers/api/v1/repo/cloudbrain.go
+++ b/routers/api/v1/repo/cloudbrain.go
@@ -79,6 +79,75 @@ 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 GetFileNoteBookInfo(ctx *context.APIContext) {
+ //image description spec description waiting count
+
+ specs, err := models.GetResourceSpecificationByIds([]int64{setting.FileNoteBook.SpecIdCPU, setting.FileNoteBook.SpecIdGPU, setting.FileNoteBook.SpecIdNPU, setting.FileNoteBook.SpecIdNPUCD})
+ if err != nil {
+ log.Error("Fail to query specifications", err)
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_query_fail")))
+ return
+ }
+
+ var specCPU, specGpu, specNPU, specNPUCD *api.SpecificationShow
+ var specGpuQueueCode string
+ for _, spec := range specs {
+ if spec.ID == setting.FileNoteBook.SpecIdCPU {
+ specCPU = convert.ToSpecification(spec)
+ } else if spec.ID == setting.FileNoteBook.SpecIdGPU {
+ specGpu = convert.ToSpecification(spec)
+ specGpuQueueCode = spec.QueueCode
+ } else if spec.ID == setting.FileNoteBook.SpecIdNPU {
+ specNPU = convert.ToSpecification(spec)
+ } else if spec.ID == setting.FileNoteBook.SpecIdNPUCD {
+ specNPUCD = convert.ToSpecification(spec)
+ }
+ }
+
+ waitCountNpu := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")
+
+ queuesMap, err := cloudbrain.GetQueuesDetail()
+ if err != nil {
+ log.Error("Fail to query gpu queues waiting count", err)
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_query_fail")))
+ return
+ }
+ waitCountGPU := (*queuesMap)[specGpuQueueCode]
+ if !setting.ModelartsCD.Enabled{
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "code": 0,
+ "projectName":setting.FileNoteBook.ProjectName,
+ "specCpu": specCPU,
+ "specGpu": specGpu,
+ "specNpu": specNPU,
+ "waitCountGpu": waitCountGPU,
+ "waitCountNpu": waitCountNpu,
+ "imageCpuDescription": setting.FileNoteBook.ImageCPUDescription,
+ "imageGpuDescription": setting.FileNoteBook.ImageGPUDescription,
+ "imageNpuDescription": setting.FileNoteBook.ImageNPUDescription,
+
+ })
+ } else{
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "code": 0,
+ "projectName":setting.FileNoteBook.ProjectName,
+ "specCpu": specCPU,
+ "specGpu": specGpu,
+ "specNpu": specNPUCD,
+ "waitCountGpu": waitCountGPU,
+ "waitCountNpu": waitCountNpu,
+ "imageCpuDescription": setting.FileNoteBook.ImageCPUDescription,
+ "imageGpuDescription": setting.FileNoteBook.ImageGPUDescription,
+ "imageNpuDescription": setting.FileNoteBook.ImageNPUCDDescription,
+ })
+
+ }
+
+}
func CreateCloudBrain(ctx *context.APIContext, option api.CreateTrainJobOption) {
if option.Type == cloudbrainTask.TaskTypeCloudbrainOne {
@@ -141,10 +210,11 @@ func GetCloudbrainTask(ctx *context.APIContext) {
)
ID := ctx.Params(":id")
- job, err := models.GetCloudbrainByID(ID)
+
+ job,err := cloudbrain.GetCloudBrainByIdOrJobId(ID)
+
if err != nil {
ctx.NotFound(err)
- log.Error("GetCloudbrainByID failed:", err)
return
}
if job.JobType == string(models.JobTypeModelSafety) {
diff --git a/routers/api/v1/repo/cloudbrain_dashboard.go b/routers/api/v1/repo/cloudbrain_dashboard.go
index 446522fc2..09e65b007 100755
--- a/routers/api/v1/repo/cloudbrain_dashboard.go
+++ b/routers/api/v1/repo/cloudbrain_dashboard.go
@@ -123,8 +123,9 @@ func GetOverviewDuration(ctx *context.Context) {
recordBeginTime := recordCloudbrain[0].Cloudbrain.CreatedUnix
now := time.Now()
endTime := now
- // worker_server_num := 1
- // cardNum := 1
+ var workServerNumber int64
+ var cardNum int64
+
durationAllSum := int64(0)
cardDuSum := int64(0)
@@ -138,52 +139,60 @@ func GetOverviewDuration(ctx *context.Context) {
c2NetDuration := int64(0)
cDCenterDuration := int64(0)
- cloudbrains, _, err := models.CloudbrainAllStatic(&models.CloudbrainsOptions{
- Type: models.TypeCloudBrainAll,
- BeginTimeUnix: int64(recordBeginTime),
- EndTimeUnix: endTime.Unix(),
- })
- if err != nil {
- ctx.ServerError("Get cloudbrains failed:", err)
- return
- }
- models.LoadSpecs4CloudbrainInfo(cloudbrains)
-
- for _, cloudbrain := range cloudbrains {
- cloudbrain = cloudbrainService.UpdateCloudbrainAiCenter(cloudbrain)
- CardDurationString := repo.GetCloudbrainCardDuration(cloudbrain.Cloudbrain)
- CardDuration := models.ConvertStrToDuration(CardDurationString)
- // if cloudbrain.Cloudbrain.WorkServerNumber >= 1 {
- // worker_server_num = cloudbrain.Cloudbrain.WorkServerNumber
- // } else {
- // worker_server_num = 1
- // }
- // if cloudbrain.Cloudbrain.Spec == nil {
- // cardNum = 1
- // } else {
- // cardNum = cloudbrain.Cloudbrain.Spec.AccCardsNum
- // }
- // duration := cloudbrain.Duration
- // duration := cloudbrain.Duration
- duration := models.ConvertStrToDuration(cloudbrain.TrainJobDuration)
- // CardDuration := cloudbrain.Duration * int64(worker_server_num) * int64(cardNum)
-
- if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainOne {
- cloudBrainOneDuration += duration
- cloudBrainOneCardDuSum += CardDuration
- } else if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainTwo {
- cloudBrainTwoDuration += duration
- cloudBrainTwoCardDuSum += CardDuration
- } else if cloudbrain.Cloudbrain.Type == models.TypeC2Net {
- c2NetDuration += duration
- c2NetCardDuSum += CardDuration
- } else if cloudbrain.Cloudbrain.Type == models.TypeCDCenter {
- cDCenterDuration += duration
- cDNetCardDuSum += CardDuration
+ page := 1
+ pagesize := 10000
+ count := pagesize
+ // Each time a maximum of 10000 pieces of data are detected to the memory, batch processing
+ for count == pagesize && count != 0 {
+ cloudbrains, _, err := models.CloudbrainAllStatic(&models.CloudbrainsOptions{
+ ListOptions: models.ListOptions{
+ Page: page,
+ PageSize: pagesize,
+ },
+ Type: models.TypeCloudBrainAll,
+ BeginTimeUnix: int64(recordBeginTime),
+ EndTimeUnix: endTime.Unix(),
+ })
+ if err != nil {
+ ctx.ServerError("Get cloudbrains failed:", err)
+ return
}
+ models.LoadSpecs4CloudbrainInfo(cloudbrains)
+
+ for _, cloudbrain := range cloudbrains {
+ cloudbrain = cloudbrainService.UpdateCloudbrainAiCenter(cloudbrain)
+ if cloudbrain.Cloudbrain.Spec != nil {
+ cardNum = int64(cloudbrain.Cloudbrain.Spec.AccCardsNum)
+ } else {
+ cardNum = 1
+ }
+ if cloudbrain.Cloudbrain.WorkServerNumber >= 1 {
+ workServerNumber = int64(cloudbrain.Cloudbrain.WorkServerNumber)
+ } else {
+ workServerNumber = 1
+ }
+ duration := models.ConvertStrToDuration(cloudbrain.TrainJobDuration)
+ CardDuration := workServerNumber * int64(cardNum) * duration
+
+ if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainOne {
+ cloudBrainOneDuration += duration
+ cloudBrainOneCardDuSum += CardDuration
+ } else if cloudbrain.Cloudbrain.Type == models.TypeCloudBrainTwo {
+ cloudBrainTwoDuration += duration
+ cloudBrainTwoCardDuSum += CardDuration
+ } else if cloudbrain.Cloudbrain.Type == models.TypeC2Net {
+ c2NetDuration += duration
+ c2NetCardDuSum += CardDuration
+ } else if cloudbrain.Cloudbrain.Type == models.TypeCDCenter {
+ cDCenterDuration += duration
+ cDNetCardDuSum += CardDuration
+ }
- durationAllSum += duration
- cardDuSum += CardDuration
+ durationAllSum += duration
+ cardDuSum += CardDuration
+ }
+ count = len(cloudbrains)
+ page += 1
}
ctx.JSON(http.StatusOK, map[string]interface{}{
"cloudBrainOneCardDuSum": cloudBrainOneCardDuSum,
diff --git a/routers/api/v1/repo/modelarts.go b/routers/api/v1/repo/modelarts.go
index e0db9eda3..127ddd835 100755
--- a/routers/api/v1/repo/modelarts.go
+++ b/routers/api/v1/repo/modelarts.go
@@ -6,6 +6,7 @@
package repo
import (
+ "code.gitea.io/gitea/modules/cloudbrain"
"encoding/json"
"net/http"
"path"
@@ -37,11 +38,14 @@ func GetModelArtsNotebook2(ctx *context.APIContext) {
)
ID := ctx.Params(":id")
- job, err := models.GetCloudbrainByID(ID)
+
+ job,err := cloudbrain.GetCloudBrainByIdOrJobId(ID)
+
if err != nil {
ctx.NotFound(err)
return
}
+
err = modelarts.HandleNotebookInfo(job)
if err != nil {
ctx.NotFound(err)
diff --git a/routers/repo/aisafety.go b/routers/repo/aisafety.go
index b638a486b..6176fcda5 100644
--- a/routers/repo/aisafety.go
+++ b/routers/repo/aisafety.go
@@ -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
diff --git a/routers/repo/cloudbrain.go b/routers/repo/cloudbrain.go
index 7d96d1b58..d3d76f440 100755
--- a/routers/repo/cloudbrain.go
+++ b/routers/repo/cloudbrain.go
@@ -15,6 +15,8 @@ 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"
@@ -92,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()
@@ -696,7 +679,7 @@ func CloudBrainRestart(ctx *context.Context) {
} else {
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
- resultCode = "-1"
+ resultCode = "2"
errorMsg = ctx.Tr("repo.cloudbrain.morethanonejob")
break
}
@@ -759,43 +742,13 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
return
}
if task.Status == string(models.JobWaiting) || task.Status == string(models.JobRunning) {
- result, err := cloudbrain.GetJob(task.JobID)
+ task, err = cloudbrainTask.SyncCloudBrainOneStatus(task)
if err != nil {
log.Info("error:" + err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
return
}
- if result != nil {
- jobRes, _ := models.ConvertToJobResultPayload(result.Payload)
- taskRoles := jobRes.TaskRoles
- taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
- ctx.Data["taskRes"] = taskRes
- ctx.Data["ExitDiagnostics"] = taskRes.TaskStatuses[0].ExitDiagnostics
- oldStatus := task.Status
- task.Status = taskRes.TaskStatuses[0].State
- task.ContainerIp = ""
- task.ContainerID = taskRes.TaskStatuses[0].ContainerID
- models.ParseAndSetDurationFromCloudBrainOne(jobRes, task)
-
- if task.DeletedAt.IsZero() { //normal record
- if oldStatus != task.Status {
- notification.NotifyChangeCloudbrainStatus(task, oldStatus)
- }
- err = models.UpdateJob(task)
- if err != nil {
- ctx.Data["error"] = err.Error()
- return
- }
- } else { //deleted record
-
- }
-
- ctx.Data["result"] = jobRes
- } else {
- log.Info("error:" + err.Error())
- return
- }
}
user, err := models.GetUserByID(task.UserID)
@@ -889,7 +842,13 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo
func CloudBrainDebug(ctx *context.Context) {
task := ctx.Cloudbrain
debugUrl := setting.DebugServerHost + "jpylab_" + task.JobID + "_" + task.SubTaskName
- ctx.Redirect(debugUrl)
+ if task.BootFile!=""{
+ ctx.Redirect(getFileUrl(debugUrl,task.BootFile))
+
+ }else{
+ ctx.Redirect(debugUrl)
+ }
+
}
func prepareSpec4Show(ctx *context.Context, task *models.Cloudbrain) {
diff --git a/routers/repo/cloudbrain_statistic.go b/routers/repo/cloudbrain_statistic.go
index ceca2845b..2ec12cd41 100644
--- a/routers/repo/cloudbrain_statistic.go
+++ b/routers/repo/cloudbrain_statistic.go
@@ -8,7 +8,6 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
cloudbrainService "code.gitea.io/gitea/services/cloudbrain"
)
@@ -23,9 +22,15 @@ func CloudbrainDurationStatisticHour() {
now := time.Now()
currentTime := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location())
if err == nil && len(recordDurationUpdateTime) > 0 {
- statisticTime = time.Unix(int64(recordDurationUpdateTime[0].DateTime), 0)
+ statisticTime = time.Unix(int64(recordDurationUpdateTime[0].DateTime), 0).Add(+1 * time.Hour)
} else {
- statisticTime = currentTime.Add(-1 * time.Hour)
+ statisticTime = currentTime
+ }
+ deleteBeginTime := time.Unix(int64(recordDurationUpdateTime[0].DateTime), 0)
+
+ err = models.DeleteCloudbrainDurationStatistic(timeutil.TimeStamp(deleteBeginTime.Unix()), timeutil.TimeStamp(currentTime.Unix()))
+ if err != nil {
+ log.Error("DeleteCloudbrainDurationStatistic failed", err)
}
for statisticTime.Before(currentTime) || statisticTime.Equal(currentTime) {
@@ -35,13 +40,10 @@ func CloudbrainDurationStatisticHour() {
}
log.Info("summaryDurationStat count: %v", count)
}
-func UpdateDurationStatisticHistoryData() int64 {
+func UpdateDurationStatisticHistoryData(beginTime time.Time, endTime time.Time) int64 {
var count int64
- recordBeginTime, _ := time.ParseInLocation("2006-01-02 15:04:05", setting.Grampus.UsageRateBeginTime, time.Local)
- now := time.Now()
- currentTime := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location())
- statisticTime := recordBeginTime.Add(+1 * time.Hour)
-
+ statisticTime := beginTime
+ currentTime := endTime
for statisticTime.Before(currentTime) || statisticTime.Equal(currentTime) {
countEach := summaryDurationStat(statisticTime)
count += countEach
@@ -105,13 +107,6 @@ func summaryDurationStat(statisticTime time.Time) int64 {
for cardType, cardDuration := range CardTypes {
cloudbrainTable := cloudbrainMap[centerCode+"/"+cardType]
if cloudbrainTable != nil {
- if _, err := models.GetDurationStatisticByDate(dayTime, hourTime, centerCode, cardType); err == nil {
- if err := models.DeleteCloudbrainDurationStatisticHour(dayTime, hourTime, centerCode, cardType); err != nil {
- log.Error("DeleteCloudbrainDurationStatisticHour failed: %v", err.Error())
- return 0
- }
- }
-
if _, ok := cardsTotalDurationMap[cloudbrainTable.Cluster+"/"+centerCode+"/"+cardType]; !ok {
cardsTotalDurationMap[cloudbrainTable.Cluster+"/"+centerCode+"/"+cardType] = 0
}
@@ -137,12 +132,6 @@ func summaryDurationStat(statisticTime time.Time) int64 {
}
for key, cardsTotalDuration := range cardsTotalDurationMap {
- if _, err := models.GetDurationStatisticByDate(dayTime, hourTime, strings.Split(key, "/")[1], strings.Split(key, "/")[2]); err == nil {
- if err := models.DeleteCloudbrainDurationStatisticHour(dayTime, hourTime, strings.Split(key, "/")[1], strings.Split(key, "/")[2]); err != nil {
- log.Error("DeleteCloudbrainDurationStatisticHour failed: %v", err.Error())
- return 0
- }
- }
cloudbrainDurationStat := models.CloudbrainDurationStatistic{
DateTime: dateTime,
DayTime: dayTime,
@@ -255,8 +244,22 @@ func getcloudBrainCenterCodeAndCardTypeInfo(ciTasks []*models.CloudbrainInfo, be
}
func CloudbrainUpdateHistoryData(ctx *context.Context) {
- err := models.DeleteCloudbrainDurationStatistic()
- count := UpdateDurationStatisticHistoryData()
+ beginTimeStr := ctx.QueryTrim("beginTime")
+ endTimeStr := ctx.QueryTrim("endTime")
+ var count int64
+ var err error
+ if beginTimeStr != "" && endTimeStr != "" {
+ beginTime, _ := time.ParseInLocation("2006-01-02 15:04:05", beginTimeStr, time.Local)
+ endTime, _ := time.ParseInLocation("2006-01-02 15:04:05", endTimeStr, time.Local)
+ if time.Now().Before(endTime) {
+ endTime = time.Now()
+ }
+ beginTimeUnix := timeutil.TimeStamp(beginTime.Unix())
+ endTimeUnix := timeutil.TimeStamp(endTime.Unix())
+
+ err = models.DeleteCloudbrainDurationStatistic(beginTimeUnix, endTimeUnix)
+ count = UpdateDurationStatisticHistoryData(beginTime.Add(+1*time.Hour), endTime)
+ }
ctx.JSON(http.StatusOK, map[string]interface{}{
"message": 0,
"count": count,
diff --git a/routers/repo/grampus.go b/routers/repo/grampus.go
index de7bb454d..8f3182758 100755
--- a/routers/repo/grampus.go
+++ b/routers/repo/grampus.go
@@ -10,7 +10,6 @@ import (
"path"
"strconv"
"strings"
- "time"
"code.gitea.io/gitea/modules/urfs_client/urchin"
"code.gitea.io/gitea/routers/response"
@@ -77,8 +76,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
diff --git a/routers/repo/modelarts.go b/routers/repo/modelarts.go
index fabf7e555..b992734e4 100755
--- a/routers/repo/modelarts.go
+++ b/routers/repo/modelarts.go
@@ -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, "",modelarts.AutoStopDurationMs)
} else {
- err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, uuid, description, imageId, spec)
+ _, err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, uuid, description, imageId, spec, "",modelarts.AutoStopDurationMs)
}
if err != nil {
@@ -387,8 +388,33 @@ func NotebookDebug2(ctx *context.Context) {
ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil)
return
}
+ if task.BootFile!=""{
+ ctx.Redirect(getFileUrl(result.Url,task.BootFile) + "?token="+ result.Token)
+ }else{
+ ctx.Redirect(result.Url + "?token=" + result.Token)
+ }
+
- ctx.Redirect(result.Url + "?token=" + result.Token)
+}
+
+func getFileUrl(url string,filename string) string{
+ middle:=""
+ if url[len(url)-3:]=="lab" || url[len(url)-4:]=="lab/" {
+ if url[len(url)-1] == '/' {
+ middle="tree/"
+ } else {
+ middle= "/tree/"
+ }
+ }else{
+ if url[len(url)-1] == '/' {
+ middle = "lab/tree/"
+ } else {
+ middle= "/lab/tree/"
+ }
+ }
+
+
+ return url+middle+path.Base(filename)
}
func NotebookRestart(ctx *context.Context) {
@@ -420,7 +446,8 @@ func NotebookRestart(ctx *context.Context) {
} else {
if count >= 1 {
log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
- errorMsg = "you have already a running or waiting task, can not create more"
+ resultCode="2"
+ errorMsg = ctx.Tr("repo.cloudbrain.morethanonejob")
break
}
}
@@ -714,8 +741,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 +2377,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)
diff --git a/routers/repo/repo.go b/routers/repo/repo.go
index 2c8c2f45b..4919b2487 100644
--- a/routers/repo/repo.go
+++ b/routers/repo/repo.go
@@ -414,7 +414,9 @@ func Action(ctx *context.Context) {
var err error
switch ctx.Params(":action") {
case "watch":
- err = models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, true)
+ err = models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, true, models.ReceiveAllNotification)
+ case "watch_but_reject":
+ err = models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, true, models.RejectAllNotification)
case "unwatch":
err = models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, false)
case "star":
diff --git a/routers/routes/routes.go b/routers/routes/routes.go
index 8d5c79b9e..60f0365ea 100755
--- a/routers/routes/routes.go
+++ b/routers/routes/routes.go
@@ -519,6 +519,7 @@ func RegisterRoutes(m *macaron.Macaron) {
// r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds)
m.Any("/activate", user.Activate, reqSignIn)
m.Any("/activate_email", user.ActivateEmail)
+ m.Post("/update_email", bindIgnErr(auth.UpdateEmailForm{}), user.UpdateEmailPost)
m.Get("/avatar/:username/:size", user.Avatar)
m.Get("/email2user", user.Email2User)
m.Get("/recover_account", user.ResetPasswd)
diff --git a/routers/user/auth.go b/routers/user/auth.go
index 57ffb1710..bf858706d 100755
--- a/routers/user/auth.go
+++ b/routers/user/auth.go
@@ -1413,6 +1413,34 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo
handleSignInFull(ctx, u, false, true)
}
+//update user emailAddress
+func UpdateEmailPost(ctx *context.Context, form auth.UpdateEmailForm) {
+ newEmailAddress := ctx.Query("NewEmail")
+ if newEmailAddress == "" {
+ log.Error("please input the newEmail")
+ return
+ }
+ if used, _ := models.IsEmailUsed(newEmailAddress); used {
+ ctx.RenderWithErr(ctx.Tr("form.email_been_used"), TplActivate, &form)
+ return
+ }
+ user := ctx.User
+ email, err := models.GetEmailAddressByIDAndEmail(user.ID, user.Email)
+ if err != nil {
+ ctx.ServerError("GetEmailAddressByIDAndEmail failed", err)
+ return
+ }
+ err = email.UpdateEmailAddress(newEmailAddress)
+ if err != nil {
+ ctx.ServerError("UpdateEmailAddress failed", err)
+ return
+ }
+ ctx.Data["Email"] = newEmailAddress
+ ctx.User.Email = newEmailAddress
+ Activate(ctx)
+
+}
+
// Activate render activate user page
func Activate(ctx *context.Context) {
code := ctx.Query("code")
diff --git a/services/cloudbrain/cloudbrainTask/notebook.go b/services/cloudbrain/cloudbrainTask/notebook.go
new file mode 100644
index 000000000..6b2fcf707
--- /dev/null
+++ b/services/cloudbrain/cloudbrainTask/notebook.go
@@ -0,0 +1,362 @@
+package cloudbrainTask
+
+import (
+ "fmt"
+ "net/http"
+ "path"
+
+ "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"
+)
+
+const NoteBookExtension = ".ipynb"
+
+func FileNotebookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption) {
+
+ if ctx.Written() {
+ return
+ }
+
+ if path.Ext(option.File) != NoteBookExtension {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_select_wrong")))
+ return
+ }
+
+ isNotebookFileExist, _ := isNoteBookFileExist(ctx, option)
+ if !isNotebookFileExist {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist")))
+ return
+ }
+
+ sourceRepo, err := models.GetRepositoryByOwnerAndName(option.OwnerName, option.ProjectName)
+ if err != nil {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist")))
+ return
+ }
+
+ permission, err := models.GetUserRepoPermission(sourceRepo, ctx.User)
+ if err != nil {
+ log.Error("Get permission failed", err)
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_no_right")))
+ return
+ }
+
+ if !permission.CanRead(models.UnitTypeCode) {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_no_right")))
+ 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(ctx.Tr("repo.failed_to_create_notebook_repo",setting.FileNoteBook.ProjectName)))
+ return
+ }
+ if option.Type <= 1 {
+ cloudBrainFileNoteBookCreate(ctx, option, repo, sourceRepo)
+ } else {
+ modelartsFileNoteBookCreate(ctx, option, repo, sourceRepo)
+ }
+
+}
+
+func cloudBrainFileNoteBookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption, repo *models.Repository, sourceRepo *models.Repository) {
+
+ displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name)
+ jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
+ jobType := string(models.JobTypeDebug)
+
+ 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.BaseMessageApi{
+ Code: 2,
+ Message: ctx.Tr("repo.cloudbrain.morethanonejob"),
+ })
+ return
+ }
+ }
+
+ errStr := uploadCodeFile(sourceRepo, getCodePath(jobName), option.BranchName, option.File, jobName)
+ if errStr != "" {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist")))
+ return
+ }
+ command := cloudbrain.GetCloudbrainDebugCommand()
+ 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
+ }
+ ctx.Repo = &context.Repository{
+ Repository: repo,
+ }
+
+ 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: "",
+ 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, sourceRepo *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.BaseMessageApi{
+ Code: 2,
+ Message: 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
+ }
+ }
+
+ err = downloadCode(sourceRepo, getCodePath(jobName), option.BranchName)
+ if err != nil {
+ ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.load_code_failed")))
+ return
+ }
+
+ var aiCenterCode = models.AICenterOfCloudBrainTwo
+ var specId = setting.FileNoteBook.SpecIdNPU
+ if setting.ModelartsCD.Enabled {
+ aiCenterCode = models.AICenterOfChengdu
+ specId = setting.FileNoteBook.SpecIdNPUCD
+ }
+ spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, 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
+ }
+ ctx.Repo = &context.Repository{
+ Repository: repo,
+ }
+
+ var jobId string
+ if setting.ModelartsCD.Enabled {
+ jobId, err = modelarts_cd.GenerateNotebook(ctx, displayJobName, jobName, "", getDescription(option), setting.FileNoteBook.ImageIdNPUCD, spec, option.File,modelarts.AutoStopDurationMs/4)
+ } else {
+ jobId, err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, "", getDescription(option), setting.FileNoteBook.ImageIdNPU, spec, option.File,modelarts.AutoStopDurationMs/4)
+ }
+
+ 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 isNoteBookFileExist(ctx *context.Context, option api.CreateFileNotebookJobOption) (bool, error) {
+ repoPathOfNoteBook := models.RepoPath(option.OwnerName, option.ProjectName)
+
+ gitRepoOfNoteBook, err := git.OpenRepository(repoPathOfNoteBook)
+ if err != nil {
+ log.Error("RepoRef Invalid repo "+repoPathOfNoteBook, err.Error())
+ return false, err
+ }
+ // We opened it, we should close it
+ defer func() {
+ // If it's been set to nil then assume someone else has closed it.
+ if gitRepoOfNoteBook != nil {
+ gitRepoOfNoteBook.Close()
+ }
+ }()
+ fileExist, err := fileExists(gitRepoOfNoteBook, option.File, option.BranchName)
+ if err != nil || !fileExist {
+ log.Error("Get file error:", err, ctx.Data["MsgID"])
+
+ return false, err
+ }
+ return true, nil
+}
+
+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"
+ }
+ return ""
+}
+
+func fileExists(gitRepo *git.Repository, path string, branch string) (bool, error) {
+
+ commit, err := gitRepo.GetBranchCommit(branch)
+ if err != nil {
+ return false, err
+ }
+ if _, err := commit.GetTreeEntryByPath(path); err != nil {
+ return false, err
+ }
+ return true, nil
+}
diff --git a/services/cloudbrain/cloudbrainTask/sync_status.go b/services/cloudbrain/cloudbrainTask/sync_status.go
index 67dc4d3b7..973b9bbc2 100644
--- a/services/cloudbrain/cloudbrainTask/sync_status.go
+++ b/services/cloudbrain/cloudbrainTask/sync_status.go
@@ -1,20 +1,21 @@
package cloudbrainTask
import (
- "net/http"
-
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/cloudbrain"
- "code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/setting"
+ "net/http"
+ "strconv"
)
var noteBookOKMap = make(map[int64]int, 20)
+var noteBookFailMap = make(map[int64]int, 20)
-//if a task notebook url can get two times, the notebook can browser.
+//if a task notebook url can get successfulCount times, the notebook can browser.
const successfulCount = 3
+const maxSuccessfulCount=10
func SyncCloudBrainOneStatus(task *models.Cloudbrain) (*models.Cloudbrain, error) {
jobResult, err := cloudbrain.GetJob(task.JobID)
@@ -62,21 +63,29 @@ func isNoteBookReady(task *models.Cloudbrain) bool {
return true
}
noteBookUrl := setting.DebugServerHost + "jpylab_" + task.JobID + "_" + task.SubTaskName
- r := httplib.Get(noteBookUrl)
- res, err := r.Response()
+ res,err := http.Get(noteBookUrl)
if err != nil {
return false
}
+ log.Info("notebook success count:"+strconv.Itoa(noteBookOKMap[task.ID])+",fail count:"+strconv.Itoa(noteBookFailMap[task.ID]))
if res.StatusCode == http.StatusOK {
count := noteBookOKMap[task.ID]
- if count < successfulCount-1 {
+ if count==0{ //如果是第一次成功,把失败数重置为0
+ noteBookFailMap[task.ID]=0
+ }
+
+ if count < successfulCount-1 || (noteBookFailMap[task.ID]==0 && count < maxSuccessfulCount-1) {
noteBookOKMap[task.ID] = count + 1
return false
} else {
+ log.Info("notebook success count:"+strconv.Itoa(count)+",fail count:"+strconv.Itoa(noteBookFailMap[task.ID]))
delete(noteBookOKMap, task.ID)
+ delete(noteBookFailMap, task.ID)
return true
}
+ }else{
+ noteBookFailMap[task.ID]+=1
}
return false
diff --git a/services/cloudbrain/cloudbrainTask/train.go b/services/cloudbrain/cloudbrainTask/train.go
index 8e4673d66..00d01a7ce 100644
--- a/services/cloudbrain/cloudbrainTask/train.go
+++ b/services/cloudbrain/cloudbrainTask/train.go
@@ -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 {
diff --git a/services/cloudbrain/util.go b/services/cloudbrain/util.go
index dc9177ecf..0a3096e3f 100644
--- a/services/cloudbrain/util.go
+++ b/services/cloudbrain/util.go
@@ -1,7 +1,11 @@
package cloudbrain
import (
+ "regexp"
+ "strconv"
"strings"
+ "time"
+
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
@@ -33,6 +37,28 @@ func GetAiCenterShow(aiCenter string, ctx *context.Context) string {
}
+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, "")
+}
+
func GetAiCenterInfoByCenterCode(aiCenterCode string) *setting.C2NetSequenceInfo {
if setting.AiCenterCodeAndNameMapInfo != nil {
if info, ok := setting.AiCenterCodeAndNameMapInfo[aiCenterCode]; ok {
diff --git a/templates/admin/cloudbrain/list.tmpl b/templates/admin/cloudbrain/list.tmpl
index 20e704a4d..94f80c0fa 100755
--- a/templates/admin/cloudbrain/list.tmpl
+++ b/templates/admin/cloudbrain/list.tmpl
@@ -238,6 +238,7 @@
{{$.i18n.Tr "repo.debug"}}
{{else}}
+ {{if not .BootFile}}
{{end}}
+ {{end}}
{{end}}
diff --git a/templates/repo/cloudbrain/inference/show.tmpl b/templates/repo/cloudbrain/inference/show.tmpl
index aee08d659..b86accead 100644
--- a/templates/repo/cloudbrain/inference/show.tmpl
+++ b/templates/repo/cloudbrain/inference/show.tmpl
@@ -362,7 +362,7 @@
diff --git a/templates/repo/cloudbrain/show.tmpl b/templates/repo/cloudbrain/show.tmpl
index cca85fb32..27c3cc556 100755
--- a/templates/repo/cloudbrain/show.tmpl
+++ b/templates/repo/cloudbrain/show.tmpl
@@ -337,6 +337,7 @@
- 创建人
+ {{$.i18n.Tr "repo.cloudbrain_creator"}}
@@ -444,6 +444,7 @@