cd-notebook
into V20220908
1 year ago
@@ -26,6 +26,7 @@ const ( | |||
TypeCloudBrainOne int = iota | |||
TypeCloudBrainTwo | |||
TypeC2Net //智算网络 | |||
TypeCDCenter //成都智算中心 | |||
TypeCloudBrainAll = -1 | |||
) | |||
@@ -596,16 +597,6 @@ type ResourceSpec struct { | |||
ShareMemMiB int `json:"shareMemMiB"` | |||
} | |||
type FlavorInfos struct { | |||
FlavorInfo []*FlavorInfo `json:"flavor_info"` | |||
} | |||
type FlavorInfo struct { | |||
Id int `json:"id"` | |||
Value string `json:"value"` | |||
Desc string `json:"desc"` | |||
} | |||
type SpecialPools struct { | |||
Pools []*SpecialPool `json:"pools"` | |||
} | |||
@@ -616,17 +607,7 @@ type SpecialPool struct { | |||
Pool []*GpuInfo `json:"pool"` | |||
JobType []string `json:"jobType"` | |||
ResourceSpec []*ResourceSpec `json:"resourceSpecs"` | |||
Flavor []*FlavorInfo `json:"flavor"` | |||
} | |||
type ImageInfosModelArts struct { | |||
ImageInfo []*ImageInfoModelArts `json:"image_info"` | |||
} | |||
type ImageInfoModelArts struct { | |||
Id string `json:"id"` | |||
Value string `json:"value"` | |||
Desc string `json:"desc"` | |||
Flavor []*setting.FlavorInfo `json:"flavor"` | |||
} | |||
type PoolInfos struct { | |||
@@ -732,6 +713,17 @@ type CreateNotebook2Params struct { | |||
Volume VolumeReq `json:"volume"` | |||
} | |||
type CreateNotebookWithoutPoolParams struct { | |||
JobName string `json:"name"` | |||
Description string `json:"description"` | |||
Duration int64 `json:"duration"` //ms | |||
Feature string `json:"feature"` | |||
Flavor string `json:"flavor"` | |||
ImageID string `json:"image_id"` | |||
WorkspaceID string `json:"workspace_id"` | |||
Volume VolumeReq `json:"volume"` | |||
} | |||
type VolumeReq struct { | |||
Capacity int `json:"capacity"` | |||
Category string `json:"category"` | |||
@@ -955,6 +947,7 @@ type NotebookGetJobTokenResult struct { | |||
} | |||
type NotebookDelResult struct { | |||
NotebookResult | |||
InstanceID string `json:"instance_id"` | |||
} | |||
@@ -1481,12 +1474,6 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { | |||
) | |||
} | |||
if len(opts.ComputeResource) > 0 { | |||
cond = cond.And( | |||
builder.Eq{"cloudbrain.compute_resource": opts.ComputeResource}, | |||
) | |||
} | |||
if len(opts.JobTypes) > 0 { | |||
if opts.JobTypeNot { | |||
cond = cond.And( | |||
@@ -1506,7 +1493,7 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { | |||
if (opts.Cluster) != "" { | |||
if opts.Cluster == "resource_cluster_openi" { | |||
cond = cond.And( | |||
builder.Or(builder.Eq{"cloudbrain.type": TypeCloudBrainOne}, builder.Eq{"cloudbrain.type": TypeCloudBrainTwo}), | |||
builder.Or(builder.Eq{"cloudbrain.type": TypeCloudBrainOne}, builder.Eq{"cloudbrain.type": TypeCloudBrainTwo}, builder.Eq{"cloudbrain.type": TypeCDCenter}), | |||
) | |||
} | |||
if opts.Cluster == "resource_cluster_c2net" { | |||
@@ -1959,7 +1946,7 @@ func GetWaitingCloudbrainCount(cloudbrainType int, computeResource string, jobTy | |||
func GetCloudbrainNotebookCountByUserID(userID int64) (int, error) { | |||
count, err := x.In("status", ModelArtsCreateQueue, ModelArtsCreating, ModelArtsStarting, ModelArtsReadyToStart, ModelArtsResizing, ModelArtsStartQueuing, ModelArtsRunning, ModelArtsRestarting). | |||
And("job_type = ? and user_id = ? and type = ?", JobTypeDebug, userID, TypeCloudBrainTwo).Count(new(Cloudbrain)) | |||
And("job_type = ? and user_id = ? and type in (?,?)", JobTypeDebug, userID, TypeCloudBrainTwo, TypeCDCenter).Count(new(Cloudbrain)) | |||
return int(count), err | |||
} | |||
@@ -30,8 +30,8 @@ const ( | |||
var ( | |||
poolInfos *models.PoolInfos | |||
FlavorInfos *models.FlavorInfos | |||
ImageInfos *models.ImageInfosModelArts | |||
FlavorInfos *setting.StFlavorInfos | |||
ImageInfos *setting.StImageInfosModelArts | |||
SpecialPools *models.SpecialPools | |||
) | |||
@@ -1,6 +1,7 @@ | |||
package modelarts | |||
import ( | |||
"code.gitea.io/gitea/modules/modelarts_cd" | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
@@ -68,8 +69,6 @@ const ( | |||
var ( | |||
poolInfos *models.PoolInfos | |||
FlavorInfos *models.FlavorInfos | |||
ImageInfos *models.ImageInfosModelArts | |||
TrainFlavorInfos *Flavor | |||
SpecialPools *models.SpecialPools | |||
MultiNodeConfig *MultiNodes | |||
@@ -757,11 +756,7 @@ func GetNotebookImageName(imageId string) (string, error) { | |||
var validImage = false | |||
var imageName = "" | |||
if ImageInfos == nil { | |||
json.Unmarshal([]byte(setting.ImageInfos), &ImageInfos) | |||
} | |||
for _, imageInfo := range ImageInfos.ImageInfo { | |||
for _, imageInfo := range setting.StImageInfos.ImageInfo { | |||
if imageInfo.Id == imageId { | |||
validImage = true | |||
imageName = imageInfo.Value | |||
@@ -825,8 +820,13 @@ func HandleTrainJobInfo(task *models.Cloudbrain) error { | |||
} | |||
func HandleNotebookInfo(task *models.Cloudbrain) error { | |||
result, err := GetNotebook2(task.JobID) | |||
var result *models.GetNotebook2Result | |||
var err error | |||
if task.Type == models.TypeCloudBrainTwo { | |||
result, err = GetNotebook2(task.JobID) | |||
} else if task.Type == models.TypeCDCenter { | |||
result, err = modelarts_cd.GetNotebook(task.JobID) | |||
} | |||
if err != nil { | |||
log.Error("GetNotebook2(%s) failed:%v", task.DisplayJobName, err) | |||
return err | |||
@@ -0,0 +1,214 @@ | |||
package modelarts_cd | |||
import ( | |||
"errors" | |||
"strconv" | |||
"strings" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/context" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/notification" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
) | |||
const ( | |||
//notebook | |||
storageTypeOBS = "obs" | |||
autoStopDuration = 4 * 60 * 60 | |||
autoStopDurationMs = 4 * 60 * 60 * 1000 | |||
MORDELART_USER_IMAGE_ENGINE_ID = -1 | |||
DataSetMountPath = "/home/ma-user/work" | |||
NotebookEnv = "Python3" | |||
NotebookType = "Ascend" | |||
FlavorInfo = "Ascend: 1*Ascend 910 CPU: 24 核 96GiB (modelarts.kat1.xlarge)" | |||
//train-job | |||
CodePath = "/code/" | |||
OutputPath = "/output/" | |||
ResultPath = "/result/" | |||
LogPath = "/log/" | |||
JobPath = "/job/" | |||
OrderDesc = "desc" //向下查询 | |||
OrderAsc = "asc" //向上查询 | |||
Lines = 500 | |||
TrainUrl = "train_url" | |||
DataUrl = "data_url" | |||
MultiDataUrl = "multi_data_url" | |||
ResultUrl = "result_url" | |||
CkptUrl = "ckpt_url" | |||
DeviceTarget = "device_target" | |||
Ascend = "Ascend" | |||
PerPage = 10 | |||
IsLatestVersion = "1" | |||
NotLatestVersion = "0" | |||
VersionCountOne = 1 | |||
SortByCreateTime = "create_time" | |||
ConfigTypeCustom = "custom" | |||
TotalVersionCount = 1 | |||
) | |||
var () | |||
type VersionInfo struct { | |||
Version []struct { | |||
ID int `json:"id"` | |||
Value string `json:"value"` | |||
Url string `json:"url"` | |||
} `json:"version"` | |||
} | |||
type Flavor struct { | |||
Info []struct { | |||
Code string `json:"code"` | |||
Value string `json:"value"` | |||
} `json:"flavor"` | |||
} | |||
type Engine struct { | |||
Info []struct { | |||
ID int `json:"id"` | |||
Value string `json:"value"` | |||
} `json:"engine"` | |||
} | |||
type ResourcePool struct { | |||
Info []struct { | |||
ID string `json:"id"` | |||
Value string `json:"value"` | |||
} `json:"resource_pool"` | |||
} | |||
type Parameters struct { | |||
Parameter []struct { | |||
Label string `json:"label"` | |||
Value string `json:"value"` | |||
} `json:"parameter"` | |||
} | |||
func GenerateNotebook(ctx *context.Context, displayJobName, jobName, uuid, description, flavor, imageId string) error { | |||
imageName, err := GetNotebookImageName(imageId) | |||
if err != nil { | |||
log.Error("GetNotebookImageName failed: %v", err.Error()) | |||
return err | |||
} | |||
createTime := timeutil.TimeStampNow() | |||
jobResult, err := createNotebook(models.CreateNotebookWithoutPoolParams{ | |||
JobName: jobName, | |||
Description: description, | |||
Flavor: flavor, | |||
Duration: autoStopDurationMs, | |||
ImageID: imageId, | |||
Feature: models.NotebookFeature, | |||
Volume: models.VolumeReq{ | |||
Capacity: setting.Capacity, | |||
Category: models.EVSCategory, | |||
Ownership: models.ManagedOwnership, | |||
}, | |||
WorkspaceID: "0", | |||
}) | |||
if err != nil { | |||
log.Error("createNotebook failed: %v", err.Error()) | |||
if strings.HasPrefix(err.Error(), UnknownErrorPrefix) { | |||
log.Info("(%s)unknown error, set temp status", displayJobName) | |||
errTemp := models.InsertCloudbrainTemp(&models.CloudbrainTemp{ | |||
JobID: models.TempJobId, | |||
VersionID: models.TempVersionId, | |||
Status: models.TempJobStatus, | |||
Type: models.TypeCDCenter, | |||
JobName: jobName, | |||
JobType: string(models.JobTypeDebug), | |||
}) | |||
if errTemp != nil { | |||
log.Error("InsertCloudbrainTemp failed: %v", errTemp.Error()) | |||
return errTemp | |||
} | |||
} | |||
return err | |||
} | |||
task := &models.Cloudbrain{ | |||
Status: jobResult.Status, | |||
UserID: ctx.User.ID, | |||
RepoID: ctx.Repo.Repository.ID, | |||
JobID: jobResult.ID, | |||
JobName: jobName, | |||
FlavorCode: flavor, | |||
DisplayJobName: displayJobName, | |||
JobType: string(models.JobTypeDebug), | |||
Type: models.TypeCDCenter, | |||
Uuid: uuid, | |||
ComputeResource: models.NPUResource, | |||
Image: imageName, | |||
Description: description, | |||
CreatedUnix: createTime, | |||
UpdatedUnix: createTime, | |||
} | |||
err = models.CreateCloudbrain(task) | |||
if err != nil { | |||
return err | |||
} | |||
stringId := strconv.FormatInt(task.ID, 10) | |||
notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, displayJobName, models.ActionCreateDebugNPUTask) | |||
return nil | |||
} | |||
func GetNotebookImageName(imageId string) (string, error) { | |||
var validImage = false | |||
var imageName = "" | |||
for _, imageInfo := range setting.StImageInfos.ImageInfo { | |||
if imageInfo.Id == imageId { | |||
validImage = true | |||
imageName = imageInfo.Value | |||
} | |||
} | |||
if !validImage { | |||
log.Error("the image id(%s) is invalid", imageId) | |||
return imageName, errors.New("the image id is invalid") | |||
} | |||
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 | |||
} | |||
*/ |
@@ -0,0 +1,220 @@ | |||
package modelarts_cd | |||
import ( | |||
"bytes" | |||
"code.gitea.io/gitea/modules/modelarts_gateway/core" | |||
"crypto/tls" | |||
"encoding/json" | |||
"fmt" | |||
"io/ioutil" | |||
"net/http" | |||
"strconv" | |||
"time" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/setting" | |||
) | |||
var ( | |||
httpClient *http.Client | |||
HOST string | |||
TOKEN string | |||
) | |||
const ( | |||
errorCodeExceedLimit = "ModelArts.0118" | |||
//notebook 2.0 | |||
urlNotebook2 = "/notebooks" | |||
//error code | |||
modelartsIllegalToken = "ModelArts.6401" | |||
NotebookNotFound = "ModelArts.6404" | |||
NotebookNoPermission = "ModelArts.6407" | |||
NotebookInvalid = "ModelArts.6400" | |||
UnknownErrorPrefix = "UNKNOWN:" | |||
) | |||
func getHttpClient() *http.Client { | |||
if httpClient == nil { | |||
httpClient = &http.Client{ | |||
Timeout: 30 * time.Second, | |||
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}, | |||
} | |||
} | |||
return httpClient | |||
} | |||
func GetNotebook(jobID string) (*models.GetNotebook2Result, error) { | |||
var result models.GetNotebook2Result | |||
client := getHttpClient() | |||
s := core.Signer{ | |||
Key: setting.ModelartsCD.AccessKey, | |||
Secret: setting.ModelartsCD.SecretKey, | |||
} | |||
r, _ := http.NewRequest(http.MethodGet, | |||
setting.ModelartsCD.EndPoint+"/v1/"+setting.ModelartsCD.ProjectID+urlNotebook2+"/"+jobID, | |||
nil) | |||
r.Header.Add("content-type", "application/json") | |||
s.Sign(r) | |||
resp, err := client.Do(r) | |||
if err != nil { | |||
log.Error("client.Do failed: %s", err.Error()) | |||
return &result, fmt.Errorf("client.Do failed: %s", err.Error()) | |||
} | |||
defer resp.Body.Close() | |||
body, err := ioutil.ReadAll(resp.Body) | |||
if err != nil { | |||
log.Error("ioutil.ReadAll failed: %s", err.Error()) | |||
return &result, fmt.Errorf("ioutil.ReadAll failed: %s", err.Error()) | |||
} | |||
err = json.Unmarshal(body, &result) | |||
if err != nil { | |||
log.Error("json.Unmarshal failed: %s", err.Error()) | |||
return &result, fmt.Errorf("son.Unmarshal failed: %s", err.Error()) | |||
} | |||
if len(result.ErrorCode) != 0 { | |||
log.Error("GetNotebook failed(%s): %s", result.ErrorCode, result.ErrorMsg) | |||
return &result, fmt.Errorf("GetNotebook failed(%s): %s", result.ErrorCode, result.ErrorMsg) | |||
} | |||
return &result, nil | |||
} | |||
func ManageNotebook(jobID string, param models.NotebookAction) (*models.NotebookActionResult, error) { | |||
var result models.NotebookActionResult | |||
client := getHttpClient() | |||
s := core.Signer{ | |||
Key: setting.ModelartsCD.AccessKey, | |||
Secret: setting.ModelartsCD.SecretKey, | |||
} | |||
r, _ := http.NewRequest(http.MethodPost, | |||
setting.ModelartsCD.EndPoint+"/v1/"+setting.ModelartsCD.ProjectID+urlNotebook2+"/"+jobID+"/"+param.Action+"?duration="+strconv.Itoa(autoStopDurationMs), | |||
nil) | |||
r.Header.Add("content-type", "application/json") | |||
s.Sign(r) | |||
resp, err := client.Do(r) | |||
if err != nil { | |||
log.Error("client.Do failed: %s", err.Error()) | |||
return &result, fmt.Errorf("client.Do failed: %s", err.Error()) | |||
} | |||
defer resp.Body.Close() | |||
body, err := ioutil.ReadAll(resp.Body) | |||
if err != nil { | |||
log.Error("ioutil.ReadAll failed: %s", err.Error()) | |||
return &result, fmt.Errorf("ioutil.ReadAll failed: %s", err.Error()) | |||
} | |||
err = json.Unmarshal(body, &result) | |||
if err != nil { | |||
log.Error("json.Unmarshal failed: %s", err.Error()) | |||
return &result, fmt.Errorf("son.Unmarshal failed: %s", err.Error()) | |||
} | |||
if len(result.ErrorCode) != 0 { | |||
log.Error("ManageNotebook2 failed(%s): %s", result.ErrorCode, result.ErrorMsg) | |||
return &result, fmt.Errorf("ManageNotebook failed(%s): %s", result.ErrorCode, result.ErrorMsg) | |||
} | |||
return &result, nil | |||
} | |||
func DelNotebook(jobID string) (*models.NotebookDelResult, error) { | |||
var result models.NotebookDelResult | |||
client := getHttpClient() | |||
s := core.Signer{ | |||
Key: setting.ModelartsCD.AccessKey, | |||
Secret: setting.ModelartsCD.SecretKey, | |||
} | |||
r, _ := http.NewRequest(http.MethodDelete, | |||
setting.ModelartsCD.EndPoint+"/v1/"+setting.ModelartsCD.ProjectID+urlNotebook2+"/"+jobID, | |||
nil) | |||
r.Header.Add("content-type", "application/json") | |||
s.Sign(r) | |||
resp, err := client.Do(r) | |||
if err != nil { | |||
log.Error("client.Do failed: %s", err.Error()) | |||
return &result, fmt.Errorf("client.Do failed: %s", err.Error()) | |||
} | |||
defer resp.Body.Close() | |||
body, err := ioutil.ReadAll(resp.Body) | |||
if err != nil { | |||
log.Error("ioutil.ReadAll failed: %s", err.Error()) | |||
return &result, fmt.Errorf("ioutil.ReadAll failed: %s", err.Error()) | |||
} | |||
err = json.Unmarshal(body, &result) | |||
if err != nil { | |||
log.Error("json.Unmarshal failed: %s", err.Error()) | |||
return &result, fmt.Errorf("son.Unmarshal failed: %s", err.Error()) | |||
} | |||
if len(result.ErrorCode) != 0 { | |||
log.Error("DelNotebook2 failed(%s): %s", result.ErrorCode, result.ErrorMsg) | |||
return &result, fmt.Errorf("DelNotebook2 failed(%s): %s", result.ErrorCode, result.ErrorMsg) | |||
} | |||
return &result, nil | |||
} | |||
func createNotebook(createJobParams models.CreateNotebookWithoutPoolParams) (*models.CreateNotebookResult, error) { | |||
var result models.CreateNotebookResult | |||
client := getHttpClient() | |||
s := core.Signer{ | |||
Key: setting.ModelartsCD.AccessKey, | |||
Secret: setting.ModelartsCD.SecretKey, | |||
} | |||
req, _ := json.Marshal(createJobParams) | |||
r, _ := http.NewRequest(http.MethodPost, | |||
setting.ModelartsCD.EndPoint+"/v1/"+setting.ModelartsCD.ProjectID+urlNotebook2, | |||
ioutil.NopCloser(bytes.NewBuffer(req))) | |||
r.Header.Add("content-type", "application/json") | |||
s.Sign(r) | |||
resp, err := client.Do(r) | |||
if err != nil { | |||
log.Error("client.Do failed: %s", err.Error()) | |||
return &result, fmt.Errorf("client.Do failed: %s", err.Error()) | |||
} | |||
defer resp.Body.Close() | |||
body, err := ioutil.ReadAll(resp.Body) | |||
if err != nil { | |||
log.Error("ioutil.ReadAll failed: %s", err.Error()) | |||
return &result, fmt.Errorf("ioutil.ReadAll failed: %s", err.Error()) | |||
} | |||
err = json.Unmarshal(body, &result) | |||
if err != nil { | |||
log.Error("json.Unmarshal failed: %s", err.Error()) | |||
return &result, fmt.Errorf("json.Unmarshal failed: %s", err.Error()) | |||
} | |||
if len(result.ErrorCode) != 0 { | |||
log.Error("createNotebook failed(%s): %s", result.ErrorCode, result.ErrorMsg) | |||
if result.ErrorCode == errorCodeExceedLimit { | |||
result.ErrorMsg = "所选规格使用数量已超过最大配额限制。" | |||
} | |||
return &result, fmt.Errorf("createNotebook failed(%s): %s", result.ErrorCode, result.ErrorMsg) | |||
} | |||
return &result, nil | |||
} |
@@ -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) | |||
} |
@@ -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 | |||
} |
@@ -75,6 +75,26 @@ type C2NetSqInfos struct { | |||
C2NetSqInfo []*C2NetSequenceInfo `json:"sequence"` | |||
} | |||
type StFlavorInfos struct { | |||
FlavorInfo []*FlavorInfo `json:"flavor_info"` | |||
} | |||
type FlavorInfo struct { | |||
Id int `json:"id"` | |||
Value string `json:"value"` | |||
Desc string `json:"desc"` | |||
} | |||
type StImageInfosModelArts struct { | |||
ImageInfo []*ImageInfoModelArts `json:"image_info"` | |||
} | |||
type ImageInfoModelArts struct { | |||
Id string `json:"id"` | |||
Value string `json:"value"` | |||
Desc string `json:"desc"` | |||
} | |||
var ( | |||
// AppVer settings | |||
AppVer string | |||
@@ -535,20 +555,32 @@ var ( | |||
AllowedOrg string | |||
ProfileID string | |||
PoolInfos string | |||
Flavor string | |||
FlavorInfos string | |||
DebugHost string | |||
ImageInfos string | |||
Capacity int | |||
MaxTempQueryTimes int | |||
StFlavorInfo *StFlavorInfos | |||
StImageInfos *StImageInfosModelArts | |||
//train-job | |||
ResourcePools string | |||
Engines string | |||
EngineVersions string | |||
FlavorInfos string | |||
TrainJobFLAVORINFOS string | |||
ModelArtsSpecialPools string | |||
ModelArtsMultiNode string | |||
// modelarts-cd config | |||
ModelartsCD = struct { | |||
Enabled bool | |||
EndPoint string | |||
ProjectID string | |||
AccessKey string | |||
SecretKey string | |||
ImageInfos string | |||
FlavorInfos string | |||
}{} | |||
//grampus config | |||
Grampus = struct { | |||
Env string | |||
@@ -1423,9 +1455,8 @@ func NewContext() { | |||
AllowedOrg = sec.Key("ORGANIZATION").MustString("") | |||
ProfileID = sec.Key("PROFILE_ID").MustString("") | |||
PoolInfos = sec.Key("POOL_INFOS").MustString("") | |||
Flavor = sec.Key("FLAVOR").MustString("") | |||
ImageInfos = sec.Key("IMAGE_INFOS").MustString("") | |||
Capacity = sec.Key("IMAGE_INFOS").MustInt(100) | |||
Capacity = sec.Key("CAPACITY").MustInt(100) | |||
MaxTempQueryTimes = sec.Key("MAX_TEMP_QUERY_TIMES").MustInt(30) | |||
ResourcePools = sec.Key("Resource_Pools").MustString("") | |||
Engines = sec.Key("Engines").MustString("") | |||
@@ -1474,8 +1505,8 @@ func NewContext() { | |||
Course.OrgName = sec.Key("org_name").MustString("") | |||
Course.TeamName = sec.Key("team_name").MustString("") | |||
GetGrampusConfig() | |||
getGrampusConfig() | |||
getModelartsCDConfig() | |||
getModelConvertConfig() | |||
} | |||
@@ -1498,7 +1529,22 @@ func getModelConvertConfig() { | |||
ModelConvert.NPU_TENSORFLOW_IMAGE_ID = sec.Key("NPU_TENSORFLOW_IMAGE_ID").MustInt(35) | |||
} | |||
func GetGrampusConfig() { | |||
func getModelartsCDConfig() { | |||
sec := Cfg.Section("modelarts-cd") | |||
ModelartsCD.Enabled = sec.Key("ENABLED").MustBool(false) | |||
ModelartsCD.EndPoint = sec.Key("ENDPOINT").MustString("https://modelarts.cn-southwest-228.cdzs.cn") | |||
ModelartsCD.ProjectID = sec.Key("PROJECT_ID").MustString("") | |||
ModelartsCD.AccessKey = sec.Key("ACCESS_KEY").MustString("") | |||
ModelartsCD.SecretKey = sec.Key("SECRET_KEY").MustString("") | |||
ModelartsCD.ImageInfos = sec.Key("IMAGE_INFOS").MustString("") | |||
ModelartsCD.FlavorInfos = sec.Key("FLAVOR_INFOS").MustString("") | |||
getNotebookImageInfos() | |||
getNotebookFlavorInfos() | |||
} | |||
func getGrampusConfig() { | |||
sec := Cfg.Section("grampus") | |||
Grampus.Env = sec.Key("ENV").MustString("TEST") | |||
@@ -1632,6 +1678,26 @@ func ensureLFSDirectory() { | |||
} | |||
} | |||
func getNotebookImageInfos() { | |||
if StImageInfos == nil { | |||
if ModelartsCD.Enabled { | |||
json.Unmarshal([]byte(ModelartsCD.ImageInfos), &StImageInfos) | |||
} else { | |||
json.Unmarshal([]byte(ImageInfos), &StImageInfos) | |||
} | |||
} | |||
} | |||
func getNotebookFlavorInfos() { | |||
if StFlavorInfo == nil { | |||
if ModelartsCD.Enabled { | |||
json.Unmarshal([]byte(ModelartsCD.FlavorInfos), &StFlavorInfo) | |||
} else { | |||
json.Unmarshal([]byte(FlavorInfos), &StFlavorInfo) | |||
} | |||
} | |||
} | |||
// NewServices initializes the services | |||
func NewServices() { | |||
InitDBConfig() | |||
@@ -1079,6 +1079,7 @@ balance.total_view = Total Balance | |||
balance.available = Available Balance: | |||
cloudbrain1 = cloudbrain1 | |||
cloudbrain2 = cloudbrain2 | |||
cdCenter = cd_ai_center | |||
cloudbrain_selection = select cloudbrain | |||
cloudbrain_platform_selection = Select the cloudbrain platform you want to use: | |||
confirm_choice = Confirm | |||
@@ -1080,6 +1080,7 @@ balance.total_view=余额总览 | |||
balance.available=可用余额: | |||
cloudbrain1=云脑1 | |||
cloudbrain2=云脑2 | |||
cdCenter=成都智算中心 | |||
intelligent_net=智算网络 | |||
cloudbrain_selection=云脑选择 | |||
cloudbrain_platform_selection=选择您准备使用的云脑平台: | |||
@@ -2765,6 +2765,8 @@ func GetCloudbrainAiCenter(task models.Cloudbrain, ctx *context.Context) string | |||
return ctx.Tr("repo.cloudbrain1") | |||
} else if task.Type == models.TypeCloudBrainTwo { | |||
return ctx.Tr("repo.cloudbrain2") | |||
} else if task.Type == models.TypeCDCenter { | |||
return ctx.Tr("repo.cdCenter") | |||
} else if task.Type == models.TypeC2Net { | |||
return getCutStringAiCenterByAiCenter(task.AiCenter) | |||
} | |||
@@ -2779,7 +2781,7 @@ func getCutStringAiCenterByAiCenter(aiCenter string) string { | |||
} | |||
func GetCloudbrainCluster(task models.Cloudbrain, ctx *context.Context) string { | |||
if task.Type == models.TypeCloudBrainOne || task.Type == models.TypeCloudBrainTwo { | |||
if task.Type == models.TypeCloudBrainOne || task.Type == models.TypeCloudBrainTwo || task.Type == models.TypeCDCenter { | |||
return ctx.Tr("cloudbrain.resource_cluster_openi") | |||
} else if task.Type == models.TypeC2Net { | |||
return ctx.Tr("cloudbrain.resource_cluster_c2net") | |||
@@ -2866,10 +2868,10 @@ func GetCloudbrainFlavorName(task models.Cloudbrain) (string, error) { | |||
return CloudbrainOneFlavorName, nil | |||
} | |||
} | |||
} else if (task.Type == models.TypeCloudBrainTwo || task.Type == models.TypeC2Net) && task.FlavorName != "" { | |||
} else if (task.Type == models.TypeCloudBrainTwo || task.Type == models.TypeC2Net || task.Type == models.TypeCDCenter) && task.FlavorName != "" { | |||
replaceFlavorName := strings.ReplaceAll(task.FlavorName, ":", ":") | |||
return replaceFlavorName, nil | |||
} else if task.Type == models.TypeCloudBrainTwo && task.FlavorName == "" && task.FlavorCode != "" { | |||
} else if (task.Type == models.TypeCloudBrainTwo || task.Type == models.TypeCDCenter) && task.FlavorName == "" && task.FlavorCode != "" { | |||
cloudbrainTwoFlavorName := getFlavorNameByFlavorCode(task.FlavorCode) | |||
return cloudbrainTwoFlavorName, nil | |||
} else if task.Type == models.TypeCloudBrainTwo && task.JobType == string(models.JobTypeDebug) && task.FlavorName == "" && task.FlavorCode == "" { | |||
@@ -2,6 +2,7 @@ package repo | |||
import ( | |||
"archive/zip" | |||
"code.gitea.io/gitea/modules/modelarts_cd" | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
@@ -60,18 +61,11 @@ func DebugJobIndex(ctx *context.Context) { | |||
if page <= 0 { | |||
page = 1 | |||
} | |||
typeCloudBrain := models.TypeCloudBrainAll | |||
jobTypeNot := false | |||
if listType == models.GPUResource { | |||
typeCloudBrain = models.TypeCloudBrainOne | |||
} else if listType == models.NPUResource { | |||
typeCloudBrain = models.TypeCloudBrainTwo | |||
} else if listType == models.AllResource { | |||
typeCloudBrain = models.TypeCloudBrainAll | |||
} else { | |||
log.Error("listType(%s) error", listType) | |||
ctx.ServerError("listType error", errors.New("listType error")) | |||
return | |||
var computeResource string | |||
if listType != models.AllResource { | |||
computeResource = listType | |||
} | |||
var jobTypes []string | |||
@@ -82,7 +76,8 @@ func DebugJobIndex(ctx *context.Context) { | |||
PageSize: setting.UI.IssuePagingNum, | |||
}, | |||
RepoID: repo.ID, | |||
Type: typeCloudBrain, | |||
ComputeResource: computeResource, | |||
Type: models.TypeCloudBrainAll, | |||
JobTypeNot: jobTypeNot, | |||
JobTypes: jobTypes, | |||
}) | |||
@@ -134,16 +129,8 @@ func notebookNewDataPrepare(ctx *context.Context) error { | |||
return err | |||
} | |||
ctx.Data["attachments"] = attachs | |||
if modelarts.ImageInfos == nil { | |||
json.Unmarshal([]byte(setting.ImageInfos), &modelarts.ImageInfos) | |||
} | |||
ctx.Data["images"] = modelarts.ImageInfos.ImageInfo | |||
if modelarts.FlavorInfos == nil { | |||
json.Unmarshal([]byte(setting.FlavorInfos), &modelarts.FlavorInfos) | |||
} | |||
ctx.Data["flavors"] = modelarts.FlavorInfos.FlavorInfo | |||
ctx.Data["images"] = setting.StImageInfos.ImageInfo | |||
ctx.Data["flavors"] = setting.StFlavorInfo.FlavorInfo | |||
setSpecBySpecialPoolConfig(ctx, string(models.JobTypeDebug)) | |||
ctx.Data["datasetType"] = models.TypeCloudBrainTwo | |||
@@ -154,50 +141,6 @@ func notebookNewDataPrepare(ctx *context.Context) error { | |||
return nil | |||
} | |||
func NotebookCreate(ctx *context.Context, form auth.CreateModelArtsNotebookForm) { | |||
ctx.Data["PageIsNotebook"] = true | |||
jobName := form.JobName | |||
uuid := form.Attachment | |||
description := form.Description | |||
flavor := form.Flavor | |||
count, err := models.GetCloudbrainNotebookCountByUserID(ctx.User.ID) | |||
if err != nil { | |||
log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||
cloudBrainNewDataPrepare(ctx) | |||
ctx.RenderWithErr("system error", tplModelArtsNotebookNew, &form) | |||
return | |||
} else { | |||
if count >= 1 { | |||
log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||
cloudBrainNewDataPrepare(ctx) | |||
ctx.RenderWithErr("you have already a running or waiting task, can not create more", tplModelArtsNotebookNew, &form) | |||
return | |||
} | |||
} | |||
_, err = models.GetCloudbrainByName(jobName) | |||
if err == nil { | |||
log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||
cloudBrainNewDataPrepare(ctx) | |||
ctx.RenderWithErr("the job name did already exist", tplModelArtsNotebookNew, &form) | |||
return | |||
} else { | |||
if !models.IsErrJobNotExist(err) { | |||
log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||
cloudBrainNewDataPrepare(ctx) | |||
ctx.RenderWithErr("system error", tplModelArtsNotebookNew, &form) | |||
return | |||
} | |||
} | |||
err = modelarts.GenerateTask(ctx, jobName, uuid, description, flavor) | |||
if err != nil { | |||
ctx.RenderWithErr(err.Error(), tplModelArtsNotebookNew, &form) | |||
return | |||
} | |||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||
} | |||
func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm) { | |||
ctx.Data["PageIsNotebook"] = true | |||
displayJobName := form.DisplayJobName | |||
@@ -247,7 +190,12 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm | |||
return | |||
} | |||
if setting.ModelartsCD.Enabled { | |||
err = modelarts_cd.GenerateNotebook(ctx, displayJobName, jobName, uuid, description, flavor, imageId) | |||
} else { | |||
err = modelarts.GenerateNotebook2(ctx, displayJobName, jobName, uuid, description, flavor, imageId) | |||
} | |||
if err != nil { | |||
log.Error("GenerateNotebook2 failed, %v", err, ctx.Data["MsgID"]) | |||
notebookNewDataPrepare(ctx) | |||
@@ -292,14 +240,11 @@ func NotebookShow(ctx *context.Context) { | |||
if err == nil { | |||
task.User = user | |||
} | |||
if modelarts.FlavorInfos == nil { | |||
json.Unmarshal([]byte(setting.FlavorInfos), &modelarts.FlavorInfos) | |||
} | |||
findSpec := false | |||
if modelarts.FlavorInfos != nil { | |||
ctx.Data["resource_spec"] = modelarts.FlavorInfos.FlavorInfo[0].Desc | |||
for _, f := range modelarts.FlavorInfos.FlavorInfo { | |||
if setting.StFlavorInfo != nil { | |||
ctx.Data["resource_spec"] = setting.StFlavorInfo.FlavorInfo[0].Desc | |||
for _, f := range setting.StFlavorInfo.FlavorInfo { | |||
if fmt.Sprint(f.Value) == task.FlavorCode { | |||
ctx.Data["resource_spec"] = f.Desc | |||
findSpec = true | |||
@@ -394,36 +339,16 @@ func setShowSpecBySpecialPoolConfig(ctx *context.Context, findSpec bool, task *m | |||
} | |||
} | |||
func NotebookDebug(ctx *context.Context) { | |||
var jobID = ctx.Params(":jobid") | |||
result, err := modelarts.GetJob(jobID) | |||
if err != nil { | |||
ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil) | |||
return | |||
} | |||
res, err := modelarts.GetJobToken(jobID) | |||
if err != nil { | |||
ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil) | |||
return | |||
} | |||
urls := strings.Split(result.Spec.Annotations.Url, "/") | |||
urlPrefix := result.Spec.Annotations.TargetDomain | |||
for i, url := range urls { | |||
if i > 2 { | |||
urlPrefix += "/" + url | |||
} | |||
} | |||
debugUrl := urlPrefix + "?token=" + res.Token | |||
ctx.Redirect(debugUrl) | |||
} | |||
func NotebookDebug2(ctx *context.Context) { | |||
var err error | |||
var result *models.GetNotebook2Result | |||
task := ctx.Cloudbrain | |||
result, err := modelarts.GetNotebook2(task.JobID) | |||
if task.Type == models.TypeCloudBrainTwo { | |||
result, err = modelarts.GetNotebook2(task.JobID) | |||
} else if task.Type == models.TypeCDCenter { | |||
result, err = modelarts_cd.GetNotebook(task.JobID) | |||
} | |||
if err != nil { | |||
ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil) | |||
return | |||
@@ -469,7 +394,13 @@ func NotebookRestart(ctx *context.Context) { | |||
Action: models.ActionStart, | |||
} | |||
res, err := modelarts.ManageNotebook2(task.JobID, param) | |||
var res *models.NotebookActionResult | |||
if task.Type == models.TypeCloudBrainTwo { | |||
res, err = modelarts.ManageNotebook2(task.JobID, param) | |||
} else if task.Type == models.TypeCDCenter { | |||
res, err = modelarts_cd.ManageNotebook(task.JobID, param) | |||
} | |||
if err != nil { | |||
log.Error("ManageNotebook2(%s) failed:%v", task.DisplayJobName, err.Error(), ctx.Data["MsgID"]) | |||
/* 暂不处理再次调试502的场景,详情见方案 | |||
@@ -555,7 +486,14 @@ func NotebookStop(ctx *context.Context) { | |||
Action: models.ActionStop, | |||
} | |||
res, err := modelarts.ManageNotebook2(task.JobID, param) | |||
var err error | |||
var res *models.NotebookActionResult | |||
if task.Type == models.TypeCloudBrainTwo { | |||
res, err = modelarts.ManageNotebook2(task.JobID, param) | |||
} else if task.Type == models.TypeCDCenter { | |||
res, err = modelarts_cd.ManageNotebook(task.JobID, param) | |||
} | |||
if err != nil { | |||
log.Error("ManageNotebook2(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||
resultCode = "-1" | |||
@@ -605,7 +543,13 @@ func NotebookDel(ctx *context.Context) { | |||
return | |||
} | |||
_, err := modelarts.DelNotebook2(task.JobID) | |||
var err error | |||
if task.Type == models.TypeCloudBrainTwo { | |||
_, err = modelarts.DelNotebook2(task.JobID) | |||
} else if task.Type == models.TypeCDCenter { | |||
_, err = modelarts_cd.DelNotebook(task.JobID) | |||
} | |||
if err != nil { | |||
log.Error("DelNotebook2(%s) failed:%v", task.JobName, err.Error()) | |||
if strings.Contains(err.Error(), modelarts.NotebookNotFound) || strings.Contains(err.Error(), modelarts.NotebookNoPermission) || strings.Contains(err.Error(), modelarts.NotebookInvalid) { | |||
@@ -2319,7 +2263,7 @@ func checkModelArtsSpecialPool(ctx *context.Context, flavorCode string, jobType | |||
if !isMatchPool { | |||
isMatchSpec := false | |||
if jobType == string(models.JobTypeDebug) { | |||
for _, flavor := range modelarts.FlavorInfos.FlavorInfo { | |||
for _, flavor := range setting.StFlavorInfo.FlavorInfo { | |||
if flavor.Value == flavorCode { | |||
isMatchSpec = true | |||
break | |||
Dear OpenI User
Thank you for your continuous support to the Openl Qizhi Community AI Collaboration Platform. In order to protect your usage rights and ensure network security, we updated the Openl Qizhi Community AI Collaboration Platform Usage Agreement in January 2024. The updated agreement specifies that users are prohibited from using intranet penetration tools. After you click "Agree and continue", you can continue to use our services. Thank you for your cooperation and understanding.
For more agreement content, please refer to the《Openl Qizhi Community AI Collaboration Platform Usage Agreement》