Browse Source

notebook

master
yuyuanshifu 4 years ago
parent
commit
7e35aeaf71
14 changed files with 1016 additions and 4 deletions
  1. +5
    -0
      custom/conf/app.ini.sample
  2. +156
    -0
      models/cloudbrain.go
  3. +2
    -2
      models/user.go
  4. +42
    -0
      modules/APIGW-go-sdk-2.0.2/core/escape.go
  5. +208
    -0
      modules/APIGW-go-sdk-2.0.2/core/signer.go
  6. +0
    -1
      modules/auth/cloudbrain.go
  7. +18
    -0
      modules/auth/modelarts.go
  8. +1
    -0
      modules/cloudbrain/cloudbrain.go
  9. +65
    -0
      modules/modelarts/modelarts.go
  10. +240
    -0
      modules/modelarts/resty.go
  11. +16
    -0
      modules/setting/setting.go
  12. +1
    -1
      routers/repo/cloudbrain.go
  13. +250
    -0
      routers/repo/modelarts.go
  14. +12
    -0
      routers/routes/routes.go

+ 5
- 0
custom/conf/app.ini.sample View File

@@ -1080,3 +1080,8 @@ BASE_PATH = attachment/

[modelarts]
ENDPOINT = 112.95.163.80
PROJECT_ID = edfccf24aace4e17a56da6bcbb55a5aa
PROJECT_NAME = cn-south-222_test
USERNAME = test1
PASSWORD = Qizhi@test.
DOMAIN = cn-south-222

+ 156
- 0
models/cloudbrain.go View File

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

type CloudbrainStatus string
type JobType string
type ModelArtsJobStatus string

