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.

cloudbrain.go 17 kB

2 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. package cloudbrain
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "os"
  6. "strconv"
  7. "code.gitea.io/gitea/modules/timeutil"
  8. "code.gitea.io/gitea/modules/storage"
  9. "code.gitea.io/gitea/models"
  10. "code.gitea.io/gitea/modules/context"
  11. "code.gitea.io/gitea/modules/log"
  12. "code.gitea.io/gitea/modules/notification"
  13. "code.gitea.io/gitea/modules/setting"
  14. )
  15. const (
  16. Command = `pip3 install jupyterlab==2.2.5 -i https://pypi.tuna.tsinghua.edu.cn/simple;service ssh stop;jupyter lab --no-browser --ip=0.0.0.0 --allow-root --notebook-dir="/code" --port=80 --LabApp.token="" --LabApp.allow_origin="self https://cloudbrain.pcl.ac.cn"`
  17. //CommandBenchmark = `echo "start benchmark";python /code/test.py;echo "end benchmark"`
  18. CommandBenchmark = `echo "start benchmark";cd /benchmark && bash run_bk.sh;echo "end benchmark"`
  19. CodeMountPath = "/code"
  20. DataSetMountPath = "/dataset"
  21. ModelMountPath = "/model"
  22. LogFile = "log.txt"
  23. BenchMarkMountPath = "/benchmark"
  24. BenchMarkResourceID = 1
  25. Snn4imagenetMountPath = "/snn4imagenet"
  26. BrainScoreMountPath = "/brainscore"
  27. TaskInfoName = "/taskInfo"
  28. Snn4imagenetCommand = `/opt/conda/bin/python /snn4imagenet/testSNN_script.py --modelname '%s' --modelpath '/dataset' --modeldescription '%s'`
  29. BrainScoreCommand = `bash /brainscore/brainscore_test_par4shSrcipt.sh -b '%s' -n '%s' -p '/dataset' -d '%s'`
  30. SubTaskName = "task1"
  31. Success = "S000"
  32. DefaultBranchName = "master"
  33. ResultPath = "/result"
  34. )
  35. var (
  36. ResourceSpecs *models.ResourceSpecs
  37. TrainResourceSpecs *models.ResourceSpecs
  38. )
  39. type GenerateCloudBrainTaskReq struct {
  40. Ctx *context.Context
  41. DisplayJobName string
  42. JobName string
  43. Image string
  44. Command string
  45. CodePath string
  46. ModelPath string
  47. BenchmarkPath string
  48. Snn4ImageNetPath string
  49. BrainScorePath string
  50. JobType string
  51. GpuQueue string
  52. Description string
  53. BranchName string
  54. BootFile string
  55. Params string
  56. CommitID string
  57. Uuids string
  58. DatasetNames string
  59. DatasetInfos map[string]models.DatasetInfo
  60. BenchmarkTypeID int
  61. BenchmarkChildTypeID int
  62. ResourceSpecId int
  63. ResultPath string
  64. TrainUrl string
  65. ModelName string
  66. ModelVersion string
  67. CkptName string
  68. }
  69. func isAdminOrOwnerOrJobCreater(ctx *context.Context, job *models.Cloudbrain, err error) bool {
  70. if !ctx.IsSigned {
  71. return false
  72. }
  73. if err != nil {
  74. return ctx.IsUserRepoOwner() || ctx.IsUserSiteAdmin()
  75. } else {
  76. return ctx.IsUserRepoOwner() || ctx.IsUserSiteAdmin() || ctx.User.ID == job.UserID
  77. }
  78. }
  79. func CanDeleteJob(ctx *context.Context, job *models.Cloudbrain) bool {
  80. return isAdminOrOwnerOrJobCreater(ctx, job, nil)
  81. }
  82. func CanCreateOrDebugJob(ctx *context.Context) bool {
  83. if !ctx.IsSigned {
  84. return false
  85. }
  86. return ctx.Repo.CanWrite(models.UnitTypeCloudBrain)
  87. }
  88. func CanModifyJob(ctx *context.Context, job *models.Cloudbrain) bool {
  89. return isAdminOrJobCreater(ctx, job, nil)
  90. }
  91. func isAdminOrJobCreater(ctx *context.Context, job *models.Cloudbrain, err error) bool {
  92. if !ctx.IsSigned {
  93. return false
  94. }
  95. if err != nil {
  96. return ctx.IsUserSiteAdmin()
  97. } else {
  98. return ctx.IsUserSiteAdmin() || ctx.User.ID == job.UserID
  99. }
  100. }
  101. func isAdminOrImageCreater(ctx *context.Context, image *models.Image, err error) bool {
  102. if !ctx.IsSigned {
  103. return false
  104. }
  105. if err != nil {
  106. return ctx.IsUserSiteAdmin()
  107. } else {
  108. return ctx.IsUserSiteAdmin() || ctx.User.ID == image.UID
  109. }
  110. }
  111. func AdminOrOwnerOrJobCreaterRight(ctx *context.Context) {
  112. var ID = ctx.Params(":id")
  113. job, err := models.GetCloudbrainByID(ID)
  114. if err != nil {
  115. log.Error("GetCloudbrainByID failed:%v", err.Error())
  116. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  117. }
  118. ctx.Cloudbrain = job
  119. if !isAdminOrOwnerOrJobCreater(ctx, job, err) {
  120. log.Error("!isAdminOrOwnerOrJobCreater error:%v", err.Error())
  121. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  122. }
  123. }
  124. func AdminOrJobCreaterRight(ctx *context.Context) {
  125. var ID = ctx.Params(":id")
  126. job, err := models.GetCloudbrainByID(ID)
  127. if err != nil {
  128. log.Error("GetCloudbrainByID failed:%v", err.Error())
  129. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  130. }
  131. ctx.Cloudbrain = job
  132. if !isAdminOrJobCreater(ctx, job, err) {
  133. log.Error("!isAdminOrJobCreater error:%v", err.Error())
  134. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  135. }
  136. }
  137. func AdminOrOwnerOrJobCreaterRightForTrain(ctx *context.Context) {
  138. var jobID = ctx.Params(":jobid")
  139. job, err := models.GetCloudbrainByJobID(jobID)
  140. if err != nil {
  141. log.Error("GetCloudbrainByJobID failed:%v", err.Error())
  142. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  143. }
  144. ctx.Cloudbrain = job
  145. if !isAdminOrOwnerOrJobCreater(ctx, job, err) {
  146. log.Error("!isAdminOrOwnerOrJobCreater failed:%v", err.Error())
  147. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  148. }
  149. }
  150. func AdminOrJobCreaterRightForTrain(ctx *context.Context) {
  151. var jobID = ctx.Params(":jobid")
  152. job, err := models.GetCloudbrainByJobID(jobID)
  153. if err != nil {
  154. log.Error("GetCloudbrainByJobID failed:%v", err.Error())
  155. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  156. }
  157. ctx.Cloudbrain = job
  158. if !isAdminOrJobCreater(ctx, job, err) {
  159. log.Error("!isAdminOrJobCreater errot:%v", err.Error())
  160. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  161. }
  162. }
  163. func AdminOrImageCreaterRight(ctx *context.Context) {
  164. id, err := strconv.ParseInt(ctx.Params(":id"), 10, 64)
  165. var image *models.Image
  166. if err != nil {
  167. log.Error("Get Image by ID failed:%v", err.Error())
  168. } else {
  169. image, err = models.GetImageByID(id)
  170. if err != nil {
  171. log.Error("Get Image by ID failed:%v", err.Error())
  172. return
  173. }
  174. }
  175. if !isAdminOrImageCreater(ctx, image, err) {
  176. log.Error("!isAdminOrImageCreater error:%v", err.Error())
  177. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  178. }
  179. }
  180. func GenerateTask(req GenerateCloudBrainTaskReq) error {
  181. var resourceSpec *models.ResourceSpec
  182. var versionCount int
  183. if req.JobType == string(models.JobTypeTrain) || req.JobType == string(models.JobTypeInference) {
  184. versionCount = 1
  185. if TrainResourceSpecs == nil {
  186. json.Unmarshal([]byte(setting.TrainResourceSpecs), &TrainResourceSpecs)
  187. }
  188. for _, spec := range TrainResourceSpecs.ResourceSpec {
  189. if req.ResourceSpecId == spec.Id {
  190. resourceSpec = spec
  191. }
  192. }
  193. } else {
  194. if ResourceSpecs == nil {
  195. json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs)
  196. }
  197. for _, spec := range ResourceSpecs.ResourceSpec {
  198. if req.ResourceSpecId == spec.Id {
  199. resourceSpec = spec
  200. }
  201. }
  202. }
  203. if resourceSpec == nil {
  204. log.Error("no such resourceSpecId(%d)", req.ResourceSpecId, req.Ctx.Data["MsgID"])
  205. return errors.New("no such resourceSpec")
  206. }
  207. volumes := []models.Volume{
  208. {
  209. HostPath: models.StHostPath{
  210. Path: req.CodePath,
  211. MountPath: CodeMountPath,
  212. ReadOnly: false,
  213. },
  214. },
  215. {
  216. HostPath: models.StHostPath{
  217. Path: req.BenchmarkPath,
  218. MountPath: BenchMarkMountPath,
  219. ReadOnly: true,
  220. },
  221. },
  222. {
  223. HostPath: models.StHostPath{
  224. Path: req.Snn4ImageNetPath,
  225. MountPath: Snn4imagenetMountPath,
  226. ReadOnly: true,
  227. },
  228. },
  229. {
  230. HostPath: models.StHostPath{
  231. Path: req.BrainScorePath,
  232. MountPath: BrainScoreMountPath,
  233. ReadOnly: true,
  234. },
  235. },
  236. {
  237. HostPath: models.StHostPath{
  238. Path: req.ResultPath,
  239. MountPath: ResultPath,
  240. ReadOnly: false,
  241. },
  242. },
  243. }
  244. if len(req.DatasetInfos) == 1 {
  245. volumes = append(volumes, models.Volume{
  246. HostPath: models.StHostPath{
  247. Path: req.DatasetInfos[req.Uuids].DataLocalPath,
  248. MountPath: DataSetMountPath,
  249. ReadOnly: true,
  250. },
  251. })
  252. } else {
  253. for _, dataset := range req.DatasetInfos {
  254. volumes = append(volumes, models.Volume{
  255. HostPath: models.StHostPath{
  256. Path: dataset.DataLocalPath,
  257. MountPath: DataSetMountPath + "/" + dataset.Name,
  258. ReadOnly: true,
  259. },
  260. })
  261. }
  262. }
  263. createTime := timeutil.TimeStampNow()
  264. jobResult, err := CreateJob(req.JobName, models.CreateJobParams{
  265. JobName: req.JobName,
  266. RetryCount: 1,
  267. GpuType: req.GpuQueue,
  268. Image: req.Image,
  269. TaskRoles: []models.TaskRole{
  270. {
  271. Name: SubTaskName,
  272. TaskNumber: 1,
  273. MinSucceededTaskCount: 1,
  274. MinFailedTaskCount: 1,
  275. CPUNumber: resourceSpec.CpuNum,
  276. GPUNumber: resourceSpec.GpuNum,
  277. MemoryMB: resourceSpec.MemMiB,
  278. ShmMB: resourceSpec.ShareMemMiB,
  279. Command: req.Command,
  280. NeedIBDevice: false,
  281. IsMainRole: false,
  282. UseNNI: false,
  283. },
  284. },
  285. Volumes: volumes,
  286. })
  287. if err != nil {
  288. log.Error("CreateJob failed:", err.Error(), req.Ctx.Data["MsgID"])
  289. return err
  290. }
  291. if jobResult.Code != Success {
  292. log.Error("CreateJob(%s) failed:%s", req.JobName, jobResult.Msg, req.Ctx.Data["MsgID"])
  293. return errors.New(jobResult.Msg)
  294. }
  295. var jobID = jobResult.Payload["jobId"].(string)
  296. err = models.CreateCloudbrain(&models.Cloudbrain{
  297. Status: string(models.JobWaiting),
  298. UserID: req.Ctx.User.ID,
  299. RepoID: req.Ctx.Repo.Repository.ID,
  300. JobID: jobID,
  301. JobName: req.JobName,
  302. DisplayJobName: req.DisplayJobName,
  303. SubTaskName: SubTaskName,
  304. JobType: req.JobType,
  305. Type: models.TypeCloudBrainOne,
  306. Uuid: req.Uuids,
  307. Image: req.Image,
  308. GpuQueue: req.GpuQueue,
  309. ResourceSpecId: req.ResourceSpecId,
  310. ComputeResource: models.GPUResource,
  311. BenchmarkTypeID: req.BenchmarkTypeID,
  312. BenchmarkChildTypeID: req.BenchmarkChildTypeID,
  313. Description: req.Description,
  314. IsLatestVersion: "1",
  315. VersionCount: versionCount,
  316. BranchName: req.BranchName,
  317. BootFile: req.BootFile,
  318. DatasetName: req.DatasetNames,
  319. Parameters: req.Params,
  320. TrainUrl: req.TrainUrl,
  321. ModelName: req.ModelName,
  322. ModelVersion: req.ModelVersion,
  323. CkptName: req.CkptName,
  324. ResultUrl: req.ResultPath,
  325. CreatedUnix: createTime,
  326. UpdatedUnix: createTime,
  327. CommitID: req.CommitID,
  328. })
  329. if err != nil {
  330. return err
  331. }
  332. task, err := models.GetCloudbrainByJobID(jobID)
  333. if err != nil {
  334. log.Error("GetCloudbrainByJobID failed: %v", err.Error())
  335. return err
  336. }
  337. stringId := strconv.FormatInt(task.ID, 10)
  338. if IsBenchmarkJob(req.JobType) {
  339. notification.NotifyOtherTask(req.Ctx.User, req.Ctx.Repo.Repository, stringId, req.DisplayJobName, models.ActionCreateBenchMarkTask)
  340. } else if string(models.JobTypeTrain) == req.JobType {
  341. notification.NotifyOtherTask(req.Ctx.User, req.Ctx.Repo.Repository, jobID, req.DisplayJobName, models.ActionCreateGPUTrainTask)
  342. } else if string(models.JobTypeInference) == req.JobType {
  343. notification.NotifyOtherTask(req.Ctx.User, req.Ctx.Repo.Repository, jobID, req.DisplayJobName, models.ActionCreateInferenceTask)
  344. } else {
  345. notification.NotifyOtherTask(req.Ctx.User, req.Ctx.Repo.Repository, stringId, req.DisplayJobName, models.ActionCreateDebugGPUTask)
  346. }
  347. return nil
  348. }
  349. func IsBenchmarkJob(jobType string) bool {
  350. return string(models.JobTypeBenchmark) == jobType || string(models.JobTypeBrainScore) == jobType || string(models.JobTypeSnn4imagenet) == jobType
  351. }
  352. func GetWaitingCloudbrainCount(cloudbrainType int, computeResource string, jobTypes ...models.JobType) int64 {
  353. num, err := models.GetWaitingCloudbrainCount(cloudbrainType, computeResource, jobTypes...)
  354. if err != nil {
  355. log.Warn("Get waiting count err", err)
  356. num = 0
  357. }
  358. return num
  359. }
  360. func RestartTask(ctx *context.Context, task *models.Cloudbrain, newID *string) error {
  361. jobName := task.JobName
  362. var resourceSpec *models.ResourceSpec
  363. if ResourceSpecs == nil {
  364. json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs)
  365. }
  366. for _, spec := range ResourceSpecs.ResourceSpec {
  367. if task.ResourceSpecId == spec.Id {
  368. resourceSpec = spec
  369. }
  370. }
  371. if resourceSpec == nil {
  372. log.Error("no such resourceSpecId(%d)", task.ResourceSpecId, ctx.Data["MsgID"])
  373. return errors.New("no such resourceSpec")
  374. }
  375. datasetInfos, _, err := models.GetDatasetInfo(task.Uuid)
  376. if err != nil {
  377. log.Error("GetDatasetInfo failed:%v", err, ctx.Data["MsgID"])
  378. return err
  379. }
  380. volumes := []models.Volume{
  381. {
  382. HostPath: models.StHostPath{
  383. Path: storage.GetMinioPath(jobName, CodeMountPath+"/"),
  384. MountPath: CodeMountPath,
  385. ReadOnly: false,
  386. },
  387. },
  388. {
  389. HostPath: models.StHostPath{
  390. Path: storage.GetMinioPath(jobName, ModelMountPath+"/"),
  391. MountPath: ModelMountPath,
  392. ReadOnly: false,
  393. },
  394. },
  395. {
  396. HostPath: models.StHostPath{
  397. Path: storage.GetMinioPath(jobName, BenchMarkMountPath+"/"),
  398. MountPath: BenchMarkMountPath,
  399. ReadOnly: true,
  400. },
  401. },
  402. {
  403. HostPath: models.StHostPath{
  404. Path: storage.GetMinioPath(jobName, Snn4imagenetMountPath+"/"),
  405. MountPath: Snn4imagenetMountPath,
  406. ReadOnly: true,
  407. },
  408. },
  409. {
  410. HostPath: models.StHostPath{
  411. Path: storage.GetMinioPath(jobName, BrainScoreMountPath+"/"),
  412. MountPath: BrainScoreMountPath,
  413. ReadOnly: true,
  414. },
  415. },
  416. }
  417. if len(datasetInfos) == 1 {
  418. volumes = append(volumes, models.Volume{
  419. HostPath: models.StHostPath{
  420. Path: datasetInfos[task.Uuid].DataLocalPath,
  421. MountPath: DataSetMountPath,
  422. ReadOnly: true,
  423. },
  424. })
  425. } else {
  426. for _, dataset := range datasetInfos {
  427. volumes = append(volumes, models.Volume{
  428. HostPath: models.StHostPath{
  429. Path: dataset.DataLocalPath,
  430. MountPath: DataSetMountPath + "/" + dataset.Name,
  431. ReadOnly: true,
  432. },
  433. })
  434. }
  435. }
  436. createTime := timeutil.TimeStampNow()
  437. jobResult, err := CreateJob(jobName, models.CreateJobParams{
  438. JobName: jobName,
  439. RetryCount: 1,
  440. GpuType: task.GpuQueue,
  441. Image: task.Image,
  442. TaskRoles: []models.TaskRole{
  443. {
  444. Name: SubTaskName,
  445. TaskNumber: 1,
  446. MinSucceededTaskCount: 1,
  447. MinFailedTaskCount: 1,
  448. CPUNumber: resourceSpec.CpuNum,
  449. GPUNumber: resourceSpec.GpuNum,
  450. MemoryMB: resourceSpec.MemMiB,
  451. ShmMB: resourceSpec.ShareMemMiB,
  452. Command: Command,
  453. NeedIBDevice: false,
  454. IsMainRole: false,
  455. UseNNI: false,
  456. },
  457. },
  458. Volumes: volumes,
  459. })
  460. if err != nil {
  461. log.Error("CreateJob failed:%v", err.Error(), ctx.Data["MsgID"])
  462. return err
  463. }
  464. if jobResult.Code != Success {
  465. log.Error("CreateJob(%s) failed:%s", jobName, jobResult.Msg, ctx.Data["MsgID"])
  466. return errors.New(jobResult.Msg)
  467. }
  468. var jobID = jobResult.Payload["jobId"].(string)
  469. newTask := &models.Cloudbrain{
  470. Status: string(models.JobWaiting),
  471. UserID: task.UserID,
  472. RepoID: task.RepoID,
  473. JobID: jobID,
  474. JobName: task.JobName,
  475. DisplayJobName: task.DisplayJobName,
  476. SubTaskName: task.SubTaskName,
  477. JobType: task.JobType,
  478. Type: task.Type,
  479. Uuid: task.Uuid,
  480. DatasetName: task.DatasetName,
  481. Image: task.Image,
  482. GpuQueue: task.GpuQueue,
  483. ResourceSpecId: task.ResourceSpecId,
  484. ComputeResource: task.ComputeResource,
  485. CreatedUnix: createTime,
  486. UpdatedUnix: createTime,
  487. BranchName: task.BranchName,
  488. }
  489. err = models.RestartCloudbrain(task, newTask)
  490. if err != nil {
  491. log.Error("RestartCloudbrain(%s) failed:%v", jobName, err.Error(), ctx.Data["MsgID"])
  492. return err
  493. }
  494. stringId := strconv.FormatInt(newTask.ID, 10)
  495. *newID = stringId
  496. notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, stringId, task.DisplayJobName, models.ActionCreateDebugGPUTask)
  497. return nil
  498. }
  499. func DelCloudBrainJob(jobId string) string {
  500. task, err := models.GetCloudbrainByJobID(jobId)
  501. if err != nil {
  502. log.Error("get cloud brain err:", err)
  503. return "cloudbrain.Delete_failed"
  504. }
  505. if task.Status != string(models.JobStopped) && task.Status != string(models.JobFailed) && task.Status != string(models.JobSucceeded) {
  506. log.Error("the job(%s) has not been stopped", task.JobName)
  507. return "cloudbrain.Not_Stopped"
  508. }
  509. err = models.DeleteJob(task)
  510. if err != nil {
  511. log.Error("DeleteJob failed:", err)
  512. return "cloudbrain.Delete_failed"
  513. }
  514. deleteJobStorage(task.JobName)
  515. return ""
  516. }
  517. func deleteJobStorage(jobName string) error {
  518. //delete local
  519. localJobPath := setting.JobPath + jobName
  520. err := os.RemoveAll(localJobPath)
  521. if err != nil {
  522. log.Error("RemoveAll(%s) failed:%v", localJobPath, err)
  523. }
  524. dirPath := setting.CBCodePathPrefix + jobName + "/"
  525. err = storage.Attachments.DeleteDir(dirPath)
  526. if err != nil {
  527. log.Error("DeleteDir(%s) failed:%v", localJobPath, err)
  528. }
  529. return nil
  530. }