| @@ -566,6 +566,17 @@ type FlavorInfo struct { | |||||
| Desc string `json:"desc"` | Desc string `json:"desc"` | ||||
| } | } | ||||
| type SpecialPools struct { | |||||
| Pools []*SpecialPool `json:"pools"` | |||||
| } | |||||
| type SpecialPool struct { | |||||
| Org string `json:"org"` | |||||
| Type string `json:"type"` | |||||
| IsExclusive bool `json:"isExclusive"` | |||||
| Pool []*GpuInfo `json:"pool"` | |||||
| JobType []string `json:"jobType"` | |||||
| } | |||||
| type ImageInfosModelArts struct { | type ImageInfosModelArts struct { | ||||
| ImageInfo []*ImageInfoModelArts `json:"image_info"` | ImageInfo []*ImageInfoModelArts `json:"image_info"` | ||||
| } | } | ||||
| @@ -1,12 +1,16 @@ | |||||
| package grampus | package grampus | ||||
| import ( | import ( | ||||
| "encoding/json" | |||||
| "strings" | |||||
| "code.gitea.io/gitea/modules/setting" | |||||
| "code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
| "code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| "code.gitea.io/gitea/modules/notification" | "code.gitea.io/gitea/modules/notification" | ||||
| "code.gitea.io/gitea/modules/timeutil" | "code.gitea.io/gitea/modules/timeutil" | ||||
| "strings" | |||||
| ) | ) | ||||
| const ( | const ( | ||||
| @@ -28,6 +32,8 @@ var ( | |||||
| poolInfos *models.PoolInfos | poolInfos *models.PoolInfos | ||||
| FlavorInfos *models.FlavorInfos | FlavorInfos *models.FlavorInfos | ||||
| ImageInfos *models.ImageInfosModelArts | ImageInfos *models.ImageInfosModelArts | ||||
| SpecialPools *models.SpecialPools | |||||
| ) | ) | ||||
| type GenerateTrainJobReq struct { | type GenerateTrainJobReq struct { | ||||
| @@ -63,6 +69,27 @@ type GenerateTrainJobReq struct { | |||||
| func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error) { | func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error) { | ||||
| createTime := timeutil.TimeStampNow() | createTime := timeutil.TimeStampNow() | ||||
| var CenterID []string | |||||
| var CenterName []string | |||||
| if SpecialPools != nil { | |||||
| for _, pool := range SpecialPools.Pools { | |||||
| if !pool.IsExclusive && strings.Contains(req.ComputeResource, pool.Type) { | |||||
| org, _ := models.GetOrgByName(pool.Org) | |||||
| if org != nil { | |||||
| isOrgMember, _ := models.IsOrganizationMember(org.ID, ctx.User.ID) | |||||
| if isOrgMember { | |||||
| for _, info := range pool.Pool { | |||||
| CenterID = append(CenterID, info.Queue) | |||||
| CenterName = append(CenterName, info.Value) | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| jobResult, err := createJob(models.CreateGrampusJobRequest{ | jobResult, err := createJob(models.CreateGrampusJobRequest{ | ||||
| Name: req.JobName, | Name: req.JobName, | ||||
| Tasks: []models.GrampusTasks{ | Tasks: []models.GrampusTasks{ | ||||
| @@ -72,6 +99,8 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error | |||||
| ResourceSpecId: req.ResourceSpecId, | ResourceSpecId: req.ResourceSpecId, | ||||
| ImageId: req.ImageId, | ImageId: req.ImageId, | ||||
| ImageUrl: req.ImageUrl, | ImageUrl: req.ImageUrl, | ||||
| CenterID: CenterID, | |||||
| CenterName: CenterName, | |||||
| ReplicaNum: 1, | ReplicaNum: 1, | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -136,3 +165,8 @@ func TransTrainJobStatus(status string) string { | |||||
| return strings.ToUpper(status) | return strings.ToUpper(status) | ||||
| } | } | ||||
| func InitSpecialPool() { | |||||
| if SpecialPools == nil && setting.Grampus.SpecialPools != "" { | |||||
| json.Unmarshal([]byte(setting.Grampus.SpecialPools), &SpecialPools) | |||||
| } | |||||
| } | |||||
| @@ -531,10 +531,11 @@ var ( | |||||
| //grampus config | //grampus config | ||||
| Grampus = struct { | Grampus = struct { | ||||
| Env string | |||||
| Host string | |||||
| UserName string | |||||
| Password string | |||||
| Env string | |||||
| Host string | |||||
| UserName string | |||||
| Password string | |||||
| SpecialPools string | |||||
| }{} | }{} | ||||
| //elk config | //elk config | ||||
| @@ -1414,6 +1415,8 @@ func GetGrampusConfig() { | |||||
| Grampus.Host = sec.Key("SERVER_HOST").MustString("") | Grampus.Host = sec.Key("SERVER_HOST").MustString("") | ||||
| Grampus.UserName = sec.Key("USERNAME").MustString("") | Grampus.UserName = sec.Key("USERNAME").MustString("") | ||||
| Grampus.Password = sec.Key("PASSWORD").MustString("") | Grampus.Password = sec.Key("PASSWORD").MustString("") | ||||
| Grampus.SpecialPools = sec.Key("SPECIAL_POOL").MustString("") | |||||
| } | } | ||||
| func SetRadarMapConfig() { | func SetRadarMapConfig() { | ||||
| @@ -6,6 +6,7 @@ package setting | |||||
| import ( | import ( | ||||
| "net/url" | "net/url" | ||||
| "strings" | |||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| ) | ) | ||||
| @@ -13,14 +14,18 @@ import ( | |||||
| var ( | var ( | ||||
| // Webhook settings | // Webhook settings | ||||
| Webhook = struct { | Webhook = struct { | ||||
| QueueLength int | |||||
| DeliverTimeout int | |||||
| SkipTLSVerify bool | |||||
| Types []string | |||||
| PagingNum int | |||||
| ProxyURL string | |||||
| ProxyURLFixed *url.URL | |||||
| ProxyHosts []string | |||||
| QueueLength int | |||||
| DeliverTimeout int | |||||
| SkipTLSVerify bool | |||||
| Types []string | |||||
| PagingNum int | |||||
| ProxyURL string | |||||
| ProxyURLFixed *url.URL | |||||
| ProxyHosts []string | |||||
| Socks5Proxy string | |||||
| Socks5UserName string | |||||
| Socks5Password string | |||||
| Socks5ProxyHosts []string | |||||
| }{ | }{ | ||||
| QueueLength: 1000, | QueueLength: 1000, | ||||
| DeliverTimeout: 5, | DeliverTimeout: 5, | ||||
| @@ -39,6 +44,10 @@ func newWebhookService() { | |||||
| Webhook.Types = []string{"gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "feishu", "matrix"} | Webhook.Types = []string{"gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "feishu", "matrix"} | ||||
| Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10) | Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10) | ||||
| Webhook.ProxyURL = sec.Key("PROXY_URL").MustString("") | Webhook.ProxyURL = sec.Key("PROXY_URL").MustString("") | ||||
| Webhook.Socks5Proxy = sec.Key("SOCKS5_PROXY_URL").MustString("") | |||||
| Webhook.Socks5UserName = sec.Key("SOCKS5_USER_NAME").MustString("") | |||||
| Webhook.Socks5Password = sec.Key("SOCKS5_PASSWORD").MustString("") | |||||
| Webhook.Socks5ProxyHosts = strings.Split(sec.Key("SOCKS5_PROXY_HOST").MustString(""), ";") | |||||
| if Webhook.ProxyURL != "" { | if Webhook.ProxyURL != "" { | ||||
| var err error | var err error | ||||
| Webhook.ProxyURLFixed, err = url.Parse(Webhook.ProxyURL) | Webhook.ProxyURLFixed, err = url.Parse(Webhook.ProxyURL) | ||||
| @@ -16,6 +16,8 @@ import ( | |||||
| "sync" | "sync" | ||||
| "time" | "time" | ||||
| "golang.org/x/net/proxy" | |||||
| "code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
| "code.gitea.io/gitea/modules/graceful" | "code.gitea.io/gitea/modules/graceful" | ||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| @@ -137,8 +139,10 @@ func Deliver(t *models.HookTask) error { | |||||
| return | return | ||||
| } | } | ||||
| }() | }() | ||||
| match := isSocks5ProxyUrlMatch(req) | |||||
| resp, err := makeReq(req, match) | |||||
| resp, err := webhookHTTPClient.Do(req) | |||||
| if err != nil { | if err != nil { | ||||
| t.ResponseInfo.Body = fmt.Sprintf("Delivery: %v", err) | t.ResponseInfo.Body = fmt.Sprintf("Delivery: %v", err) | ||||
| return err | return err | ||||
| @@ -161,6 +165,23 @@ func Deliver(t *models.HookTask) error { | |||||
| return nil | return nil | ||||
| } | } | ||||
| func makeReq(req *http.Request, proxyMatch bool) (*http.Response, error) { | |||||
| if proxyMatch { | |||||
| return webhookSocks5PoxyHTTPClient.Do(req) | |||||
| } | |||||
| return webhookHTTPClient.Do(req) | |||||
| } | |||||
| func isSocks5ProxyUrlMatch(req *http.Request) bool { | |||||
| for _, v := range socks5HostMatchers { | |||||
| if v.Match(req.URL.Host) { | |||||
| return true | |||||
| } | |||||
| } | |||||
| return false | |||||
| } | |||||
| // DeliverHooks checks and delivers undelivered hooks. | // DeliverHooks checks and delivers undelivered hooks. | ||||
| // FIXME: graceful: This would likely benefit from either a worker pool with dummy queue | // FIXME: graceful: This would likely benefit from either a worker pool with dummy queue | ||||
| // or a full queue. Then more hooks could be sent at same time. | // or a full queue. Then more hooks could be sent at same time. | ||||
| @@ -225,9 +246,11 @@ func DeliverHooks(ctx context.Context) { | |||||
| } | } | ||||
| var ( | var ( | ||||
| webhookHTTPClient *http.Client | |||||
| once sync.Once | |||||
| hostMatchers []glob.Glob | |||||
| webhookHTTPClient *http.Client | |||||
| once sync.Once | |||||
| hostMatchers []glob.Glob | |||||
| webhookSocks5PoxyHTTPClient *http.Client | |||||
| socks5HostMatchers []glob.Glob | |||||
| ) | ) | ||||
| func webhookProxy() func(req *http.Request) (*url.URL, error) { | func webhookProxy() func(req *http.Request) (*url.URL, error) { | ||||
| @@ -274,5 +297,31 @@ func InitDeliverHooks() { | |||||
| }, | }, | ||||
| } | } | ||||
| if setting.Webhook.Socks5Proxy != "" { | |||||
| auth := proxy.Auth{ | |||||
| User: setting.Webhook.Socks5UserName, | |||||
| Password: setting.Webhook.Socks5Password, | |||||
| } | |||||
| dialSocksProxy, err := proxy.SOCKS5("tcp", setting.Webhook.Socks5Proxy, &auth, proxy.Direct) | |||||
| if err != nil { | |||||
| fmt.Println("Error connecting to proxy:", err) | |||||
| } | |||||
| tr := &http.Transport{Dial: dialSocksProxy.Dial} | |||||
| webhookSocks5PoxyHTTPClient = &http.Client{ | |||||
| Transport: tr, | |||||
| } | |||||
| for _, h := range setting.Webhook.Socks5ProxyHosts { | |||||
| if g, err := glob.Compile(h); err == nil { | |||||
| socks5HostMatchers = append(socks5HostMatchers, g) | |||||
| } else { | |||||
| log.Error("glob.Compile %s failed: %v", h, err) | |||||
| } | |||||
| } | |||||
| } | |||||
| go graceful.GetManager().RunWithShutdownContext(DeliverHooks) | go graceful.GetManager().RunWithShutdownContext(DeliverHooks) | ||||
| } | } | ||||
| @@ -1178,6 +1178,7 @@ model.manage.model_accuracy = Model Accuracy | |||||
| grampus.train_job.ai_center = AI Center | grampus.train_job.ai_center = AI Center | ||||
| grampus.dataset_path_rule = The code is storaged in /cache/code;the dataset is storaged in /cache/dataset;and please put your model into /cache/output, then you can download it online。 | grampus.dataset_path_rule = The code is storaged in /cache/code;the dataset is storaged in /cache/dataset;and please put your model into /cache/output, then you can download it online。 | ||||
| grampus.no_operate_right = You have no right to do this operation. | |||||
| template.items = Template Items | template.items = Template Items | ||||
| template.git_content = Git Content (Default Branch) | template.git_content = Git Content (Default Branch) | ||||
| @@ -1193,6 +1193,8 @@ model.manage.model_accuracy = 模型精度 | |||||
| grampus.train_job.ai_center=智算中心 | grampus.train_job.ai_center=智算中心 | ||||
| grampus.dataset_path_rule = 训练脚本存储在/cache/code中,数据集存储在/cache/dataset中,训练输出请存储在/cache/output中以供后续下载。 | grampus.dataset_path_rule = 训练脚本存储在/cache/code中,数据集存储在/cache/dataset中,训练输出请存储在/cache/output中以供后续下载。 | ||||
| grampus.no_operate_right = 您没有权限创建这类任务。 | |||||
| template.items=模板选项 | template.items=模板选项 | ||||
| template.git_content=Git数据(默认分支) | template.git_content=Git数据(默认分支) | ||||
| template.git_hooks=Git 钩子 | template.git_hooks=Git 钩子 | ||||
| @@ -71,6 +71,25 @@ func grampusTrainJobNewDataPrepare(ctx *context.Context, processType string) err | |||||
| ctx.Data["images"] = images.Infos | ctx.Data["images"] = images.Infos | ||||
| } | } | ||||
| grampus.InitSpecialPool() | |||||
| ctx.Data["GPUEnabled"] = true | |||||
| ctx.Data["NPUEnabled"] = true | |||||
| if grampus.SpecialPools != nil { | |||||
| for _, pool := range grampus.SpecialPools.Pools { | |||||
| if pool.IsExclusive { | |||||
| org, _ := models.GetOrgByName(pool.Org) | |||||
| if org != nil { | |||||
| isOrgMember, _ := models.IsOrganizationMember(org.ID, ctx.User.ID) | |||||
| if !isOrgMember { | |||||
| ctx.Data[pool.Type+"Enabled"] = false | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| //get valid resource specs | //get valid resource specs | ||||
| specs, err := grampus.GetResourceSpecs(processType) | specs, err := grampus.GetResourceSpecs(processType) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -128,10 +147,18 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||||
| image := strings.TrimSpace(form.Image) | image := strings.TrimSpace(form.Image) | ||||
| if !jobNamePattern.MatchString(displayJobName) { | if !jobNamePattern.MatchString(displayJobName) { | ||||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplGrampusTrainJobGPUNew, &form) | ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplGrampusTrainJobGPUNew, &form) | ||||
| return | return | ||||
| } | } | ||||
| errStr := checkSpecialPool(ctx, "GPU") | |||||
| if errStr != "" { | |||||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU) | |||||
| ctx.RenderWithErr(errStr, tplGrampusTrainJobGPUNew, &form) | |||||
| return | |||||
| } | |||||
| //check count limit | //check count limit | ||||
| count, err := models.GetGrampusCountByUserID(ctx.User.ID, string(models.JobTypeTrain), models.GPUResource) | count, err := models.GetGrampusCountByUserID(ctx.User.ID, string(models.JobTypeTrain), models.GPUResource) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -263,6 +290,28 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") | ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") | ||||
| } | } | ||||
| func checkSpecialPool(ctx *context.Context, resourceType string) string { | |||||
| grampus.InitSpecialPool() | |||||
| if grampus.SpecialPools != nil { | |||||
| for _, pool := range grampus.SpecialPools.Pools { | |||||
| if pool.IsExclusive && pool.Type == resourceType { | |||||
| org, _ := models.GetOrgByName(pool.Org) | |||||
| if org != nil { | |||||
| isOrgMember, _ := models.IsOrganizationMember(org.ID, ctx.User.ID) | |||||
| if !isOrgMember { | |||||
| return ctx.Tr("repo.grampus.no_operate_right") | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| return "" | |||||
| } | |||||
| func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrainJobForm) { | func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrainJobForm) { | ||||
| displayJobName := form.DisplayJobName | displayJobName := form.DisplayJobName | ||||
| jobName := util.ConvertDisplayJobNameToJobName(displayJobName) | jobName := util.ConvertDisplayJobNameToJobName(displayJobName) | ||||
| @@ -281,10 +330,18 @@ func GrampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain | |||||
| engineName := form.EngineName | engineName := form.EngineName | ||||
| if !jobNamePattern.MatchString(displayJobName) { | if !jobNamePattern.MatchString(displayJobName) { | ||||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||||
| ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplGrampusTrainJobNPUNew, &form) | ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplGrampusTrainJobNPUNew, &form) | ||||
| return | return | ||||
| } | } | ||||
| errStr := checkSpecialPool(ctx, "NPU") | |||||
| if errStr != "" { | |||||
| grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU) | |||||
| ctx.RenderWithErr(errStr, tplGrampusTrainJobGPUNew, &form) | |||||
| return | |||||
| } | |||||
| //check count limit | //check count limit | ||||
| count, err := models.GetGrampusCountByUserID(ctx.User.ID, string(models.JobTypeTrain), models.NPUResource) | count, err := models.GetGrampusCountByUserID(ctx.User.ID, string(models.JobTypeTrain), models.NPUResource) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -89,23 +89,23 @@ | |||||
| <svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg> | <svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg> | ||||
| {{.i18n.Tr "cloudbrain.resource_cluster_openi"}} | {{.i18n.Tr "cloudbrain.resource_cluster_openi"}} | ||||
| </a> | </a> | ||||
| <a class="active item" href="{{.RepoLink}}/grampus/train-job/npu/create"> | |||||
| <svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg> | |||||
| {{.i18n.Tr "cloudbrain.resource_cluster_c2net"}} | |||||
| </a> | |||||
| <a class="active item" href="{{.RepoLink}}/grampus/train-job/ {{if.NPUEnabled}}npu{{else}}gpu{{end}}/create"> | |||||
| <svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg> | |||||
| {{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}(Beta) | |||||
| </a> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="required unite min_title inline field"> | <div class="required unite min_title inline field"> | ||||
| <label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label> | <label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label> | ||||
| <div class="ui blue mini menu compact selectcloudbrain"> | <div class="ui blue mini menu compact selectcloudbrain"> | ||||
| <a class="active item" href="{{.RepoLink}}/grampus/train-job/gpu/create"> | |||||
| <a {{if.GPUEnabled}}class="active item" href="{{.RepoLink}}/grampus/train-job/gpu/create"{{else}}href="javascript:return false;" class="item disabled" {{end}}> | |||||
| <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | ||||
| <path fill="none" d="M0 0h24v24H0z"/> | <path fill="none" d="M0 0h24v24H0z"/> | ||||
| <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | ||||
| </svg> | </svg> | ||||
| CPU/GPU | CPU/GPU | ||||
| </a> | </a> | ||||
| <a class="item" href="{{.RepoLink}}/grampus/train-job/npu/create"> | |||||
| <a {{if.NPUEnabled}}class="item" href="{{.RepoLink}}/grampus/train-job/npu/create"{{else}}href="javascript:return false;" class="item disabled" {{end}} > | |||||
| <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | ||||
| <path fill="none" d="M0 0h24v24H0z"/> | <path fill="none" d="M0 0h24v24H0z"/> | ||||
| <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | ||||
| @@ -85,23 +85,23 @@ | |||||
| <svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg> | <svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg> | ||||
| {{.i18n.Tr "cloudbrain.resource_cluster_openi"}} | {{.i18n.Tr "cloudbrain.resource_cluster_openi"}} | ||||
| </a> | </a> | ||||
| <a class="active item" href="{{.RepoLink}}/grampus/train-job/npu/create"> | |||||
| <svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg> | |||||
| {{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}(Beta) | |||||
| <a class="active item" href="{{.RepoLink}}/grampus/train-job/ {{if.NPUEnabled}}npu{{else}}gpu{{end}}/create"> | |||||
| <svg class="svg" sxmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-2.29-2.333A17.9 17.9 0 0 1 8.027 13H4.062a8.008 8.008 0 0 0 5.648 6.667zM10.03 13c.151 2.439.848 4.73 1.97 6.752A15.905 15.905 0 0 0 13.97 13h-3.94zm9.908 0h-3.965a17.9 17.9 0 0 1-1.683 6.667A8.008 8.008 0 0 0 19.938 13zM4.062 11h3.965A17.9 17.9 0 0 1 9.71 4.333 8.008 8.008 0 0 0 4.062 11zm5.969 0h3.938A15.905 15.905 0 0 0 12 4.248 15.905 15.905 0 0 0 10.03 11zm4.259-6.667A17.9 17.9 0 0 1 15.973 11h3.965a8.008 8.008 0 0 0-5.648-6.667z"></path></svg> | |||||
| {{.i18n.Tr "cloudbrain.resource_cluster_c2net"}}(Beta) | |||||
| </a> | </a> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="required unite min_title inline field"> | <div class="required unite min_title inline field"> | ||||
| <label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label> | <label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.compute_resource"}}</label> | ||||
| <div class="ui blue mini menu compact selectcloudbrain"> | <div class="ui blue mini menu compact selectcloudbrain"> | ||||
| <!--a class="item" href="{{.RepoLink}}/grampus/train-job/gpu/create" type="hidden"> | |||||
| <a {{if.GPUEnabled}}class="item" href="{{.RepoLink}}/grampus/train-job/gpu/create"{{else}}href="javascript:return false;" class="item disabled" {{end}}> | |||||
| <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | ||||
| <path fill="none" d="M0 0h24v24H0z"/> | <path fill="none" d="M0 0h24v24H0z"/> | ||||
| <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | ||||
| </svg> | </svg> | ||||
| CPU/GPU | CPU/GPU | ||||
| </a--> | |||||
| <a class="active item" href="{{.RepoLink}}/grampus/train-job/npu/create"> | |||||
| </a> | |||||
| <a {{if.NPUEnabled}}class="active item" href="{{.RepoLink}}/grampus/train-job/npu/create"{{else}}href="javascript:return false;" class="item disabled" {{end}} > | |||||
| <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | <svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | ||||
| <path fill="none" d="M0 0h24v24H0z"/> | <path fill="none" d="M0 0h24v24H0z"/> | ||||
| <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | <path d="M3 2.992C3 2.444 3.445 2 3.993 2h16.014a1 1 0 0 1 .993.992v18.016a.993.993 0 0 1-.993.992H3.993A1 1 0 0 1 3 21.008V2.992zM19 11V4H5v7h14zm0 2H5v7h14v-7zM9 6h6v2H9V6zm0 9h6v2H9v-2z"/> | ||||