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

migrate_storage.go 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package cmd
  5. import (
  6. "context"
  7. "fmt"
  8. "strings"
  9. "code.gitea.io/gitea/models"
  10. "code.gitea.io/gitea/models/migrations"
  11. "code.gitea.io/gitea/modules/log"
  12. "code.gitea.io/gitea/modules/setting"
  13. "code.gitea.io/gitea/modules/storage"
  14. "github.com/urfave/cli"
  15. )
  16. // CmdMigrateStorage represents the available migrate storage sub-command.
  17. var CmdMigrateStorage = cli.Command{
  18. Name: "migrate-storage",
  19. Usage: "Migrate the storage",
  20. Description: "This is a command for migrating storage.",
  21. Action: runMigrateStorage,
  22. Flags: []cli.Flag{
  23. cli.StringFlag{
  24. Name: "type, t",
  25. Value: "",
  26. Usage: "Kinds of files to migrate, currently only 'attachments' is supported",
  27. },
  28. cli.StringFlag{
  29. Name: "storage, s",
  30. Value: "",
  31. Usage: "New storage type: local (default) or minio",
  32. },
  33. cli.StringFlag{
  34. Name: "path, p",
  35. Value: "",
  36. Usage: "New storage placement if store is local (leave blank for default)",
  37. },
  38. cli.StringFlag{
  39. Name: "minio-endpoint",
  40. Value: "",
  41. Usage: "Minio storage endpoint",
  42. },
  43. cli.StringFlag{
  44. Name: "minio-access-key-id",
  45. Value: "",
  46. Usage: "Minio storage accessKeyID",
  47. },
  48. cli.StringFlag{
  49. Name: "minio-secret-access-key",
  50. Value: "",
  51. Usage: "Minio storage secretAccessKey",
  52. },
  53. cli.StringFlag{
  54. Name: "minio-bucket",
  55. Value: "",
  56. Usage: "Minio storage bucket",
  57. },
  58. cli.StringFlag{
  59. Name: "minio-location",
  60. Value: "",
  61. Usage: "Minio storage location to create bucket",
  62. },
  63. cli.StringFlag{
  64. Name: "minio-base-path",
  65. Value: "",
  66. Usage: "Minio storage basepath on the bucket",
  67. },
  68. cli.BoolFlag{
  69. Name: "minio-use-ssl",
  70. Usage: "Enable SSL for minio",
  71. },
  72. },
  73. }
  74. func migrateAttachments(dstStorage storage.ObjectStorage) error {
  75. return models.IterateAttachment(func(attach *models.Attachment) error {
  76. _, err := storage.Copy(dstStorage, attach.RelativePath(), storage.Attachments, attach.RelativePath())
  77. return err
  78. })
  79. }
  80. func migrateLFS(dstStorage storage.ObjectStorage) error {
  81. return models.IterateLFS(func(mo *models.LFSMetaObject) error {
  82. _, err := storage.Copy(dstStorage, mo.RelativePath(), storage.LFS, mo.RelativePath())
  83. return err
  84. })
  85. }
  86. func migrateAvatars(dstStorage storage.ObjectStorage) error {
  87. return models.IterateUser(func(user *models.User) error {
  88. _, err := storage.Copy(dstStorage, user.CustomAvatarRelativePath(), storage.Avatars, user.CustomAvatarRelativePath())
  89. return err
  90. })
  91. }
  92. func migrateRepoAvatars(dstStorage storage.ObjectStorage) error {
  93. return models.IterateRepository(func(repo *models.Repository) error {
  94. _, err := storage.Copy(dstStorage, repo.CustomAvatarRelativePath(), storage.RepoAvatars, repo.CustomAvatarRelativePath())
  95. return err
  96. })
  97. }
  98. func runMigrateStorage(ctx *cli.Context) error {
  99. if err := initDB(); err != nil {
  100. return err
  101. }
  102. log.Trace("AppPath: %s", setting.AppPath)
  103. log.Trace("AppWorkPath: %s", setting.AppWorkPath)
  104. log.Trace("Custom path: %s", setting.CustomPath)
  105. log.Trace("Log path: %s", setting.LogRootPath)
  106. setting.InitDBConfig()
  107. if err := models.NewEngine(context.Background(), migrations.Migrate); err != nil {
  108. log.Fatal("Failed to initialize ORM engine: %v", err)
  109. return err
  110. }
  111. goCtx := context.Background()
  112. if err := storage.Init(); err != nil {
  113. return err
  114. }
  115. var dstStorage storage.ObjectStorage
  116. var err error
  117. switch strings.ToLower(ctx.String("storage")) {
  118. case "":
  119. fallthrough
  120. case string(storage.LocalStorageType):
  121. p := ctx.String("path")
  122. if p == "" {
  123. log.Fatal("Path must be given when storage is loal")
  124. return nil
  125. }
  126. dstStorage, err = storage.NewLocalStorage(
  127. goCtx,
  128. storage.LocalStorageConfig{
  129. Path: p,
  130. })
  131. case string(storage.MinioStorageType):
  132. dstStorage, err = storage.NewMinioStorage(
  133. goCtx,
  134. storage.MinioStorageConfig{
  135. Endpoint: ctx.String("minio-endpoint"),
  136. AccessKeyID: ctx.String("minio-access-key-id"),
  137. SecretAccessKey: ctx.String("minio-secret-access-key"),
  138. Bucket: ctx.String("minio-bucket"),
  139. Location: ctx.String("minio-location"),
  140. BasePath: ctx.String("minio-base-path"),
  141. UseSSL: ctx.Bool("minio-use-ssl"),
  142. })
  143. default:
  144. return fmt.Errorf("Unsupported storage type: %s", ctx.String("storage"))
  145. }
  146. if err != nil {
  147. return err
  148. }
  149. tp := strings.ToLower(ctx.String("type"))
  150. switch tp {
  151. case "attachments":
  152. if err := migrateAttachments(dstStorage); err != nil {
  153. return err
  154. }
  155. case "lfs":
  156. if err := migrateLFS(dstStorage); err != nil {
  157. return err
  158. }
  159. case "avatars":
  160. if err := migrateAvatars(dstStorage); err != nil {
  161. return err
  162. }
  163. case "repo-avatars":
  164. if err := migrateRepoAvatars(dstStorage); err != nil {
  165. return err
  166. }
  167. default:
  168. return fmt.Errorf("Unsupported storage: %s", ctx.String("type"))
  169. }
  170. log.Warn("All files have been copied to the new placement but old files are still on the orignial placement.")
  171. return nil
  172. }