const (
JobWaiting CloudbrainStatus = "WAITING"
@@ -24,6 +25,22 @@ const (

JobTypeDebug JobType = "DEBUG"
JobTypeBenchmark JobType = "BENCHMARK"

ModelArtsCreateQueue ModelArtsJobStatus = "CREATE_QUEUING" //免费资源创建排队中
ModelArtsCreating ModelArtsJobStatus = "CREATING" //创建中
ModelArtsCreateFailed ModelArtsJobStatus = "CREATE_FAILED" //创建失败
ModelArtsStartQueuing ModelArtsJobStatus = "START_QUEUING" //免费资源启动排队中
ModelArtsReadyToStart ModelArtsJobStatus = "READY_TO_START" //免费资源等待启动
ModelArtsStarting ModelArtsJobStatus = "STARTING" //启动中
ModelArtsRestarting ModelArtsJobStatus = "RESTARTING" //重启中
ModelArtsStartFailed ModelArtsJobStatus = "START_FAILED" //启动失败
ModelArtsRunning ModelArtsJobStatus = "RUNNING" //运行中
ModelArtsStopping ModelArtsJobStatus = "STOPPING" //停止中
ModelArtsStopped ModelArtsJobStatus = "STOPPED" //停止
ModelArtsUnavailable ModelArtsJobStatus = "UNAVAILABLE" //故障
ModelArtsDeleted ModelArtsJobStatus = "DELETED" //已删除
ModelArtsResizing ModelArtsJobStatus = "RESIZING" //规格变更中
ModelArtsResizFailed ModelArtsJobStatus = "RESIZE_FAILED" //规格变更失败
)

type Cloudbrain struct {
@@ -41,6 +58,7 @@ type Cloudbrain struct {
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
DeletedAt time.Time `xorm:"deleted"`
CanDebug bool `xorm:"-"`
Type int `xorm:"INDEX DEFAULT 0"`

User *User `xorm:"-"`
Repo *Repository `xorm:"-"`
@@ -112,6 +130,7 @@ type CloudbrainsOptions struct {
SortType string
CloudbrainIDs []int64
// JobStatus CloudbrainStatus
Type int
}
type TaskPod struct {
TaskRoleStatus struct {
@@ -257,6 +276,137 @@ type StopJobResult struct {
Msg string `json:"msg"`
}

type CreateNotebookParams struct {
JobName string `json:"name"`
Description string `json:"description"`
ProfileID string `json:"profile_id"`
Flavor string `json:"flavor"`
Spec Spec `json:"spec"`
Workspace Workspace `json:"workspace"`
}

type Workspace struct {
ID string `json:"id"`
}

type Spec struct {
Storage Storage `json:"storage"`
AutoStop AutoStop `json:"auto_stop"`
}

type AutoStop struct {
Enable bool `json:"enable"`
Duration int `json:"duration"`
}

type Storage struct {
Type string `json:"type"`
Location Location `json:"location"`
}

type Location struct {
Path string `json:"path"`
}

type CreateNotebookResult struct {
ErrorCode string `json:"error_code"`
ErrorMsg string `json:"error_msg"`
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Status string `json:"status"`
CreationTimestamp string `json:"creation_timestamp"`
LatestUpdateTimestamp string `json:"latest_update_timestamp"`
Profile struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
DeType string `json:"de_type"`
FlavorType string `json:"flavor_type"`
} `json:"profile"`
Flavor string `json:"flavor"`
FlavorDetails struct{
Name string `json:"name"`
Status string `json:"status"`
QueuingNum int `json:"queuing_num"`
QueueLeftTime int `json:"queue_left_time"` //s
Duration int `json:"duration"` //auto_stop_time s
} `json:"flavor_details"`
}

type GetNotebookResult struct {
ErrorCode string `json:"error_code"`
ErrorMsg string `json:"error_msg"`
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Status string `json:"status"`
CreationTimestamp string `json:"creation_timestamp"`
LatestUpdateTimestamp string `json:"latest_update_timestamp"`
Profile struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
DeType string `json:"de_type"`
FlavorType string `json:"flavor_type"`
} `json:"profile"`
Flavor string `json:"flavor"`
FlavorDetails struct{
Name string `json:"name"`
Status string `json:"status"`
QueuingNum int `json:"queuing_num"`
QueueLeftTime int `json:"queue_left_time"` //s
Duration int `json:"duration"` //auto_stop_time s
} `json:"flavor_details"`
QueuingInfo struct{
ID string `json:"id"`
Name string `json:"name"`
Flavor string `json:"flavor"`
DeType string `json:"de_type"`
Status string `json:"status"`
BeginTimestamp int `json:"begin_timestamp"`//time of instance begin in queue
RemainTime int `json:"remain_time"` //remain time of instance
EndTimestamp int `json:"end_timestamp"` //
Rank int `json:"rank"` //rank of instance in queue
} `json:"queuing_info"`
}

type GetTokenParams struct {
Auth Auth `json:auth`
}

type Auth struct {
Identity Identity `json:identity`
Scope Scope `json:scope`
}

type Scope struct {
Project Project `json:project`
}

type Project struct {
Name string `json:name`
}

type Identity struct {
Methods []string `json:"methods"`
Password Password `json:password`
}

type Password struct {
User NotebookUser `json:user`
}

type NotebookUser struct {
Name string `json:name`
Password string `json:"password"`
Domain Domain `json:domain`
}

type Domain struct {
Name string `json:name`
}

func Cloudbrains(opts *CloudbrainsOptions) ([]*Cloudbrain, int64, error) {
sess := x.NewSession()
defer sess.Close()
@@ -280,6 +430,12 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*Cloudbrain, int64, error) {
)
}

if (opts.Type) >= 0 {
cond = cond.And(
builder.Eq{"cloudbrain.type": opts.Type},
)
}

// switch opts.JobStatus {
// case JobWaiting:
// cond.And(builder.Eq{"cloudbrain.status": int(JobWaiting)})


+ 2
- 2
models/user.go View File

@@ -2045,8 +2045,8 @@ func SyncExternalUsers(ctx context.Context, updateExisting bool) error {

func GetBlockChainUnSuccessUsers() ([]*User, error) {
users := make([]*User, 0, 10)
err := x.Where("public_key is null").
Or("private_key is null").
err := x.Where("public_key = ''").
Or("private_key = ''").
Find(&users)
return users, err
}

+ 42
- 0
modules/APIGW-go-sdk-2.0.2/core/escape.go View File

@@ -0,0 +1,42 @@
// based on https://github.com/golang/go/blob/master/src/net/url/url.go
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package core

func shouldEscape(c byte) bool {
if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c == '-' || c == '~' || c == '.' {
return false
}
return true
}
func escape(s string) string {
hexCount := 0
for i := 0; i < len(s); i++ {
c := s[i]
if shouldEscape(c) {
hexCount++
}
}

if hexCount == 0 {
return s
}

t := make([]byte, len(s)+2*hexCount)
j := 0
for i := 0; i < len(s); i++ {
switch c := s[i]; {
case shouldEscape(c):
t[j] = '%'
t[j+1] = "0123456789ABCDEF"[c>>4]
t[j+2] = "0123456789ABCDEF"[c&15]
j += 3
default:
t[j] = s[i]
j++
}
}
return string(t)
}

+ 208
- 0
modules/APIGW-go-sdk-2.0.2/core/signer.go View File

@@ -0,0 +1,208 @@
// HWS API Gateway Signature
// based on https://github.com/datastream/aws/blob/master/signv4.go
// Copyright (c) 2014, Xianjie

package core

import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"fmt"
"io/ioutil"
"net/http"
"sort"
"strings"
"time"
)

const (
BasicDateFormat = "20060102T150405Z"
Algorithm = "SDK-HMAC-SHA256"
HeaderXDate = "X-Sdk-Date"
HeaderHost = "host"
HeaderAuthorization = "Authorization"
HeaderContentSha256 = "X-Sdk-Content-Sha256"
)

func hmacsha256(key []byte, data string) ([]byte, error) {
h := hmac.New(sha256.New, []byte(key))
if _, err := h.Write([]byte(data)); err != nil {
return nil, err
}
return h.Sum(nil), nil
}

// Build a CanonicalRequest from a regular request string
//
// CanonicalRequest =
// HTTPRequestMethod + '\n' +
// CanonicalURI + '\n' +
// CanonicalQueryString + '\n' +
// CanonicalHeaders + '\n' +
// SignedHeaders + '\n' +
// HexEncode(Hash(RequestPayload))
func CanonicalRequest(r *http.Request, signedHeaders []string) (string, error) {
var hexencode string
var err error
if hex := r.Header.Get(HeaderContentSha256); hex != "" {
hexencode = hex
} else {
data, err := RequestPayload(r)
if err != nil {
return "", err
}
hexencode, err = HexEncodeSHA256Hash(data)
if err != nil {
return "", err
}
}
return fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s", r.Method, CanonicalURI(r), CanonicalQueryString(r), CanonicalHeaders(r, signedHeaders), strings.Join(signedHeaders, ";"), hexencode), err
}

// CanonicalURI returns request uri
func CanonicalURI(r *http.Request) string {
pattens := strings.Split(r.URL.Path, "/")
var uri []string
for _, v := range pattens {
uri = append(uri, escape(v))
}
urlpath := strings.Join(uri, "/")
if len(urlpath) == 0 || urlpath[len(urlpath)-1] != '/' {
urlpath = urlpath + "/"
}
return urlpath
}

// CanonicalQueryString
func CanonicalQueryString(r *http.Request) string {
var keys []string
query := r.URL.Query()
for key := range query {
keys = append(keys, key)
}
sort.Strings(keys)
var a []string
for _, key := range keys {
k := escape(key)
sort.Strings(query[key])
for _, v := range query[key] {
kv := fmt.Sprintf("%s=%s", k, escape(v))
a = append(a, kv)
}
}
queryStr := strings.Join(a, "&")
r.URL.RawQuery = queryStr
return queryStr
}

// CanonicalHeaders
func CanonicalHeaders(r *http.Request, signerHeaders []string) string {
var a []string
header := make(map[string][]string)
for k, v := range r.Header {
header[strings.ToLower(k)] = v
}
for _, key := range signerHeaders {
value := header[key]
if strings.EqualFold(key, HeaderHost) {
value = []string{r.Host}
}
sort.Strings(value)
for _, v := range value {
a = append(a, key+":"+strings.TrimSpace(v))
}
}
return fmt.Sprintf("%s\n", strings.Join(a, "\n"))
}

// SignedHeaders
func SignedHeaders(r *http.Request) []string {
var a []string
for key := range r.Header {
a = append(a, strings.ToLower(key))
}
sort.Strings(a)
return a
}

// RequestPayload
func RequestPayload(r *http.Request) ([]byte, error) {
if r.Body == nil {
return []byte(""), nil
}
b, err := ioutil.ReadAll(r.Body)
if err != nil {
return []byte(""), err
}
r.Body = ioutil.NopCloser(bytes.NewBuffer(b))
return b, err
}

// Create a "String to Sign".
func StringToSign(canonicalRequest string, t time.Time) (string, error) {
hash := sha256.New()
_, err := hash.Write([]byte(canonicalRequest))
if err != nil {
return "", err
}
return fmt.Sprintf("%s\n%s\n%x",
Algorithm, t.UTC().Format(BasicDateFormat), hash.Sum(nil)), nil
}

// Create the HWS Signature.
func SignStringToSign(stringToSign string, signingKey []byte) (string, error) {
hm, err := hmacsha256(signingKey, stringToSign)
return fmt.Sprintf("%x", hm), err
}

// HexEncodeSHA256Hash returns hexcode of sha256
func HexEncodeSHA256Hash(body []byte) (string, error) {
hash := sha256.New()
if body == nil {
body = []byte("")
}
_, err := hash.Write(body)
return fmt.Sprintf("%x", hash.Sum(nil)), err
}

// Get the finalized value for the "Authorization" header. The signature parameter is the output from SignStringToSign
func AuthHeaderValue(signature, accessKey string, signedHeaders []string) string {
return fmt.Sprintf("%s Access=%s, SignedHeaders=%s, Signature=%s", Algorithm, accessKey, strings.Join(signedHeaders, ";"), signature)
}

// Signature HWS meta
type Signer struct {
Key string
Secret string
}

// SignRequest set Authorization header
func (s *Signer) Sign(r *http.Request) error {
var t time.Time
var err error
var dt string
if dt = r.Header.Get(HeaderXDate); dt != "" {
t, err = time.Parse(BasicDateFormat, dt)
}
if err != nil || dt == "" {
t = time.Now()
r.Header.Set(HeaderXDate, t.UTC().Format(BasicDateFormat))
}
signedHeaders := SignedHeaders(r)
canonicalRequest, err := CanonicalRequest(r, signedHeaders)
if err != nil {
return err
}
stringToSign, err := StringToSign(canonicalRequest, t)
if err != nil {
return err
}
signature, err := SignStringToSign(stringToSign, []byte(s.Secret))
if err != nil {
return err
}
authValue := AuthHeaderValue(signature, s.Key, signedHeaders)
r.Header.Set(HeaderAuthorization, authValue)
return nil
}

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

@@ -5,7 +5,6 @@ import (
"gitea.com/macaron/macaron"
)

// CreateDatasetForm form for dataset page
type CreateCloudBrainForm struct {
JobName string `form:"job_name" binding:"Required"`
Image string `form:"image" binding:"Required"`


+ 18
- 0
modules/auth/modelarts.go View File

@@ -0,0 +1,18 @@
package auth

import (
"gitea.com/macaron/binding"
"gitea.com/macaron/macaron"
)

type CreateModelArtsForm struct {
JobName string `form:"job_name" binding:"Required"`
Image string `form:"image" binding:"Required"`
Command string `form:"command" binding:"Required"`
Attachment string `form:"attachment" binding:"Required"`
JobType string `form:"job_type" binding:"Required"`
}

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

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

@@ -98,6 +98,7 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath,
JobName: jobName,
SubTaskName: SubTaskName,
JobType: jobType,
Type: models.TypeCloudBrainOne,
})

if err != nil {


+ 65
- 0
modules/modelarts/modelarts.go View File

@@ -0,0 +1,65 @@
package modelarts

import (
"code.gitea.io/gitea/modules/setting"
"path"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
)

const (
storageTypeOBS = "obs"
autoStopDuration = 4 * 60 *60
flavor = "modelarts.kat1.xlarge"
profileID = "Python3-ascend910-arm"

subTaskName = "task1"

DataSetMountPath = "/home/ma-user/work"
)

func GenerateTask(ctx *context.Context, jobName, uuid string) error {
dataActualPath := setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/"
jobResult, err := CreateJob(models.CreateNotebookParams{
JobName: jobName,
Description:"",
ProfileID: profileID,
Flavor: flavor,
Spec: models.Spec{
Storage: models.Storage{
Type: storageTypeOBS,
Location:models.Location{
Path: dataActualPath,
},
},
AutoStop: models.AutoStop{
Enable: true,
Duration: autoStopDuration,
},
},

})
if err != nil {
log.Error("CreateJob failed:", err.Error())
return err
}

err = models.CreateCloudbrain(&models.Cloudbrain{
Status: string(models.JobWaiting),
UserID: ctx.User.ID,
RepoID: ctx.Repo.Repository.ID,
JobID: jobResult.ID,
JobName: jobName,
SubTaskName: subTaskName,
JobType: string(models.JobTypeDebug),
Type: models.TypeCloudBrainTwo,
})

if err != nil {
return err
}

return nil
}

+ 240
- 0
modules/modelarts/resty.go View File

@@ -0,0 +1,240 @@
package modelarts

import (
"code.gitea.io/gitea/modules/log"
"fmt"
"net/http"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/setting"
"github.com/go-resty/resty/v2"
)

var (
restyClient *resty.Client
HOST string
TOKEN string
)

const (
methodPassword = "password"

urlGetToken = "/v3/auth/tokens"
urlNotebook = "/demanager/instances"
urlQuaryNotebook = "/demanager/instances"
)
func getRestyClient() *resty.Client {
if restyClient == nil {
restyClient = resty.New()
}
return restyClient
}

func checkSetting() {
if len(HOST) != 0 && len(TOKEN) != 0 && restyClient != nil {
return
}

getToken()
}

func getToken() error {
HOST = setting.ModelArtsHost

client := getRestyClient()
params := models.GetTokenParams{
Auth: models.Auth{
Identity: models.Identity{
Methods: []string{methodPassword},
Password: models.Password{
User: models.NotebookUser{
Name: setting.ModelArtsUsername,
Password: setting.ModelArtsPassword,
Domain: models.Domain{
Name: setting.ModelArtsDomain,
},
},
},
},
Scope: models.Scope{
Project: models.Project{
Name: setting.ProjectName,
},
},
},
}

res, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody(params).
Post(HOST + urlGetToken)
if err != nil {
return fmt.Errorf("resty getToken: %s", err)
}

if res.StatusCode() != http.StatusCreated {
return fmt.Errorf("getToken failed:%s", res.String())
}

TOKEN = res.Header().Get("X-Subject-Token")

return nil
}

func CreateJob(createJobParams models.CreateNotebookParams) (*models.CreateNotebookResult, error) {
checkSetting()
client := getRestyClient()
var result models.CreateNotebookResult

retry := 0

sendjob:
res, err := client.R().
SetHeader("Content-Type", "application/json").
SetAuthToken(TOKEN).
SetBody(createJobParams).
SetResult(&result).
Post(HOST + "/v1/" + setting.ProjectID + urlNotebook)

if err != nil {
return nil, fmt.Errorf("resty create job: %s", err)
}

if res.StatusCode() == http.StatusUnauthorized && retry < 1 {
retry++
_ = getToken()
goto sendjob
}

if len(result.ErrorCode) != 0 {
log.Error("CreateJob failed(%s): %s", result.ErrorCode, result.ErrorMsg)
return &result, fmt.Errorf("CreateJob failed(%s): %s", result.ErrorCode, result.ErrorMsg)
}

return &result, nil
}

func GetJob(jobID string) (*models.GetNotebookResult, error) {
checkSetting()
client := getRestyClient()
var result models.GetNotebookResult

retry := 0

sendjob:
res, err := client.R().
SetHeader("Content-Type", "application/json").
SetAuthToken(TOKEN).
SetResult(&result).
Get(HOST + "/v1/" + setting.ProjectID + urlNotebook + jobID)

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

if res.StatusCode() == http.StatusUnauthorized && retry < 1 {
retry++
_ = getToken()
goto sendjob
}

if len(result.ErrorCode) != 0 {
return &result, fmt.Errorf("CreateJob failed(%s): %s", result.ErrorCode, result.ErrorMsg)
}

return &result, nil
}

func GetImages() (*models.GetImagesResult, error) {
checkSetting()
client := getRestyClient()
var getImagesResult models.GetImagesResult

retry := 0

sendjob:
res, err := client.R().
SetHeader("Content-Type", "application/json").
SetAuthToken(TOKEN).
SetResult(&getImagesResult).
Get(HOST + "/rest-server/api/v1/image/list/")

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

if res.StatusCode() == http.StatusUnauthorized && retry < 1 {
retry++
_ = getToken()
goto sendjob
}

//if len(result.ErrorCode) != 0 {
// return &result, fmt.Errorf("CreateJob failed(%s): %s", result.ErrorCode, result.ErrorMsg)
//}

return &getImagesResult, nil
}

func CommitImage(jobID string, params models.CommitImageParams) error {
checkSetting()
client := getRestyClient()
var result models.CommitImageResult

retry := 0

sendjob:
res, err := client.R().
SetHeader("Content-Type", "application/json").
SetAuthToken(TOKEN).
SetBody(params).
SetResult(&result).
Post(HOST + "/rest-server/api/v1/jobs/" + jobID + "/commitImage")

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

if res.StatusCode() == http.StatusUnauthorized && retry < 1 {
retry++
_ = getToken()
goto sendjob
}

//if len(result.ErrorCode) != 0 {
// return &result, fmt.Errorf("CreateJob failed(%s): %s", result.ErrorCode, result.ErrorMsg)
//}

return nil
}

func StopJob(jobID string) error {
checkSetting()
client := getRestyClient()
var result models.StopJobResult

retry := 0

sendjob:
res, err := client.R().
SetHeader("Content-Type", "application/json").
SetAuthToken(TOKEN).
SetResult(&result).
Delete(HOST + "/rest-server/api/v1/jobs/" + jobID)

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

if res.StatusCode() == http.StatusUnauthorized && retry < 1 {
retry++
_ = getToken()
goto sendjob
}

//if len(result.ErrorCode) != 0 {
// return &result, fmt.Errorf("CreateJob failed(%s): %s", result.ErrorCode, result.ErrorMsg)
//}

return nil
}

+ 16
- 0
modules/setting/setting.go View File

@@ -456,6 +456,14 @@ var (
Location string
BasePath string
//RealPath string

//modelarts config
ModelArtsHost string
ProjectID string
ProjectName string
ModelArtsUsername string
ModelArtsPassword string
ModelArtsDomain string
)

// DateLang transforms standard language locale name to corresponding value in datetime plugin.
@@ -1148,6 +1156,14 @@ func NewContext() {
Bucket = sec.Key("BUCKET").MustString("testopendata")
Location = sec.Key("LOCATION").MustString("cn-south-222")
BasePath = sec.Key("BASE_PATH").MustString("attachment/")

sec = Cfg.Section("modelarts")
ModelArtsHost = sec.Key("ENDPOINT").MustString("112.95.163.80")
ProjectID = sec.Key("PROJECT_ID").MustString("")
ProjectName = sec.Key("PROJECT_NAME").MustString("")
ModelArtsUsername = sec.Key("USERNAME").MustString("")
ModelArtsPassword = sec.Key("PASSWORD").MustString("")
ModelArtsDomain = sec.Key("DOMAIN").MustString("cn-south-222")
}

func loadInternalToken(sec *ini.Section) string {


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

@@ -46,7 +46,7 @@ func CloudBrainIndex(ctx *context.Context) {
PageSize: setting.UI.IssuePagingNum,
},
RepoID: repo.ID,
// SortType: sortType,
Type: models.TypeCloudBrainOne,
})
if err != nil {
ctx.ServerError("Cloudbrain", err)


+ 250
- 0
routers/repo/modelarts.go View File

@@ -0,0 +1,250 @@
package repo

import (
"code.gitea.io/gitea/modules/modelarts"
"errors"
"strconv"
"time"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/cloudbrain"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)

const (
tplModelArtsIndex base.TplName = "repo/modelarts/index"
tplModelArtsNew base.TplName = "repo/modelarts/new"
tplModelArtsShow base.TplName = "repo/modelarts/show"
)

// MustEnableDataset check if repository enable internal cb
func MustEnableModelArts(ctx *context.Context) {
if !ctx.Repo.CanRead(models.UnitTypeCloudBrain) {
ctx.NotFound("MustEnableCloudbrain", nil)
return
}
}
func ModelArtsIndex(ctx *context.Context) {
MustEnableCloudbrain(ctx)
repo := ctx.Repo.Repository
page := ctx.QueryInt("page")
if page <= 0 {
page = 1
}

ciTasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{
ListOptions: models.ListOptions{
Page: page,
PageSize: setting.UI.IssuePagingNum,
},
RepoID: repo.ID,
// SortType: sortType,
})
if err != nil {
ctx.ServerError("Cloudbrain", err)
return
}

timestamp := time.Now().Unix()
for i, task := range ciTasks {
if task.Status == string(models.JobRunning) && (timestamp-int64(task.CreatedUnix) > 30) {
ciTasks[i].CanDebug = true
} else {
ciTasks[i].CanDebug = false
}
}

pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5)
pager.SetDefaultParams(ctx)
ctx.Data["Page"] = pager

ctx.Data["PageIsCloudBrain"] = true
ctx.Data["Tasks"] = ciTasks
ctx.HTML(200, tplCloudBrainIndex)
}

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

t := time.Now()
var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
ctx.Data["job_name"] = jobName

//attachs, err := models.GetAllUserAttachments(ctx.User.ID)
//if err != nil {
// ctx.ServerError("GetAllUserAttachments failed:", err)
// return
//}

//ctx.Data["attachments"] = attachs
//ctx.Data["command"] = cloudbrain.Command
//ctx.Data["code_path"] = cloudbrain.CodeMountPath
ctx.Data["dataset_path"] = modelarts.DataSetMountPath
//ctx.Data["model_path"] = cloudbrain.ModelMountPath
ctx.HTML(200, tplModelArtsNew)
}

func ModelArtsCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
ctx.Data["PageIsCloudBrain"] = true
jobName := form.JobName
uuid := form.Attachment
//repo := ctx.Repo.Repository

err := modelarts.GenerateTask(ctx, jobName, uuid)
if err != nil {
ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form)
return
}
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts")
}

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

var jobID = ctx.Params(":jobid")
task, err := models.GetCloudbrainByJobID(jobID)
if err != nil {
ctx.Data["error"] = err.Error()
}

//result, err := modelarts.GetJob(jobID)
result, err := cloudbrain.GetJob(jobID)
if err != nil {
ctx.Data["error"] = err.Error()
}

if result != nil {
jobRes, _ := models.ConvertToJobResultPayload(result.Payload)
ctx.Data["result"] = jobRes
taskRoles := jobRes.TaskRoles
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{}))
ctx.Data["taskRes"] = taskRes
task.Status = taskRes.TaskStatuses[0].State
task.ContainerID = taskRes.TaskStatuses[0].ContainerID
task.ContainerIp = taskRes.TaskStatuses[0].ContainerIP
err = models.UpdateJob(task)
if err != nil {
ctx.Data["error"] = err.Error()
}
}

ctx.Data["task"] = task
ctx.Data["jobID"] = jobID
ctx.HTML(200, tplCloudBrainShow)
}

