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.

notebook.go 19 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. package cloudbrainTask
  2. import (
  3. "fmt"
  4. "net/http"
  5. "path"
  6. "strings"
  7. "code.gitea.io/gitea/modules/notebook"
  8. "code.gitea.io/gitea/modules/modelarts"
  9. "code.gitea.io/gitea/modules/modelarts_cd"
  10. "code.gitea.io/gitea/modules/git"
  11. "code.gitea.io/gitea/modules/cloudbrain"
  12. "code.gitea.io/gitea/modules/log"
  13. "code.gitea.io/gitea/modules/redis/redis_key"
  14. "code.gitea.io/gitea/modules/redis/redis_lock"
  15. "code.gitea.io/gitea/modules/storage"
  16. "code.gitea.io/gitea/services/cloudbrain/resource"
  17. "code.gitea.io/gitea/services/reward/point/account"
  18. "code.gitea.io/gitea/modules/setting"
  19. cloudbrainService "code.gitea.io/gitea/services/cloudbrain"
  20. repo_service "code.gitea.io/gitea/services/repository"
  21. "code.gitea.io/gitea/models"
  22. "code.gitea.io/gitea/modules/context"
  23. api "code.gitea.io/gitea/modules/structs"
  24. "code.gitea.io/gitea/modules/util"
  25. )
  26. const NoteBookExtension = ".ipynb"
  27. const CPUType = 0
  28. const GPUType = 1
  29. const NPUType = 2
  30. func FileNotebookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption) {
  31. if ctx.Written() {
  32. return
  33. }
  34. if path.Ext(option.File) != NoteBookExtension {
  35. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_select_wrong")))
  36. return
  37. }
  38. isNotebookFileExist, _ := isNoteBookFileExist(ctx, option)
  39. if !isNotebookFileExist {
  40. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist")))
  41. return
  42. }
  43. sourceRepo, err := models.GetRepositoryByOwnerAndName(option.OwnerName, option.ProjectName)
  44. if err != nil {
  45. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist")))
  46. return
  47. }
  48. permission, err := models.GetUserRepoPermission(sourceRepo, ctx.User)
  49. if err != nil {
  50. log.Error("Get permission failed", err)
  51. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_no_right")))
  52. return
  53. }
  54. if !permission.CanRead(models.UnitTypeCode) {
  55. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_no_right")))
  56. return
  57. }
  58. //create repo if not exist
  59. repo, _ := models.GetRepositoryByName(ctx.User.ID, setting.FileNoteBook.ProjectName)
  60. if repo == nil {
  61. repo, err = repo_service.CreateRepository(ctx.User, ctx.User, models.CreateRepoOptions{
  62. Name: setting.FileNoteBook.ProjectName,
  63. Alias: "",
  64. Description: "",
  65. IssueLabels: "",
  66. Gitignores: "",
  67. License: "",
  68. Readme: "Default",
  69. IsPrivate: false,
  70. AutoInit: true,
  71. DefaultBranch: "master",
  72. })
  73. if err != nil {
  74. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.failed_to_create_notebook_repo", setting.FileNoteBook.ProjectName)))
  75. return
  76. }
  77. } else {
  78. noteBook, _ := models.GetWaitOrRunFileNotebookByRepo(repo.ID, getCloudbrainType(option.Type))
  79. if noteBook != nil {
  80. if isRepoConfilcts(option, noteBook) {
  81. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_repo_conflict")))
  82. return
  83. }
  84. if isNotebookSpecMath(option, noteBook) {
  85. if !isRepoMatch(option, noteBook) {
  86. err = downloadCode(sourceRepo, getCodePath(noteBook.JobName, sourceRepo), option.BranchName)
  87. if err != nil {
  88. log.Error("download code failed", err)
  89. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.load_code_failed")))
  90. return
  91. }
  92. }
  93. if !isRepoFileMatch(option, noteBook) {
  94. noteBook.BootFile += ";" + getBootFile(option.File, option.OwnerName, option.ProjectName)
  95. noteBook.BranchName += ";" + option.BranchName
  96. noteBook.Description += ";" + getDescription(option)
  97. err := models.UpdateJob(noteBook)
  98. if err != nil {
  99. log.Error("GenerateNotebook2 failed, %v", err, ctx.Data["MsgID"])
  100. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(err.Error()))
  101. return
  102. }
  103. }
  104. ctx.JSON(http.StatusOK, models.BaseMessageApi{
  105. Code: 0,
  106. Message: noteBook.JobID,
  107. })
  108. return
  109. }
  110. }
  111. }
  112. if option.Type <= GPUType {
  113. cloudBrainFileNoteBookCreate(ctx, option, repo, sourceRepo)
  114. } else {
  115. modelartsFileNoteBookCreate(ctx, option, repo, sourceRepo)
  116. }
  117. }
  118. func FileNotebookStatus(ctx *context.Context, option api.CreateFileNotebookJobOption) {
  119. if ctx.Written() {
  120. return
  121. }
  122. if path.Ext(option.File) != NoteBookExtension {
  123. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_select_wrong")))
  124. return
  125. }
  126. isNotebookFileExist, _ := isNoteBookFileExist(ctx, option)
  127. if !isNotebookFileExist {
  128. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_file_not_exist")))
  129. return
  130. }
  131. task, err := models.GetCloudbrainByJobID(option.JobId)
  132. if err != nil {
  133. log.Error("job not found:"+option.JobId, err)
  134. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("Job id may not be right. can not find job."))
  135. return
  136. }
  137. if task.BootFile == "" || task.Status != string(models.ModelArtsRunning) {
  138. log.Warn("Boot file is empty or status is running. ")
  139. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("Boot file is empty or status is running."))
  140. return
  141. }
  142. if !isRepoFileMatch(option, task) {
  143. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("can not math repo file."))
  144. return
  145. }
  146. debugBaseUrl, token, err := getBaseUrlAndToken(task)
  147. if err != nil {
  148. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(err.Error()))
  149. return
  150. }
  151. if uploadNotebookFileIfCannotBroswer(debugBaseUrl, getBootFile(option.File, option.OwnerName, option.ProjectName), task, token) {
  152. ctx.JSON(http.StatusOK, models.BaseOKMessageApi)
  153. } else {
  154. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("upload failed."))
  155. }
  156. }
  157. func getBaseUrlAndToken(task *models.Cloudbrain) (string, string, error) {
  158. var debugBaseUrl string
  159. var token string
  160. if task.Type == models.TypeCloudBrainOne {
  161. debugBaseUrl = setting.DebugServerHost + "jpylab_" + task.JobID + "_" + task.SubTaskName + "/lab"
  162. } else {
  163. var result *models.GetNotebook2Result
  164. var err error
  165. if task.Type == models.TypeCloudBrainTwo {
  166. result, err = modelarts.GetNotebook2(task.JobID)
  167. } else if task.Type == models.TypeCDCenter {
  168. result, err = modelarts_cd.GetNotebook(task.JobID)
  169. }
  170. if err != nil || result == nil || result.Status != string(models.ModelArtsRunning) || result.Url == "" {
  171. log.Error("notebook job not found:"+task.JobID, err)
  172. return "", "", fmt.Errorf("can not get job or job is invalid.")
  173. }
  174. debugBaseUrl = result.Url
  175. token = result.Token
  176. }
  177. return debugBaseUrl, token, nil
  178. }
  179. func uploadNotebookFileIfCannotBroswer(debugBaseUrl string, bootFile string, task *models.Cloudbrain, token string) bool {
  180. c := &notebook.NotebookContent{
  181. Url: debugBaseUrl,
  182. Path: bootFile,
  183. PathType: "file",
  184. Token: token,
  185. }
  186. if c.IsNotebookFileCanBrowser() {
  187. return true
  188. } else {
  189. c.SetCookiesAndCsrf()
  190. c.UploadNoteBookFile(task)
  191. return c.IsNotebookFileCanBrowser()
  192. }
  193. }
  194. func isNotebookSpecMath(option api.CreateFileNotebookJobOption, book *models.Cloudbrain) bool {
  195. if option.Type == NPUType || option.Type == CPUType {
  196. return true
  197. }
  198. spec, err := models.GetCloudbrainSpecByID(book.ID)
  199. if err != nil {
  200. log.Warn("can not get spec ", err)
  201. return false
  202. }
  203. return spec.AccCardsNum > 0
  204. }
  205. func isRepoConfilcts(option api.CreateFileNotebookJobOption, book *models.Cloudbrain) bool {
  206. bootFiles := strings.Split(book.BootFile, ";")
  207. branches := strings.Split(book.BranchName, ";")
  208. for i, bootFile := range bootFiles {
  209. splits := strings.Split(bootFile, "/")
  210. if len(splits) >= 3 {
  211. if splits[0] == option.OwnerName && splits[1] == option.ProjectName && branches[i] != option.BranchName {
  212. return true
  213. }
  214. }
  215. }
  216. return false
  217. }
  218. func isRepoMatch(option api.CreateFileNotebookJobOption, book *models.Cloudbrain) bool {
  219. bootFiles := strings.Split(book.BootFile, ";")
  220. for _, bootFile := range bootFiles {
  221. splits := strings.Split(bootFile, "/")
  222. if len(splits) >= 3 {
  223. if splits[0] == option.OwnerName && splits[1] == option.ProjectName {
  224. return true
  225. }
  226. }
  227. }
  228. return false
  229. }
  230. func isRepoFileMatch(option api.CreateFileNotebookJobOption, book *models.Cloudbrain) bool {
  231. bootFiles := strings.Split(book.BootFile, ";")
  232. branches := strings.Split(book.BranchName, ";")
  233. for i, bootFile := range bootFiles {
  234. if branches[i] == option.BranchName && getBootFile(option.File, option.OwnerName, option.ProjectName) == bootFile {
  235. return true
  236. }
  237. }
  238. return false
  239. }
  240. func UploadNotebookFiles(task *models.Cloudbrain) {
  241. if task.Status == string(models.JobRunning) && task.BootFile != "" {
  242. debugBaseUrl, token, err := getBaseUrlAndToken(task)
  243. if err != nil {
  244. log.Error("can not get base url:", err)
  245. return
  246. }
  247. bootFiles := strings.Split(task.BootFile, ";")
  248. for _, bootFile := range bootFiles {
  249. uploadNotebookFileIfCannotBroswer(debugBaseUrl, bootFile, task, token)
  250. }
  251. }
  252. }
  253. func cloudBrainFileNoteBookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption, repo *models.Repository, sourceRepo *models.Repository) {
  254. displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name)
  255. jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
  256. jobType := string(models.JobTypeDebug)
  257. lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), jobType, displayJobName))
  258. defer lock.UnLock()
  259. isOk, err := lock.Lock(models.CloudbrainKeyDuration)
  260. if !isOk {
  261. log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
  262. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
  263. return
  264. }
  265. tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName)
  266. if err == nil {
  267. if len(tasks) != 0 {
  268. log.Error("the job name did already exist", ctx.Data["MsgID"])
  269. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
  270. return
  271. }
  272. } else {
  273. if !models.IsErrJobNotExist(err) {
  274. log.Error("system error, %v", err, ctx.Data["MsgID"])
  275. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
  276. return
  277. }
  278. }
  279. count, err := GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType)
  280. if err != nil {
  281. log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
  282. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
  283. return
  284. } else {
  285. if count >= 1 {
  286. log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
  287. ctx.JSON(http.StatusOK, models.BaseMessageApi{
  288. Code: 2,
  289. Message: ctx.Tr("repo.cloudbrain.morethanonejob"),
  290. })
  291. return
  292. }
  293. }
  294. err = downloadCode(sourceRepo, getCodePath(jobName, sourceRepo), option.BranchName)
  295. if err != nil {
  296. log.Error("download code failed", err)
  297. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.load_code_failed")))
  298. return
  299. }
  300. command := cloudbrain.GetCloudbrainDebugCommand()
  301. specId := setting.FileNoteBook.SpecIdGPU
  302. if option.Type == 0 {
  303. specId = setting.FileNoteBook.SpecIdCPU
  304. }
  305. spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{
  306. JobType: models.JobType(jobType),
  307. ComputeResource: models.GPU,
  308. Cluster: models.OpenICluster,
  309. AiCenterCode: models.AICenterOfCloudBrainOne})
  310. if err != nil || spec == nil {
  311. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.wrong_specification")))
  312. return
  313. }
  314. if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
  315. log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
  316. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
  317. return
  318. }
  319. ctx.Repo = &context.Repository{
  320. Repository: repo,
  321. }
  322. req := cloudbrain.GenerateCloudBrainTaskReq{
  323. Ctx: ctx,
  324. DisplayJobName: displayJobName,
  325. JobName: jobName,
  326. Image: setting.FileNoteBook.ImageGPU,
  327. Command: command,
  328. Uuids: "",
  329. DatasetNames: "",
  330. DatasetInfos: nil,
  331. CodePath: storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"),
  332. ModelPath: storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"),
  333. BenchmarkPath: storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"),
  334. Snn4ImageNetPath: storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"),
  335. BrainScorePath: storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"),
  336. JobType: jobType,
  337. Description: getDescription(option),
  338. BranchName: option.BranchName,
  339. BootFile: getBootFile(option.File, option.OwnerName, option.ProjectName),
  340. Params: "{\"parameter\":[]}",
  341. CommitID: "",
  342. BenchmarkTypeID: 0,
  343. BenchmarkChildTypeID: 0,
  344. ResultPath: storage.GetMinioPath(jobName, cloudbrain.ResultPath+"/"),
  345. Spec: spec,
  346. }
  347. jobId, err := cloudbrain.GenerateTask(req)
  348. if err != nil {
  349. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(err.Error()))
  350. return
  351. }
  352. ctx.JSON(http.StatusOK, models.BaseMessageApi{
  353. Code: 0,
  354. Message: jobId,
  355. })
  356. }
  357. func getCloudbrainType(optionType int) int {
  358. if optionType < 1 {
  359. return models.TypeCloudBrainOne
  360. }
  361. if setting.ModelartsCD.Enabled {
  362. return models.TypeCDCenter
  363. }
  364. return models.TypeCloudBrainTwo
  365. }
  366. func getCodePath(jobName string, repo *models.Repository) string {
  367. return setting.JobPath + jobName + cloudbrain.CodeMountPath + "/" + repo.OwnerName + "/" + repo.Name
  368. }
  369. func getDescription(option api.CreateFileNotebookJobOption) string {
  370. return option.OwnerName + "/" + option.ProjectName + "/" + option.File
  371. }
  372. func modelartsFileNoteBookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption, repo *models.Repository, sourceRepo *models.Repository) {
  373. displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name)
  374. jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
  375. lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeDebug), displayJobName))
  376. isOk, err := lock.Lock(models.CloudbrainKeyDuration)
  377. if !isOk {
  378. log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
  379. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
  380. return
  381. }
  382. defer lock.UnLock()
  383. count, err := GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeDebug))
  384. if err != nil {
  385. log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"])
  386. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
  387. return
  388. } else {
  389. if count >= 1 {
  390. log.Error("the user already has running or waiting task", ctx.Data["MsgID"])
  391. ctx.JSON(http.StatusOK, models.BaseMessageApi{
  392. Code: 2,
  393. Message: ctx.Tr("repo.cloudbrain.morethanonejob"),
  394. })
  395. return
  396. }
  397. }
  398. tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeDebug), displayJobName)
  399. if err == nil {
  400. if len(tasks) != 0 {
  401. log.Error("the job name did already exist", ctx.Data["MsgID"])
  402. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
  403. return
  404. }
  405. } else {
  406. if !models.IsErrJobNotExist(err) {
  407. log.Error("system error, %v", err, ctx.Data["MsgID"])
  408. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
  409. return
  410. }
  411. }
  412. err = downloadCode(sourceRepo, getCodePath(jobName, sourceRepo), option.BranchName)
  413. if err != nil {
  414. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.load_code_failed")))
  415. return
  416. }
  417. var aiCenterCode = models.AICenterOfCloudBrainTwo
  418. var specId = setting.FileNoteBook.SpecIdNPU
  419. if setting.ModelartsCD.Enabled {
  420. aiCenterCode = models.AICenterOfChengdu
  421. specId = setting.FileNoteBook.SpecIdNPUCD
  422. }
  423. spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{
  424. JobType: models.JobTypeDebug,
  425. ComputeResource: models.NPU,
  426. Cluster: models.OpenICluster,
  427. AiCenterCode: aiCenterCode})
  428. if err != nil || spec == nil {
  429. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.wrong_specification")))
  430. return
  431. }
  432. if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
  433. log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
  434. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
  435. return
  436. }
  437. ctx.Repo = &context.Repository{
  438. Repository: repo,
  439. }
  440. var jobId string
  441. req := cloudbrain.GenerateModelArtsNotebookReq{
  442. DisplayJobName: displayJobName,
  443. JobName: jobName,
  444. Description: getDescription(option),
  445. ImageId: setting.FileNoteBook.ImageIdNPU,
  446. Spec: spec,
  447. BootFile: getBootFile(option.File, option.OwnerName, option.ProjectName),
  448. AutoStopDurationMs: modelarts.AutoStopDurationMs / 4,
  449. BranchName: option.BranchName,
  450. }
  451. if setting.ModelartsCD.Enabled {
  452. req.ImageId = setting.FileNoteBook.ImageIdNPUCD
  453. jobId, err = modelarts_cd.GenerateNotebook(ctx, req)
  454. } else {
  455. jobId, err = modelarts.GenerateNotebook2(ctx, req)
  456. }
  457. if err != nil {
  458. log.Error("GenerateNotebook2 failed, %v", err, ctx.Data["MsgID"])
  459. ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(err.Error()))
  460. return
  461. }
  462. ctx.JSON(http.StatusOK, models.BaseMessageApi{
  463. Code: 0,
  464. Message: jobId,
  465. })
  466. }
  467. func isNoteBookFileExist(ctx *context.Context, option api.CreateFileNotebookJobOption) (bool, error) {
  468. repoPathOfNoteBook := models.RepoPath(option.OwnerName, option.ProjectName)
  469. gitRepoOfNoteBook, err := git.OpenRepository(repoPathOfNoteBook)
  470. if err != nil {
  471. log.Error("RepoRef Invalid repo "+repoPathOfNoteBook, err.Error())
  472. return false, err
  473. }
  474. // We opened it, we should close it
  475. defer func() {
  476. // If it's been set to nil then assume someone else has closed it.
  477. if gitRepoOfNoteBook != nil {
  478. gitRepoOfNoteBook.Close()
  479. }
  480. }()
  481. fileExist, err := fileExists(gitRepoOfNoteBook, option.File, option.BranchName)
  482. if err != nil || !fileExist {
  483. log.Error("Get file error:", err, ctx.Data["MsgID"])
  484. return false, err
  485. }
  486. return true, nil
  487. }
  488. func getBootFile(filePath string, ownerName string, projectName string) string {
  489. return ownerName + "/" + projectName + "/" + filePath
  490. }
  491. func fileExists(gitRepo *git.Repository, path string, branch string) (bool, error) {
  492. commit, err := gitRepo.GetBranchCommit(branch)
  493. if err != nil {
  494. return false, err
  495. }
  496. if _, err := commit.GetTreeEntryByPath(path); err != nil {
  497. return false, err
  498. }
  499. return true, nil
  500. }