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.

temp.go 10 kB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. package http
  2. import (
  3. "net/http"
  4. "github.com/gin-gonic/gin"
  5. "github.com/samber/lo"
  6. "gitlink.org.cn/cloudream/common/consts/errorcode"
  7. "gitlink.org.cn/cloudream/common/pkgs/logger"
  8. cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
  9. )
  10. type TempService struct {
  11. *Server
  12. }
  13. func (s *Server) Temp() *TempService {
  14. return &TempService{
  15. Server: s,
  16. }
  17. }
  18. type TempListDetailsResp struct {
  19. Buckets []BucketDetail `json:"buckets"`
  20. }
  21. type BucketDetail struct {
  22. BucketID cdssdk.BucketID `json:"bucketID"`
  23. Name string `json:"name"`
  24. ObjectCount int `json:"objectCount"`
  25. }
  26. func (s *TempService) ListDetails(ctx *gin.Context) {
  27. log := logger.WithField("HTTP", "Bucket.ListBucketsDetails")
  28. bkts, err := s.svc.BucketSvc().GetUserBuckets(1)
  29. if err != nil {
  30. log.Warnf("getting user buckets: %s", err.Error())
  31. ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get user buckets failed"))
  32. return
  33. }
  34. details := make([]BucketDetail, len(bkts))
  35. for i := range bkts {
  36. details[i].BucketID = bkts[i].BucketID
  37. details[i].Name = bkts[i].Name
  38. objs, err := s.getBucketObjects(bkts[i].BucketID)
  39. if err != nil {
  40. log.Warnf("getting bucket objects: %s", err.Error())
  41. ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get bucket objects failed"))
  42. return
  43. }
  44. details[i].ObjectCount = len(objs)
  45. }
  46. ctx.JSON(http.StatusOK, OK(TempListDetailsResp{
  47. Buckets: details,
  48. }))
  49. }
  50. type TempGetObjects struct {
  51. BucketID cdssdk.BucketID `form:"bucketID"`
  52. }
  53. type BucketGetObjectsResp struct {
  54. Objects []cdssdk.Object `json:"objects"`
  55. }
  56. func (s *TempService) GetObjects(ctx *gin.Context) {
  57. log := logger.WithField("HTTP", "Bucket.ListBucketsDetails")
  58. var req TempGetObjects
  59. if err := ctx.ShouldBindQuery(&req); err != nil {
  60. log.Warnf("binding query: %s", err.Error())
  61. ctx.JSON(http.StatusBadRequest, Failed(errorcode.BadArgument, "missing argument or invalid argument"))
  62. return
  63. }
  64. objs, err := s.getBucketObjects(req.BucketID)
  65. if err != nil {
  66. log.Warnf("getting bucket objects: %s", err.Error())
  67. ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get bucket objects failed"))
  68. return
  69. }
  70. ctx.JSON(http.StatusOK, OK(BucketGetObjectsResp{
  71. Objects: objs,
  72. }))
  73. }
  74. type TempGetObjectDetail struct {
  75. ObjectID cdssdk.ObjectID `form:"objectID"`
  76. }
  77. type TempGetObjectDetailResp struct {
  78. Blocks []ObjectBlockDetail `json:"blocks"`
  79. }
  80. type ObjectBlockDetail struct {
  81. ObjectID cdssdk.ObjectID `json:"objectID"`
  82. Type string `json:"type"`
  83. FileHash string `json:"fileHash"`
  84. LocationType string `json:"locationType"`
  85. LocationName string `json:"locationName"`
  86. }
  87. func (s *TempService) GetObjectDetail(ctx *gin.Context) {
  88. log := logger.WithField("HTTP", "Object.GetObjectDetail")
  89. var req TempGetObjectDetail
  90. if err := ctx.ShouldBindQuery(&req); err != nil {
  91. log.Warnf("binding query: %s", err.Error())
  92. ctx.JSON(http.StatusBadRequest, Failed(errorcode.BadArgument, "missing argument or invalid argument"))
  93. return
  94. }
  95. details, err := s.svc.ObjectSvc().GetObjectDetail(req.ObjectID)
  96. if err != nil {
  97. log.Warnf("getting object detail: %s", err.Error())
  98. ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get object detail failed"))
  99. return
  100. }
  101. if details == nil {
  102. log.Warnf("object not found")
  103. ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "object not found"))
  104. return
  105. }
  106. loadedNodeIDs, err := s.svc.PackageSvc().GetLoadedNodes(1, details.Object.PackageID)
  107. if err != nil {
  108. log.Warnf("getting loaded nodes: %s", err.Error())
  109. ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get loaded nodes failed"))
  110. return
  111. }
  112. var allNodeIDs []cdssdk.NodeID
  113. allNodeIDs = append(allNodeIDs, details.PinnedAt...)
  114. for _, b := range details.Blocks {
  115. allNodeIDs = append(allNodeIDs, b.NodeID)
  116. }
  117. allNodeIDs = append(allNodeIDs, loadedNodeIDs...)
  118. allNodeIDs = lo.Uniq(allNodeIDs)
  119. getNodes, err := s.svc.NodeSvc().GetNodes(allNodeIDs)
  120. if err != nil {
  121. log.Warnf("getting nodes: %s", err.Error())
  122. ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get nodes failed"))
  123. return
  124. }
  125. allNodes := make(map[cdssdk.NodeID]*cdssdk.Node)
  126. for _, n := range getNodes {
  127. n2 := n
  128. allNodes[n.NodeID] = &n2
  129. }
  130. var blocks []ObjectBlockDetail
  131. for _, nodeID := range details.PinnedAt {
  132. blocks = append(blocks, ObjectBlockDetail{
  133. Type: "Rep",
  134. FileHash: details.Object.FileHash,
  135. LocationType: "Agent",
  136. LocationName: allNodes[nodeID].Name,
  137. })
  138. }
  139. switch details.Object.Redundancy.(type) {
  140. case *cdssdk.NoneRedundancy:
  141. for _, blk := range details.Blocks {
  142. if !lo.Contains(details.PinnedAt, blk.NodeID) {
  143. blocks = append(blocks, ObjectBlockDetail{
  144. Type: "Rep",
  145. FileHash: blk.FileHash,
  146. LocationType: "Agent",
  147. LocationName: allNodes[blk.NodeID].Name,
  148. })
  149. }
  150. }
  151. case *cdssdk.RepRedundancy:
  152. for _, blk := range details.Blocks {
  153. if !lo.Contains(details.PinnedAt, blk.NodeID) {
  154. blocks = append(blocks, ObjectBlockDetail{
  155. Type: "Rep",
  156. FileHash: blk.FileHash,
  157. LocationType: "Agent",
  158. LocationName: allNodes[blk.NodeID].Name,
  159. })
  160. }
  161. }
  162. case *cdssdk.ECRedundancy:
  163. for _, blk := range details.Blocks {
  164. blocks = append(blocks, ObjectBlockDetail{
  165. Type: "Block",
  166. FileHash: blk.FileHash,
  167. LocationType: "Agent",
  168. LocationName: allNodes[blk.NodeID].Name,
  169. })
  170. }
  171. }
  172. for _, nodeID := range loadedNodeIDs {
  173. blocks = append(blocks, ObjectBlockDetail{
  174. Type: "Rep",
  175. FileHash: details.Object.FileHash,
  176. LocationType: "Storage",
  177. LocationName: allNodes[nodeID].Name,
  178. })
  179. }
  180. ctx.JSON(http.StatusOK, OK(TempGetObjectDetailResp{
  181. Blocks: blocks,
  182. }))
  183. }
  184. func (s *TempService) getBucketObjects(bktID cdssdk.BucketID) ([]cdssdk.Object, error) {
  185. pkgs, err := s.svc.PackageSvc().GetBucketPackages(1, bktID)
  186. if err != nil {
  187. return nil, err
  188. }
  189. var allObjs []cdssdk.Object
  190. for _, pkg := range pkgs {
  191. objs, err := s.svc.ObjectSvc().GetPackageObjects(1, pkg.PackageID)
  192. if err != nil {
  193. return nil, err
  194. }
  195. allObjs = append(allObjs, objs...)
  196. }
  197. return allObjs, nil
  198. }
  199. type TempGetDatabaseAll struct {
  200. }
  201. type TempGetDatabaseAllResp struct {
  202. Buckets []BucketDetail `json:"buckets"`
  203. Objects []BucketObject `json:"objects"`
  204. Blocks []ObjectBlockDetail `json:"blocks"`
  205. }
  206. type BucketObject struct {
  207. cdssdk.Object
  208. BucketID cdssdk.BucketID `json:"bucketID"`
  209. }
  210. func (s *TempService) GetDatabaseAll(ctx *gin.Context) {
  211. log := logger.WithField("HTTP", "Temp.GetDatabaseAll")
  212. db, err := s.svc.ObjectSvc().GetDatabaseAll()
  213. if err != nil {
  214. log.Warnf("getting database all: %s", err.Error())
  215. ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get database all failed"))
  216. return
  217. }
  218. nodes, err := s.svc.NodeSvc().GetNodes(nil)
  219. if err != nil {
  220. log.Warnf("getting nodes: %s", err.Error())
  221. ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get nodes failed"))
  222. return
  223. }
  224. allNodes := make(map[cdssdk.NodeID]cdssdk.Node)
  225. for _, n := range nodes {
  226. allNodes[n.NodeID] = n
  227. }
  228. bkts := make(map[cdssdk.BucketID]*BucketDetail)
  229. for _, bkt := range db.Buckets {
  230. bkts[bkt.BucketID] = &BucketDetail{
  231. BucketID: bkt.BucketID,
  232. Name: bkt.Name,
  233. ObjectCount: 0,
  234. }
  235. }
  236. type PackageDetail struct {
  237. Package cdssdk.Package
  238. Loaded []cdssdk.Node
  239. }
  240. pkgs := make(map[cdssdk.PackageID]*PackageDetail)
  241. for _, pkg := range db.Packages {
  242. p := PackageDetail{
  243. Package: pkg,
  244. Loaded: make([]cdssdk.Node, 0),
  245. }
  246. loaded, err := s.svc.PackageSvc().GetLoadedNodes(1, pkg.PackageID)
  247. if err != nil {
  248. log.Warnf("getting loaded nodes: %s", err.Error())
  249. ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get loaded nodes failed"))
  250. return
  251. }
  252. for _, nodeID := range loaded {
  253. p.Loaded = append(p.Loaded, allNodes[nodeID])
  254. }
  255. pkgs[pkg.PackageID] = &p
  256. }
  257. var objs []BucketObject
  258. for _, obj := range db.Objects {
  259. o := BucketObject{
  260. Object: obj.Object,
  261. BucketID: pkgs[obj.Object.PackageID].Package.BucketID,
  262. }
  263. objs = append(objs, o)
  264. }
  265. var blocks []ObjectBlockDetail
  266. for _, obj := range db.Objects {
  267. bkts[pkgs[obj.Object.PackageID].Package.BucketID].ObjectCount++
  268. for _, nodeID := range obj.PinnedAt {
  269. blocks = append(blocks, ObjectBlockDetail{
  270. ObjectID: obj.Object.ObjectID,
  271. Type: "Rep",
  272. FileHash: obj.Object.FileHash,
  273. LocationType: "Agent",
  274. LocationName: allNodes[nodeID].Name,
  275. })
  276. }
  277. switch obj.Object.Redundancy.(type) {
  278. case *cdssdk.NoneRedundancy:
  279. for _, blk := range obj.Blocks {
  280. if !lo.Contains(obj.PinnedAt, blk.NodeID) {
  281. blocks = append(blocks, ObjectBlockDetail{
  282. ObjectID: obj.Object.ObjectID,
  283. Type: "Rep",
  284. FileHash: blk.FileHash,
  285. LocationType: "Agent",
  286. LocationName: allNodes[blk.NodeID].Name,
  287. })
  288. }
  289. }
  290. case *cdssdk.RepRedundancy:
  291. for _, blk := range obj.Blocks {
  292. if !lo.Contains(obj.PinnedAt, blk.NodeID) {
  293. blocks = append(blocks, ObjectBlockDetail{
  294. ObjectID: obj.Object.ObjectID,
  295. Type: "Rep",
  296. FileHash: blk.FileHash,
  297. LocationType: "Agent",
  298. LocationName: allNodes[blk.NodeID].Name,
  299. })
  300. }
  301. }
  302. case *cdssdk.ECRedundancy:
  303. for _, blk := range obj.Blocks {
  304. blocks = append(blocks, ObjectBlockDetail{
  305. ObjectID: obj.Object.ObjectID,
  306. Type: "Block",
  307. FileHash: blk.FileHash,
  308. LocationType: "Agent",
  309. LocationName: allNodes[blk.NodeID].Name,
  310. })
  311. }
  312. }
  313. for _, node := range pkgs[obj.Object.PackageID].Loaded {
  314. blocks = append(blocks, ObjectBlockDetail{
  315. ObjectID: obj.Object.ObjectID,
  316. Type: "Rep",
  317. FileHash: obj.Object.FileHash,
  318. LocationType: "Storage",
  319. LocationName: allNodes[node.NodeID].Name,
  320. })
  321. }
  322. }
  323. ctx.JSON(http.StatusOK, OK(TempGetDatabaseAllResp{
  324. Buckets: lo.Map(lo.Values(bkts), func(b *BucketDetail, _ int) BucketDetail { return *b }),
  325. Objects: objs,
  326. Blocks: blocks,
  327. }))
  328. }
  329. func auth(ctx *gin.Context) {
  330. token := ctx.Request.Header.Get("X-CDS-Auth")
  331. if token != "cloudream@123" {
  332. ctx.AbortWithStatus(http.StatusUnauthorized)
  333. }
  334. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。