func ModelArtsDebug(ctx *context.Context) {
var jobID = ctx.Params(":jobid")
task, err := models.GetCloudbrainByJobID(jobID)
if err != nil {
ctx.ServerError("GetCloudbrainByJobID failed", err)
return
}

//https://console.ai.pcl.cn/modelarts/internal/hub/notebook/user/DE-afcdf674-6489-11eb-bfe7-0255ac100057/lab
//debugUrl := setting.DebugServerHost + "jpylab_" + task.JobID + "_" + task.SubTaskName
debugUrl := "https://console.ai.pcl.cn/modelarts/internal/hub/notebook/user/" + task.JobID + "/lab"
ctx.Redirect(debugUrl)
}

func ModelArtsCommitImage(ctx *context.Context, form auth.CommitImageCloudBrainForm) {
var jobID = ctx.Params(":jobid")
task, err := models.GetCloudbrainByJobID(jobID)
if err != nil {
ctx.JSON(200, map[string]string{
"result_code": "-1",
"error_msg": "GetCloudbrainByJobID failed",
})
return
}

err = cloudbrain.CommitImage(jobID, models.CommitImageParams{
Ip: task.ContainerIp,
TaskContainerId: task.ContainerID,
ImageDescription: form.Description,
ImageTag: form.Tag,
})
if err != nil {
log.Error("CommitImage(%s) failed:", task.JobName, err.Error())
ctx.JSON(200, map[string]string{
"result_code": "-1",
"error_msg": "CommitImage failed",
})
return
}

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

func ModelArtsStop(ctx *context.Context) {
var jobID = ctx.Params(":jobid")
log.Info(jobID)
task, err := models.GetCloudbrainByJobID(jobID)
if err != nil {
ctx.ServerError("GetCloudbrainByJobID failed", err)
return
}

if task.Status != string(models.JobRunning) {
log.Error("the job(%s) is not running", task.JobName)
ctx.ServerError("the job is not running", errors.New("the job is not running"))
return
}

err = cloudbrain.StopJob(jobID)
if err != nil {
log.Error("StopJob(%s) failed:%v", task.JobName, err.Error())
ctx.ServerError("StopJob failed", err)
return
}

task.Status = string(models.JobStopped)
err = models.UpdateJob(task)
if err != nil {
ctx.ServerError("UpdateJob failed", err)
return
}

ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/cloudbrain")
}

func ModelArtsDel(ctx *context.Context) {
var jobID = ctx.Params(":jobid")
task, err := models.GetCloudbrainByJobID(jobID)
if err != nil {
ctx.ServerError("GetCloudbrainByJobID failed", err)
return
}

if task.Status != string(models.JobStopped) {
log.Error("the job(%s) has not been stopped", task.JobName)
ctx.ServerError("the job has not been stopped", errors.New("the job has not been stopped"))
return
}

err = models.DeleteJob(task)
if err != nil {
ctx.ServerError("DeleteJob failed", err)
return
}

ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/cloudbrain")
}

func ModelArtsBenchmark(ctx *context.Context) {
var jobID = ctx.Params(":jobid")
_, err := models.GetCloudbrainByJobID(jobID)
if err != nil {
ctx.ServerError("GetCloudbrainByJobID failed", err)
return
}

ctx.Redirect(setting.BenchmarkServerHost)
}

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

@@ -915,6 +915,18 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/create", reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainCreate)
}, context.RepoRef())

m.Group("/modelarts", func() {
m.Get("", reqRepoCloudBrainReader, repo.ModelArtsIndex)
m.Group("/:jobid", func() {
m.Get("", reqRepoCloudBrainReader, repo.ModelArtsShow)
m.Get("/debug", reqRepoCloudBrainReader, repo.ModelArtsDebug)
//m.Post("/stop", reqRepoCloudBrainWriter, repo.CloudBrainStop)
//m.Post("/del", reqRepoCloudBrainWriter, repo.CloudBrainDel)
})
m.Get("/create", reqRepoCloudBrainWriter, repo.ModelArtsNew)
m.Post("/create", reqRepoCloudBrainWriter, bindIgnErr(auth.CreateModelArtsForm{}), repo.ModelArtsCreate)
}, context.RepoRef())

m.Group("/blockchain", func() {
m.Get("", repo.BlockChainIndex)
}, context.RepoRef())


Loading…
Cancel
Save