You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

modelarts.go 17 kB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. package repo
  2. import (
  3. "code.gitea.io/gitea/modules/git"
  4. "code.gitea.io/gitea/modules/modelarts"
  5. "code.gitea.io/gitea/modules/obs"
  6. "code.gitea.io/gitea/modules/storage"
  7. "encoding/json"
  8. "errors"
  9. "github.com/unknwon/com"
  10. "io"
  11. "net/http"
  12. "os"
  13. "path"
  14. "strconv"
  15. "strings"
  16. "time"
  17. "code.gitea.io/gitea/models"
  18. "code.gitea.io/gitea/modules/auth"
  19. "code.gitea.io/gitea/modules/base"
  20. "code.gitea.io/gitea/modules/context"
  21. "code.gitea.io/gitea/modules/log"
  22. "code.gitea.io/gitea/modules/setting"
  23. )
  24. const (
  25. tplModelArtsNotebookIndex base.TplName = "repo/modelarts/notebook/index"
  26. tplModelArtsNotebookNew base.TplName = "repo/modelarts/notebook/new"
  27. tplModelArtsNotebookShow base.TplName = "repo/modelarts/notebook/show"
  28. tplModelArtsTrainJobIndex base.TplName = "repo/modelarts/trainjob/index"
  29. tplModelArtsTrainJobNew base.TplName = "repo/modelarts/trainjob/new"
  30. tplModelArtsTrainJobShow base.TplName = "repo/modelarts/trainjob/show"
  31. )
  32. // MustEnableDataset check if repository enable internal cb
  33. func MustEnableModelArts(ctx *context.Context) {
  34. if !ctx.Repo.CanRead(models.UnitTypeCloudBrain) {
  35. ctx.NotFound("MustEnableCloudbrain", nil)
  36. return
  37. }
  38. }
  39. func NotebookIndex(ctx *context.Context) {
  40. MustEnableModelArts(ctx)
  41. repo := ctx.Repo.Repository
  42. page := ctx.QueryInt("page")
  43. if page <= 0 {
  44. page = 1
  45. }
  46. ciTasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{
  47. ListOptions: models.ListOptions{
  48. Page: page,
  49. PageSize: setting.UI.IssuePagingNum,
  50. },
  51. RepoID: repo.ID,
  52. Type: models.TypeCloudBrainNotebook,
  53. })
  54. if err != nil {
  55. ctx.ServerError("Cloudbrain", err)
  56. return
  57. }
  58. for i, task := range ciTasks {
  59. if task.Status == string(models.JobRunning) {
  60. ciTasks[i].CanDebug = true
  61. } else {
  62. ciTasks[i].CanDebug = false
  63. }
  64. }
  65. pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5)
  66. pager.SetDefaultParams(ctx)
  67. ctx.Data["Page"] = pager
  68. ctx.Data["PageIsCloudBrain"] = true
  69. ctx.Data["Tasks"] = ciTasks
  70. ctx.HTML(200, tplModelArtsNotebookIndex)
  71. }
  72. func NotebookNew(ctx *context.Context) {
  73. ctx.Data["PageIsCloudBrain"] = true
  74. t := time.Now()
  75. var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
  76. ctx.Data["job_name"] = jobName
  77. attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID)
  78. if err != nil {
  79. ctx.ServerError("GetAllUserAttachments failed:", err)
  80. return
  81. }
  82. ctx.Data["attachments"] = attachs
  83. ctx.Data["dataset_path"] = modelarts.DataSetMountPath
  84. ctx.Data["env"] = modelarts.NotebookEnv
  85. ctx.Data["notebook_type"] = modelarts.NotebookType
  86. ctx.Data["flavor"] = modelarts.FlavorInfo
  87. ctx.HTML(200, tplModelArtsNotebookNew)
  88. }
  89. func NotebookCreate(ctx *context.Context, form auth.CreateModelArtsNotebookForm) {
  90. ctx.Data["PageIsCloudBrain"] = true
  91. jobName := form.JobName
  92. uuid := form.Attachment
  93. description := form.Description
  94. err := modelarts.GenerateTask(ctx, jobName, uuid, description)
  95. if err != nil {
  96. ctx.RenderWithErr(err.Error(), tplModelArtsNotebookNew, &form)
  97. return
  98. }
  99. ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/notebook")
  100. }
  101. func NotebookShow(ctx *context.Context) {
  102. ctx.Data["PageIsCloudBrain"] = true
  103. var jobID = ctx.Params(":jobid")
  104. task, err := models.GetCloudbrainByJobID(jobID)
  105. if err != nil {
  106. ctx.Data["error"] = err.Error()
  107. ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil)
  108. return
  109. }
  110. result, err := modelarts.GetJob(jobID)
  111. if err != nil {
  112. ctx.Data["error"] = err.Error()
  113. ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil)
  114. return
  115. }
  116. if result != nil {
  117. task.Status = result.Status
  118. err = models.UpdateJob(task)
  119. if err != nil {
  120. ctx.Data["error"] = err.Error()
  121. ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil)
  122. return
  123. }
  124. createTime, _ := com.StrTo(result.CreationTimestamp).Int64()
  125. result.CreateTime = time.Unix(int64(createTime/1000), 0).Format("2006-01-02 15:04:05")
  126. endTime, _ := com.StrTo(result.LatestUpdateTimestamp).Int64()
  127. result.LatestUpdateTime = time.Unix(int64(endTime/1000), 0).Format("2006-01-02 15:04:05")
  128. result.QueuingInfo.BeginTime = time.Unix(int64(result.QueuingInfo.BeginTimestamp/1000), 0).Format("2006-01-02 15:04:05")
  129. result.QueuingInfo.EndTime = time.Unix(int64(result.QueuingInfo.EndTimestamp/1000), 0).Format("2006-01-02 15:04:05")
  130. }
  131. ctx.Data["task"] = task
  132. ctx.Data["jobID"] = jobID
  133. ctx.Data["result"] = result
  134. ctx.HTML(200, tplModelArtsNotebookShow)
  135. }
  136. func NotebookDebug(ctx *context.Context) {
  137. var jobID = ctx.Params(":jobid")
  138. _, err := models.GetCloudbrainByJobID(jobID)
  139. if err != nil {
  140. ctx.ServerError("GetCloudbrainByJobID failed", err)
  141. return
  142. }
  143. result, err := modelarts.GetJob(jobID)
  144. if err != nil {
  145. ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil)
  146. return
  147. }
  148. res, err := modelarts.GetJobToken(jobID)
  149. if err != nil {
  150. ctx.RenderWithErr(err.Error(), tplModelArtsNotebookIndex, nil)
  151. return
  152. }
  153. urls := strings.Split(result.Spec.Annotations.Url, "/")
  154. urlPrefix := result.Spec.Annotations.TargetDomain
  155. for i, url := range urls {
  156. if i > 2 {
  157. urlPrefix += "/" + url
  158. }
  159. }
  160. debugUrl := urlPrefix + "?token=" + res.Token
  161. ctx.Redirect(debugUrl)
  162. }
  163. func NotebookStop(ctx *context.Context) {
  164. var jobID = ctx.Params(":jobid")
  165. log.Info(jobID)
  166. task, err := models.GetCloudbrainByJobID(jobID)
  167. if err != nil {
  168. ctx.ServerError("GetCloudbrainByJobID failed", err)
  169. return
  170. }
  171. if task.Status != string(models.JobRunning) {
  172. log.Error("the job(%s) is not running", task.JobName)
  173. ctx.ServerError("the job is not running", errors.New("the job is not running"))
  174. return
  175. }
  176. param := models.NotebookAction{
  177. Action: models.ActionStop,
  178. }
  179. res, err := modelarts.StopJob(jobID, param)
  180. if err != nil {
  181. log.Error("StopJob(%s) failed:%v", task.JobName, err.Error())
  182. ctx.ServerError("StopJob failed", err)
  183. return
  184. }
  185. task.Status = res.CurrentStatus
  186. err = models.UpdateJob(task)
  187. if err != nil {
  188. ctx.ServerError("UpdateJob failed", err)
  189. return
  190. }
  191. ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/notebook")
  192. }
  193. func NotebookDel(ctx *context.Context) {
  194. var jobID = ctx.Params(":jobid")
  195. task, err := models.GetCloudbrainByJobID(jobID)
  196. if err != nil {
  197. ctx.ServerError("GetCloudbrainByJobID failed", err)
  198. return
  199. }
  200. if task.Status != string(models.JobStopped) {
  201. log.Error("the job(%s) has not been stopped", task.JobName)
  202. ctx.ServerError("the job has not been stopped", errors.New("the job has not been stopped"))
  203. return
  204. }
  205. _, err = modelarts.DelJob(jobID)
  206. if err != nil {
  207. log.Error("DelJob(%s) failed:%v", task.JobName, err.Error())
  208. ctx.ServerError("DelJob failed", err)
  209. return
  210. }
  211. err = models.DeleteJob(task)
  212. if err != nil {
  213. ctx.ServerError("DeleteJob failed", err)
  214. return
  215. }
  216. ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/notebook")
  217. }
  218. func TrainJobIndex(ctx *context.Context) {
  219. MustEnableModelArts(ctx)
  220. repo := ctx.Repo.Repository
  221. page := ctx.QueryInt("page")
  222. if page <= 0 {
  223. page = 1
  224. }
  225. tasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{
  226. ListOptions: models.ListOptions{
  227. Page: page,
  228. PageSize: setting.UI.IssuePagingNum,
  229. },
  230. RepoID: repo.ID,
  231. Type: models.TypeCloudBrainTrainJob,
  232. })
  233. if err != nil {
  234. ctx.ServerError("Cloudbrain", err)
  235. return
  236. }
  237. pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5)
  238. pager.SetDefaultParams(ctx)
  239. ctx.Data["Page"] = pager
  240. ctx.Data["PageIsCloudBrain"] = true
  241. ctx.Data["Tasks"] = tasks
  242. ctx.HTML(200, tplModelArtsTrainJobIndex)
  243. }
  244. func TrainJobNew(ctx *context.Context) {
  245. ctx.Data["PageIsCloudBrain"] = true
  246. t := time.Now()
  247. var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:]
  248. ctx.Data["job_name"] = jobName
  249. attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID)
  250. if err != nil {
  251. ctx.ServerError("GetAllUserAttachments failed:", err)
  252. return
  253. }
  254. ctx.Data["attachments"] = attachs
  255. var resourcePools modelarts.ResourcePool
  256. if err = json.Unmarshal([]byte(modelarts.ResourcePools), &resourcePools); err != nil {
  257. ctx.ServerError("json.Unmarshal failed:", err)
  258. return
  259. }
  260. ctx.Data["resource_pools"] = resourcePools.Info
  261. var engines modelarts.Engine
  262. if err = json.Unmarshal([]byte(modelarts.Engines), &engines); err != nil {
  263. ctx.ServerError("json.Unmarshal failed:", err)
  264. return
  265. }
  266. ctx.Data["engines"] = engines.Info
  267. var versionInfos modelarts.VersionInfo
  268. if err = json.Unmarshal([]byte(modelarts.EngineVersions), &versionInfos); err != nil {
  269. ctx.ServerError("json.Unmarshal failed:", err)
  270. return
  271. }
  272. ctx.Data["engine_versions"] = versionInfos.Version
  273. var flavorInfos modelarts.Flavor
  274. if err = json.Unmarshal([]byte(modelarts.FlavorInfos), &flavorInfos); err != nil {
  275. ctx.ServerError("json.Unmarshal failed:", err)
  276. return
  277. }
  278. ctx.Data["flavor_infos"] = flavorInfos.Info
  279. ctx.HTML(200, tplModelArtsTrainJobNew)
  280. }
  281. func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) {
  282. ctx.Data["PageIsCloudBrain"] = true
  283. jobName := form.JobName
  284. uuid := form.Attachment
  285. description := form.Description
  286. workServerNumber := form.WorkServerNumber
  287. engineID := form.EngineID
  288. bootFile := form.BootFile
  289. flavorCode := form.Flavor
  290. poolID := form.PoolID
  291. isSaveParam := form.IsSaveParam
  292. repo := ctx.Repo.Repository
  293. codeLocalPath := setting.JobPath + jobName + modelarts.CodePath
  294. codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath
  295. outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath
  296. logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath
  297. dataPath := "/" + setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + "/"
  298. //param check
  299. if err := paramCheckCreateTrainJob(form); err != nil {
  300. log.Error("paramCheckCreateTrainJob failed:(%v)", err)
  301. ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobNew, &form)
  302. return
  303. }
  304. if err := git.Clone(repo.RepoPath(), codeLocalPath, git.CloneRepoOptions{}); err != nil {
  305. log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
  306. ctx.RenderWithErr("Failed to clone repository", tplModelArtsTrainJobNew, &form)
  307. return
  308. }
  309. //todo: upload code (send to file_server todo this work?)
  310. if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.OutputPath); err != nil {
  311. log.Error("Failed to obsMkdir_output: %s (%v)", repo.FullName(), err)
  312. ctx.RenderWithErr("Failed to obsMkdir_output", tplModelArtsTrainJobNew, &form)
  313. return
  314. }
  315. if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.LogPath); err != nil {
  316. log.Error("Failed to obsMkdir_log: %s (%v)", repo.FullName(), err)
  317. ctx.RenderWithErr("Failed to obsMkdir_log", tplModelArtsTrainJobNew, &form)
  318. return
  319. }
  320. if err := uploadCodeToObs(codeLocalPath, jobName, ""); err != nil {
  321. log.Error("Failed to uploadCodeToObs: %s (%v)", repo.FullName(), err)
  322. ctx.RenderWithErr("Failed to uploadCodeToObs", tplModelArtsTrainJobNew, &form)
  323. return
  324. }
  325. //todo: del local code?
  326. if isSaveParam == "on" {
  327. if form.ParameterTemplateName == "" {
  328. log.Error("ParameterTemplateName is empty")
  329. ctx.RenderWithErr("保存作业参数时,作业参数名称不能为空", tplModelArtsTrainJobNew, &form)
  330. return
  331. }
  332. _, err := modelarts.CreateTrainJobConfig(models.CreateConfigParams{
  333. ConfigName: form.ParameterTemplateName,
  334. Description: form.PrameterDescription,
  335. DataUrl: dataPath,
  336. AppUrl: codeObsPath,
  337. BootFileUrl: codeObsPath + bootFile,
  338. TrainUrl: outputObsPath,
  339. Flavor: models.Flavor{
  340. Code: flavorCode,
  341. },
  342. WorkServerNum: workServerNumber,
  343. EngineID: int64(engineID),
  344. LogUrl: logObsPath,
  345. PoolID: poolID,
  346. Parameter: []models.Parameter{
  347. },
  348. })
  349. if err != nil {
  350. log.Error("Failed to CreateTrainJobConfig: %v", err)
  351. ctx.RenderWithErr("保存作业参数失败:" + err.Error(), tplModelArtsTrainJobNew, &form)
  352. return
  353. }
  354. }
  355. req := &modelarts.GenerateTrainJobReq{
  356. JobName: jobName,
  357. DataUrl: dataPath,
  358. Description: description,
  359. CodeObsPath: codeObsPath,
  360. BootFile: codeObsPath + bootFile,
  361. TrainUrl: outputObsPath,
  362. FlavorCode: flavorCode,
  363. WorkServerNumber: workServerNumber,
  364. EngineID: int64(engineID),
  365. LogUrl: logObsPath,
  366. PoolID: poolID,
  367. }
  368. err := modelarts.GenerateTrainJob(ctx, req)
  369. if err != nil {
  370. log.Error("GenerateTrainJob failed:%v", err.Error())
  371. ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobNew, &form)
  372. return
  373. }
  374. ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job")
  375. }
  376. // readDir reads the directory named by dirname and returns
  377. // a list of directory entries sorted by filename.
  378. func readDir(dirname string) ([]os.FileInfo, error) {
  379. f, err := os.Open(dirname)
  380. if err != nil {
  381. return nil, err
  382. }
  383. list, err := f.Readdir(100)
  384. f.Close()
  385. if err != nil {
  386. //todo: can not upload empty folder
  387. if err == io.EOF {
  388. return nil, nil
  389. }
  390. return nil, err
  391. }
  392. //sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() })
  393. return list, nil
  394. }
  395. func uploadCodeToObs(codePath, jobName, parentDir string) error {
  396. files, err := readDir(codePath)
  397. if err != nil {
  398. log.Error("readDir(%s) failed: %s", codePath, err.Error())
  399. return err
  400. }
  401. for _, file := range files {
  402. if file.IsDir() {
  403. input := &obs.PutObjectInput{}
  404. input.Bucket = setting.Bucket
  405. input.Key = parentDir + file.Name() + "/"
  406. _, err = storage.ObsCli.PutObject(input)
  407. if err != nil {
  408. log.Error("PutObject(%s) failed: %s", input.Key, err.Error())
  409. return err
  410. }
  411. if err = uploadCodeToObs(codePath + file.Name() + "/", jobName, parentDir + file.Name() + "/"); err != nil {
  412. log.Error("uploadCodeToObs(%s) failed: %s", file.Name(), err.Error())
  413. return err
  414. }
  415. } else {
  416. input := &obs.PutFileInput{}
  417. input.Bucket = setting.Bucket
  418. input.Key = setting.CodePathPrefix + jobName + "/code/" + parentDir + file.Name()
  419. input.SourceFile = codePath + file.Name()
  420. _, err = storage.ObsCli.PutFile(input)
  421. if err != nil {
  422. log.Error("PutFile(%s) failed: %s", input.SourceFile, err.Error())
  423. return err
  424. }
  425. }
  426. }
  427. return nil
  428. }
  429. func obsMkdir(dir string) error {
  430. input := &obs.PutObjectInput{}
  431. input.Bucket = setting.Bucket
  432. input.Key = dir
  433. _, err := storage.ObsCli.PutObject(input)
  434. if err != nil {
  435. log.Error("PutObject(%s) failed: %s", input.Key, err.Error())
  436. return err
  437. }
  438. return nil
  439. }
  440. func paramCheckCreateTrainJob(form auth.CreateModelArtsTrainJobForm) error {
  441. if !strings.HasSuffix(form.BootFile, ".py") {
  442. log.Error("the boot file(%s) must be a python file", form.BootFile)
  443. return errors.New("启动文件必须是python文件")
  444. }
  445. if form.WorkServerNumber > 25 || form.WorkServerNumber < 1{
  446. log.Error("the WorkServerNumber(%d) must be in (1,25)", form.WorkServerNumber)
  447. return errors.New("计算节点数必须在1-25之间")
  448. }
  449. return nil
  450. }
  451. func TrainJobShow(ctx *context.Context) {
  452. ctx.Data["PageIsCloudBrain"] = true
  453. var jobID = ctx.Params(":jobid")
  454. task, err := models.GetCloudbrainByJobID(jobID)
  455. if err != nil {
  456. log.Error("GetCloudbrainByJobID(%s) failed:%v", jobID, err.Error())
  457. ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobIndex, nil)
  458. return
  459. }
  460. result, err := modelarts.GetTrainJob(jobID, strconv.FormatInt(task.VersionID, 10))
  461. if err != nil {
  462. log.Error("GetJob(%s) failed:%v", jobID, err.Error())
  463. ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobIndex, nil)
  464. return
  465. }
  466. if result != nil {
  467. createTime, _ := com.StrTo(result.LongCreateTime).Int64()
  468. result.CreateTime = time.Unix(int64(createTime/1000), 0).Format("2006-01-02 15:04:05")
  469. }
  470. ctx.Data["task"] = task
  471. ctx.Data["jobID"] = jobID
  472. ctx.Data["result"] = result
  473. ctx.HTML(http.StatusOK, tplModelArtsTrainJobShow)
  474. }
  475. func TrainJobGetLog(ctx *context.Context) {
  476. ctx.Data["PageIsCloudBrain"] = true
  477. var jobID = ctx.Params(":jobid")
  478. task, err := models.GetCloudbrainByJobID(jobID)
  479. if err != nil {
  480. log.Error("GetCloudbrainByJobID(%s) failed:%v", jobID, err.Error())
  481. ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobShow, nil)
  482. return
  483. }
  484. resultLogFile, err := modelarts.GetTrainJobLogFileNames(jobID, strconv.FormatInt(task.VersionID, 10))
  485. if err != nil {
  486. log.Error("GetTrainJobLogFileNames(%s) failed:%v", jobID, err.Error())
  487. ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobShow, nil)
  488. return
  489. }
  490. result, err := modelarts.GetTrainJobLog(jobID, strconv.FormatInt(task.VersionID, 10), "", resultLogFile.LogFileList[0], modelarts.OrderDesc, 20)
  491. if err != nil {
  492. log.Error("GetTrainJobLog(%s) failed:%v", jobID, err.Error())
  493. ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobShow, nil)
  494. return
  495. }
  496. ctx.Data["log"] = result
  497. ctx.HTML(http.StatusOK, tplModelArtsTrainJobShow)
  498. }