Browse Source

镜像管理

tags/v1.22.4.1^2
ychao_1983 3 years ago
parent
commit
4793fae46b
12 changed files with 616 additions and 25 deletions
  1. +9
    -1
      models/cloudbrain.go
  2. +415
    -0
      models/cloudbrain_image.go
  3. +2
    -0
      models/models.go
  4. +19
    -1
      modules/auth/cloudbrain.go
  5. +34
    -0
      modules/cloudbrain/cloudbrain.go
  6. +33
    -2
      modules/cloudbrain/resty.go
  7. +5
    -3
      modules/setting/cloudbrain.go
  8. +5
    -3
      options/locale/locale_en-US.ini
  9. +4
    -2
      options/locale/locale_zh-CN.ini
  10. +6
    -0
      routers/admin/cloudbrains.go
  11. +72
    -12
      routers/repo/cloudbrain.go
  12. +12
    -1
      routers/routes/routes.go

+ 9
- 1
models/cloudbrain.go View File

@@ -518,13 +518,21 @@ type PoolInfo struct {
PoolType string `json:"pool_type"`
}

type CommitImageParams struct {
type CommitImageCloudBrainParams struct {
Ip string `json:"ip"`
TaskContainerId string `json:"taskContainerId"`
ImageTag string `json:"imageTag"`
ImageDescription string `json:"imageDescription"`
}

type CommitImageParams struct {
CommitImageCloudBrainParams
IsPrivate bool
Topics []string
CloudBrainType int
UID int64
}

type CommitImageResult struct {
Code string `json:"code"`
Msg string `json:"msg"`


+ 415
- 0
models/cloudbrain_image.go View File

@@ -0,0 +1,415 @@
package models

import (
"fmt"
"strings"

"xorm.io/builder"

"code.gitea.io/gitea/modules/timeutil"
)

const RECOMMOND_TYPE = 5
const NORMAL_TYPE = 0

type Image struct {
ID int64 `xorm:"pk autoincr"`
Type int `xorm:"INDEX NOT NULL"` //0 normal 5官方推荐,中间值保留为后续扩展
CloudbrainType int `xorm:"INDEX NOT NULL"` //0 云脑一 1云脑二
UID int64 `xorm:"INDEX NOT NULL"`
IsPrivate bool `xorm:"INDEX NOT NULL"`
Tag string `xorm:"varchar(100) UNIQUE"`
Description string `xorm:"varchar(765)"`
Topics []string `xorm:"TEXT JSON"`
Place string `xorm:"varchar(300)"`
NumStars int `xorm:"NOT NULL DEFAULT 0"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}

type ImageStar struct {
ID int64 `xorm:"pk autoincr"`
UID int64 `xorm:"UNIQUE(s)"`
ImageID int64 `xorm:"UNIQUE(s)"`
CreatedUnix timeutil.TimeStamp `xorm:"created"`
}

type ImageTopic struct {
ID int64
Name string `xorm:"UNIQUE VARCHAR(105)"`
ImageCount int
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
}

type ImageTopicRelation struct {
ImageID int64 `xorm:"UNIQUE(s)"`
TopicID int64 `xorm:"UNIQUE(s)"`
}

type SearchImageOptions struct {
Keyword string
UID int64
IncludePublic bool
IncludeStarByMe bool
IncludeCustom bool
CodeLanguage string
Framework string
CudaVersion string
ListOptions
SearchOrderBy
}
type ErrorImageTagExist struct {
Tag string
}

func (err ErrorImageTagExist) Error() string {
return fmt.Sprintf("Image already exists [tag: %s]", err.Tag)
}

type ErrImageNotExist struct {
ID int64
}

func (err ErrImageNotExist) Error() string {
return fmt.Sprintf("Image does not exist [id: %d]", err.ID)
}

func IsErrImageTagExist(err error) bool {
_, ok := err.(ErrorImageTagExist)
return ok
}

func IsImageExist(tag string) (bool, error) {
return x.Exist(&Image{
Tag: tag,
})
}

type FindImageTopicOptions struct {
ListOptions
ImageID int64
Keyword string
}

func (opts *FindImageTopicOptions) toConds() builder.Cond {
var cond = builder.NewCond()
if opts.ImageID > 0 {
cond = cond.And(builder.Eq{"image_topic.image_id": opts.ImageID})
}

if opts.Keyword != "" {
cond = cond.And(builder.Like{"image_topic.name", strings.ToLower(opts.Keyword)})
}

return cond
}

func GetImageByID(id int64) (*Image, error) {
rel := new(Image)
has, err := x.
ID(id).
Get(rel)
if err != nil {
return nil, err
} else if !has {
return nil, ErrImageNotExist{id}
}

return rel, nil
}
func FindImageTopics(opts *FindImageTopicOptions) (topics []*ImageTopic, err error) {
sess := x.Select("image_topic.*").Where(opts.toConds())
if opts.ImageID > 0 {
sess.Join("INNER", "image_topic_relation", "image_topic_relation.topic_id = image_topic.id")
}
if opts.PageSize != 0 && opts.Page != 0 {
sess = opts.setSessionPagination(sess)
}
return topics, sess.Desc("image_topic.image_count").Find(&topics)
}

func SaveImageTopics(imageID int64, topicNames ...string) error {
topics, err := FindImageTopics(&FindImageTopicOptions{
ImageID: imageID,
})
if err != nil {
return err
}

sess := x.NewSession()
defer sess.Close()

if err := sess.Begin(); err != nil {
return err
}

var addedTopicNames []string
for _, topicName := range topicNames {
if strings.TrimSpace(topicName) == "" {
continue
}

var found bool
for _, t := range topics {
if strings.EqualFold(topicName, t.Name) {
found = true
break
}
}
if !found {
addedTopicNames = append(addedTopicNames, topicName)
}
}

var removeTopics []*ImageTopic
for _, t := range topics {
var found bool
for _, topicName := range topicNames {
if strings.EqualFold(topicName, t.Name) {
found = true
break
}
}
if !found {
removeTopics = append(removeTopics, t)
}
}

for _, topicName := range addedTopicNames {
_, err := addTopicByNameToImage(sess, imageID, topicName)
if err != nil {
return err
}
}

for _, topic := range removeTopics {
err := removeTopicFromImage(sess, imageID, topic)
if err != nil {
return err
}
}

topicNames = make([]string, 0, 25)
if err := sess.Table("image_topic").Cols("name").
Join("INNER", "image_topic_relation", "image_topic_relation.topic_id = image_topic.id").
Where("image_topic_relation.image_id = ?", imageID).Desc("image_topic.image_count").Find(&topicNames); err != nil {
return err
}

if _, err := sess.ID(imageID).Cols("topics").Update(&Image{
Topics: topicNames,
}); err != nil {
return err
}

return sess.Commit()
}

func addTopicByNameToImage(e Engine, imageID int64, topicName string) (*ImageTopic, error) {
var topic ImageTopic
has, err := e.Where("name = ?", topicName).Get(&topic)
if err != nil {
return nil, err
}
if !has {
topic.Name = topicName
topic.ImageCount = 1
if _, err := e.Insert(&topic); err != nil {
return nil, err
}
} else {
topic.ImageCount++
if _, err := e.ID(topic.ID).Cols("image_count").Update(&topic); err != nil {
return nil, err
}
}

if _, err := e.Insert(&ImageTopicRelation{
ImageID: imageID,
TopicID: topic.ID,
}); err != nil {
return nil, err
}

return &topic, nil
}

func removeTopicFromImage(e Engine, imageId int64, topic *ImageTopic) error {
topic.ImageCount--
if _, err := e.ID(topic.ID).Cols("image_count").Update(topic); err != nil {
return err
}

if _, err := e.Delete(&ImageTopicRelation{
ImageID: imageId,
TopicID: topic.ID,
}); err != nil {
return err
}

return nil
}

/*func SearchImage(opts *SearchImageOptions) ([]*Image, int64, error) {
cond := SearchImageCondition(opts)
return SearchImageByCondition(opts, cond)
}*/

func SearchImageCondition(opts *SearchImageOptions) builder.Cond {
var cond = builder.NewCond()

if len(opts.Keyword) > 0 {
cond = cond.And(builder.Or(builder.Like{"image.tag", opts.Keyword}, builder.Like{"image.description", opts.Keyword}))
}

if len(opts.CudaVersion) > 0 {
cond = cond.And(builder.Eq{"image.cuda_version": opts.CudaVersion})
}

if len(opts.CodeLanguage) > 0 {
cond = cond.And(builder.Eq{"image.code_language": opts.CodeLanguage})
}
if len(opts.Framework) > 0 {
cond = cond.And(builder.Eq{"image.framework": opts.Framework})
}

if opts.IncludePublic {
cond = cond.And(builder.Eq{"image.is_private": false})
}
/**
if opts.IncludeStarByMe {
cond = cond.And(builder.Eq{"dataset.status": DatasetStatusPublic})
cond = cond.And(builder.Eq{"attachment.is_private": false})
if opts.OwnerID > 0 {
if len(opts.Keyword) == 0 {
cond = cond.Or(builder.Eq{"repository.owner_id": opts.OwnerID})
} else {
subCon := builder.NewCond()
subCon = subCon.And(builder.Eq{"repository.owner_id": opts.OwnerID}, builder.Or(builder.Like{"dataset.title", opts.Keyword}, builder.Like{"dataset.description", opts.Keyword}))
cond = cond.Or(subCon)

}
}
} else if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"repository.owner_id": opts.OwnerID})
if !opts.IsOwner {
cond = cond.And(builder.Eq{"dataset.status": DatasetStatusPublic})
cond = cond.And(builder.Eq{"attachment.is_private": false})
}
}*/

return cond
}

/*func SearchImageByCondition(opts *SearchImageOptions, cond builder.Cond) ([]*Image, int64, error) {
if opts.Page <= 0 {
opts.Page = 1
}

var err error
sess := x.NewSession()
defer sess.Close()

datasets := make(DatasetList, 0, opts.PageSize)
selectColumnsSql := "distinct dataset.id,dataset.title, dataset.status, dataset.category, dataset.description, dataset.download_times, dataset.license, dataset.task, dataset.release_id, dataset.user_id, dataset.repo_id, dataset.created_unix,dataset.updated_unix,dataset.num_stars"

count, err := sess.Distinct("dataset.id").Join("INNER", "repository", "repository.id = dataset.repo_id").
Join("INNER", "attachment", "attachment.dataset_id=dataset.id").
Where(cond).Count(new(Dataset))

if err != nil {
return nil, 0, fmt.Errorf("Count: %v", err)
}

sess.Select(selectColumnsSql).Join("INNER", "repository", "repository.id = dataset.repo_id").
Join("INNER", "attachment", "attachment.dataset_id=dataset.id").
Where(cond).OrderBy(opts.SearchOrderBy.String())

if opts.PageSize > 0 {
sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
}
if err = sess.Find(&datasets); err != nil {
return nil, 0, fmt.Errorf("Dataset: %v", err)
}

if err = datasets.loadAttributes(sess); err != nil {
return nil, 0, fmt.Errorf("LoadAttributes: %v", err)
}

return datasets, count, nil
}*/

func CreateLocalImage(image *Image) error {

_, err := x.Insert(image)
return err
}

//star or unstar Image
func StarImage(userID, imageID int64, star bool) error {
sess := x.NewSession()
defer sess.Close()

if err := sess.Begin(); err != nil {
return err
}

if star {
if isImageStaring(sess, userID, imageID) {
return nil
}

if _, err := sess.Insert(&ImageStar{UID: userID, ImageID: imageID}); err != nil {
return err
}
if _, err := sess.Exec("UPDATE `image` SET num_stars = num_stars + 1 WHERE id = ?", imageID); err != nil {
return err
}
if _, err := sess.Exec("UPDATE `user` SET num_image_stars = num_image_stars + 1 WHERE id = ?", userID); err != nil {
return err
}
} else {
if !isImageStaring(sess, userID, imageID) {
return nil
}

if _, err := sess.Delete(&ImageStar{0, userID, imageID, 0}); err != nil {
return err
}
if _, err := sess.Exec("UPDATE `image` SET num_stars = num_stars - 1 WHERE id = ?", imageID); err != nil {
return err
}
if _, err := sess.Exec("UPDATE `user` SET num_image_stars = num_image_stars - 1 WHERE id = ?", userID); err != nil {
return err
}
}

return sess.Commit()
}

func IsImageStaring(userID, datasetID int64) bool {
return isImageStaring(x, userID, datasetID)

}

func isImageStaring(e Engine, userID, imageID int64) bool {
has, _ := e.Get(&ImageStar{0, userID, imageID, 0})
return has
}
func RecommendImage(imageId int64, recommond bool) error {

image := Image{Type: getRecommondType(recommond)}
_, err := x.ID(imageId).Cols("type").Update(image)
return err
}

func getRecommondType(recommond bool) int {
if recommond {

return RECOMMOND_TYPE
} else {
return NORMAL_TYPE
}

}

+ 2
- 0
models/models.go View File

@@ -131,6 +131,8 @@ func init() {
new(Dataset),
new(DatasetStar),
new(Cloudbrain),
new(Image),
new(ImageStar),
new(FileChunk),
new(BlockChain),
new(RecommendOrg),


+ 19
- 1
modules/auth/cloudbrain.go View File

@@ -24,9 +24,27 @@ type CreateCloudBrainForm struct {

type CommitImageCloudBrainForm struct {
Description string `form:"description" binding:"Required"`
Tag string `form:"tag" binding:"Required"`
Type int `form:"type" binding:"Required"`
Tag string `form:"tag" binding:"Required;MaxSize(64)" `
IsPrivate bool `form:"isPrivate" binding:"Required"`
Topics string `form:"topics"`
}

type EditImageCloudBrainForm struct {
ID int64 `form:"id" binding:"Required"`
Description string `form:"description" binding:"Required"`
IsPrivate bool `form:"isPrivate" binding:"Required"`
Topics string `form:"topics"`
}

func (f *CreateCloudBrainForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

func (f *CommitImageCloudBrainForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

func (f *EditImageCloudBrainForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

+ 34
- 0
modules/cloudbrain/cloudbrain.go View File

@@ -83,6 +83,18 @@ func isAdminOrJobCreater(ctx *context.Context, job *models.Cloudbrain, err error

}

func isAdminOrImageCreater(ctx *context.Context, image *models.Image, err error) bool {
if !ctx.IsSigned {
return false
}
if err != nil {
return ctx.IsUserSiteAdmin()
} else {
return ctx.IsUserSiteAdmin() || ctx.User.ID == image.UID
}

}

func AdminOrOwnerOrJobCreaterRight(ctx *context.Context) {

var ID = ctx.Params(":id")
@@ -147,6 +159,28 @@ func AdminOrJobCreaterRightForTrain(ctx *context.Context) {

}

func AdminOrImageCreaterRight(ctx *context.Context) {

id, err := strconv.ParseInt(ctx.Params(":id"), 10, 64)
var image *models.Image
if err != nil {
log.Error("Get Image by ID failed:%v", err.Error())

} else {
image, err = models.GetImageByID(id)
if err != nil {
log.Error("Get Image by ID failed:%v", err.Error())
return
}
}

if !isAdminOrImageCreater(ctx, image, err) {
log.Error("!isAdminOrImageCreater error:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
}

}

func GenerateTask(ctx *context.Context, displayJobName, jobName, image, command, uuid, codePath, modelPath, benchmarkPath, snn4imagenetPath, brainScorePath, jobType, gpuQueue, description string, benchmarkTypeID, benchmarkChildTypeID, resourceSpecId int) error {
dataActualPath := setting.Attachment.Minio.RealPath +
setting.Attachment.Minio.Bucket + "/" +


+ 33
- 2
modules/cloudbrain/resty.go View File

@@ -210,6 +210,17 @@ func getQueryString(page int, size int, name string) string {
}

func CommitImage(jobID string, params models.CommitImageParams) error {

has, err := models.IsImageExist(params.ImageTag)
if err != nil {
return fmt.Errorf("resty CommitImage: %v", err)
}
if has {
return models.ErrorImageTagExist{
Tag: params.ImageTag,
}
}

checkSetting()
client := getRestyClient()
var result models.CommitImageResult
@@ -220,7 +231,7 @@ sendjob:
res, err := client.R().
SetHeader("Content-Type", "application/json").
SetAuthToken(TOKEN).
SetBody(params).
SetBody(params.CommitImageCloudBrainParams).
SetResult(&result).
Post(HOST + "/rest-server/api/v1/jobs/" + jobID + "/commitImage")

@@ -238,7 +249,27 @@ sendjob:
return fmt.Errorf("CommitImage err: %s", res.String())
}

return nil
err = models.WithTx(func(ctx models.DBContext) error {
image := models.Image{
Type: models.NORMAL_TYPE,
CloudbrainType: params.CloudBrainType,
UID: params.UID,
IsPrivate: params.IsPrivate,
Tag: params.ImageTag,
Description: params.ImageDescription,
Place: setting.Cloudbrain.ImageURLPrefix + params.ImageTag,
}
if err := models.CreateLocalImage(&image); err != nil {
log.Error("Failed to insert image record.", err)
return fmt.Errorf("CommitImage err: %s", res.String())
}
if err := models.SaveImageTopics(image.ID, params.Topics...); err != nil {
log.Error("Failed to insert image record.", err)
return fmt.Errorf("CommitImage err: %s", res.String())
}
return nil
})
return err
}

func StopJob(jobID string) error {


+ 5
- 3
modules/setting/cloudbrain.go View File

@@ -1,9 +1,10 @@
package setting

type CloudbrainLoginConfig struct {
Username string
Password string
Host string
Username string
Password string
Host string
ImageURLPrefix string
}

var (
@@ -15,5 +16,6 @@ func GetCloudbrainConfig() CloudbrainLoginConfig {
Cloudbrain.Username = cloudbrainSec.Key("USERNAME").MustString("")
Cloudbrain.Password = cloudbrainSec.Key("PASSWORD").MustString("")
Cloudbrain.Host = cloudbrainSec.Key("REST_SERVER_HOST").MustString("")
Cloudbrain.ImageURLPrefix = cloudbrainSec.Key("IMAGE_URL_PREFIX").MustString("")
return Cloudbrain
}

+ 5
- 3
options/locale/locale_en-US.ini View File

@@ -878,7 +878,7 @@ readme_helper = Select a README file template.
auto_init = Initialize Repository (Adds .gitignore, License and README)
create_repo = Create Repository
create_course = Publish Course
failed_to_create_course=Fail to publish course, please try again later.
failed_to_create_course=Failed to publish course, please try again later.
default_branch = Default Branch
mirror_prune = Prune
mirror_prune_desc = Remove obsolete remote-tracking references
@@ -912,6 +912,8 @@ more=More
gpu_type_all=All
model_download=Model Download
submit_image=Submit Image
image_exist=Image name has been used, please use a new one.
image_commit_fail=Failed to submit image, please try again later.
download=Download
score=Score

@@ -948,7 +950,7 @@ total_count_get_error=Can not get the total page.
last_update_time_error=Can not get the last updated time.
get_repo_stat_error=Can not get the statistics of the repository.
get_repo_info_error=Can not get the information of the repository.
generate_statistic_file_error=Fail to generate file.
generate_statistic_file_error=Failed to generate file.
repo_stat_inspect=ProjectAnalysis
all=All

@@ -1097,7 +1099,7 @@ form.name_reserved = The repository name '%s' is reserved.
form.course_name_reserved=The course name '%s' is reserved.
form.name_pattern_not_allowed = The pattern '%s' is not allowed in a repository name.
form.course_name_pattern_not_allowed=The pattern '%s' is not allowed in a course name.
add_course_org_fail=Fail to add organization, please try again later.
add_course_org_fail=Failed to add organization, please try again later.

need_auth = Clone Authorization
migrate_type = Migration Type


+ 4
- 2
options/locale/locale_zh-CN.ini View File

@@ -917,6 +917,8 @@ more=更多
gpu_type_all=全部
model_download=结果下载
submit_image=提交镜像
image_exist=镜像名称已被使用,请修改镜像名称。
image_commit_fail=提交镜像失败,请稍后再试。
download=模型下载
score=评分

@@ -2142,8 +2144,8 @@ branch.included=已包含

topic.manage_topics=管理主题
topic.done=保存
topic.count_prompt=您最多选择25个主题
topic.format_prompt=主题必须以中文、字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
topic.count_prompt=您最多选择25个标签
topic.format_prompt=标签必须以中文、字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

[org]
org_name_holder=组织名称


+ 6
- 0
routers/admin/cloudbrains.go View File

@@ -20,6 +20,7 @@ import (

const (
tplCloudBrains base.TplName = "admin/cloudbrain/list"
tplImages base.TplName = "admin/cloudbrain/images"
EXCEL_DATE_FORMAT = "20060102150405"
CREATE_TIME_FORMAT = "2006/01/02 15:04:05"
)
@@ -107,6 +108,11 @@ func CloudBrains(ctx *context.Context) {

}

func Images(ctx *context.Context) {
ctx.HTML(200, tplImages)

}

func DownloadCloudBrains(ctx *context.Context) {

page := 1


+ 72
- 12
routers/repo/cloudbrain.go View File

@@ -37,6 +37,8 @@ const (
tplCloudBrainBenchmarkIndex base.TplName = "repo/cloudbrain/benchmark/index"
tplCloudBrainBenchmarkNew base.TplName = "repo/cloudbrain/benchmark/new"
tplCloudBrainBenchmarkShow base.TplName = "repo/cloudbrain/benchmark/show"
tplCloudBrainImageSubmit base.TplName = "repo/cloudbrain/image/submit"
tplCloudBrainImageEdit base.TplName = "repo/cloudbrain/image/edit"
)

var (
@@ -447,26 +449,84 @@ func CloudBrainDebug(ctx *context.Context) {
ctx.Redirect(debugUrl)
}

func CloudBrainCommitImageShow(ctx *context.Context) {
ctx.Data["PageIsCloudBrain"] = true
ctx.Data["Type"] = ctx.Cloudbrain.Type
ctx.HTML(200, tplCloudBrainImageSubmit)
}

func CloudBrainImageEdit(ctx *context.Context) {
ctx.Data["PageIsImageEdit"] = true
ctx.Data["PageFrom"] = ctx.Params(":from")
var ID = ctx.Params(":id")
id, err := strconv.ParseInt(ID, 10, 64)
if err != nil {
log.Error("GetCloudbrainByID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)

image, err := models.GetImageByID(id)
if err != nil {
log.Error("GetCloudbrainByID failed:%v", err.Error())
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
}
ctx.Data["Image"] = image
ctx.HTML(http.StatusOK, tplCloudBrainImageSubmit)
}
}

func CloudBrainImageEditPost(ctx *context.Context, form auth.EditImageCloudBrainForm) {

}

func CloudBrainImageDelete(ctx *context.Context) {

}

func CloudBrainCommitImage(ctx *context.Context, form auth.CommitImageCloudBrainForm) {

var topics = make([]string, 0)
var topicsStr = strings.TrimSpace(form.Topics)
if len(topicsStr) > 0 {
topics = strings.Split(topicsStr, ",")
}

validTopics, invalidTopics := models.SanitizeAndValidateTopics(topics)

if len(validTopics) > 25 {
ctx.JSON(200, models.BaseErrorMessage(ctx.Tr("repo.topic.count_prompt")))
return
}

if len(invalidTopics) > 0 {
ctx.JSON(200, models.BaseErrorMessage(ctx.Tr("repo.topic.format_prompt")))
return
}

err := cloudbrain.CommitImage(ctx.Cloudbrain.JobID, models.CommitImageParams{
Ip: ctx.Cloudbrain.ContainerIp,
TaskContainerId: ctx.Cloudbrain.ContainerID,
ImageDescription: form.Description,
ImageTag: form.Tag,
CommitImageCloudBrainParams: models.CommitImageCloudBrainParams{
Ip: ctx.Cloudbrain.ContainerIp,
TaskContainerId: ctx.Cloudbrain.ContainerID,
ImageDescription: form.Description,
ImageTag: form.Tag,
},
IsPrivate: form.IsPrivate,
CloudBrainType: form.Type,
Topics: validTopics,
UID: ctx.User.ID,
})
if err != nil {
log.Error("CommitImage(%s) failed:%v", ctx.Cloudbrain.JobName, err.Error(), ctx.Data["msgID"])
ctx.JSON(200, map[string]string{
"result_code": "-1",
"error_msg": "CommitImage failed",
})
if models.IsErrImageTagExist(err) {
ctx.JSON(200, models.BaseErrorMessage(ctx.Tr("repo.image_exist")))

} else {
ctx.JSON(200, models.BaseErrorMessage(ctx.Tr("repo.image_commit_fail")))
}

return
}

ctx.JSON(200, map[string]string{
"result_code": "0",
"error_msg": "",
})
ctx.JSON(200, models.BaseOKMessage)
}

func CloudBrainStop(ctx *context.Context) {


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

@@ -330,6 +330,8 @@ func RegisterRoutes(m *macaron.Macaron) {
})
m.Get("/images/public", repo.GetPublicImages)
m.Get("/images/custom", repo.GetCustomImages)
m.Get("/images/star", repo.GetCustomImages)

m.Get("/repos", routers.ExploreRepos)
m.Get("/datasets", routers.ExploreDatasets)
m.Get("/users", routers.ExploreUsers)
@@ -523,6 +525,9 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("", admin.CloudBrains)
m.Get("/download", admin.DownloadCloudBrains)
})
m.Group("/images", func() {
m.Get("", admin.Images)
})

m.Group("/^:configType(hooks|system-hooks)$", func() {
m.Get("", admin.DefaultOrSystemWebhooks)
@@ -970,7 +975,12 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Group("/:username/:reponame", func() {
m.Post("/topics", repo.TopicsPost)
}, context.RepoAssignment(), context.RepoMustNotBeArchived(), reqRepoAdmin)

m.Group("/image/:id", func() {
m.Get("/:from", cloudbrain.AdminOrImageCreaterRight, repo.CloudBrainImageEdit)
m.Post("", cloudbrain.AdminOrImageCreaterRight, bindIgnErr(auth.EditImageCloudBrainForm{}), repo.CloudBrainImageEditPost)
m.Delete("", cloudbrain.AdminOrImageCreaterRight, repo.CloudBrainImageDelete)
})
m.Group("/:username/:reponame", func() {
m.Group("", func() {
m.Get("/^:type(issues|pulls)$", repo.Issues)
@@ -1012,6 +1022,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Group("/:id", func() {
m.Get("", reqRepoCloudBrainReader, repo.CloudBrainShow)
m.Get("/debug", cloudbrain.AdminOrJobCreaterRight, repo.CloudBrainDebug)
m.Get("/commit_image", cloudbrain.AdminOrJobCreaterRight, repo.CloudBrainCommitImageShow)
m.Post("/commit_image", cloudbrain.AdminOrJobCreaterRight, bindIgnErr(auth.CommitImageCloudBrainForm{}), repo.CloudBrainCommitImage)
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainStop)
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainDel)


Loading…
Cancel
Save