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.

239 lines
6.7 KiB

5 months ago
5 months ago
  1. package s3api
  2. import (
  3. "encoding/json"
  4. "github.com/aws/aws-sdk-go/service/s3"
  5. "github.com/seaweedfs/seaweedfs/weed/glog"
  6. "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
  7. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
  8. "github.com/seaweedfs/seaweedfs/weed/s3api/s3acl"
  9. "github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
  10. "github.com/seaweedfs/seaweedfs/weed/util"
  11. "math"
  12. "sync"
  13. )
  14. var loadBucketMetadataFromFiler = func(r *BucketRegistry, bucketName string) (*BucketMetaData, error) {
  15. entry, err := filer_pb.GetEntry(r.s3a, util.NewFullPath(r.s3a.option.BucketsPath, bucketName))
  16. if err != nil {
  17. return nil, err
  18. }
  19. return buildBucketMetadata(r.s3a.iam, entry), nil
  20. }
  21. type BucketMetaData struct {
  22. _ struct{} `type:"structure"`
  23. Name string
  24. //By default, when another AWS account uploads an object to S3 bucket,
  25. //that account (the object writer) owns the object, has access to it, and
  26. //can grant other users access to it through ACLs. You can use Object Ownership
  27. //to change this default behavior so that ACLs are disabled and you, as the
  28. //bucket owner, automatically own every object in your bucket.
  29. ObjectOwnership string
  30. // Container for the bucket owner's display name and ID.
  31. Owner *s3.Owner `type:"structure"`
  32. // A list of grants for access controls.
  33. Acl []*s3.Grant `locationName:"AccessControlList" locationNameList:"Grant" type:"list"`
  34. }
  35. type BucketRegistry struct {
  36. metadataCache map[string]*BucketMetaData
  37. metadataCacheLock sync.RWMutex
  38. notFound map[string]struct{}
  39. notFoundLock sync.RWMutex
  40. s3a *S3ApiServer
  41. }
  42. func NewBucketRegistry(s3a *S3ApiServer) *BucketRegistry {
  43. br := &BucketRegistry{
  44. metadataCache: make(map[string]*BucketMetaData),
  45. notFound: make(map[string]struct{}),
  46. s3a: s3a,
  47. }
  48. err := br.init()
  49. if err != nil {
  50. glog.Fatal("init bucket registry failed", err)
  51. return nil
  52. }
  53. return br
  54. }
  55. func (r *BucketRegistry) init() error {
  56. err := filer_pb.List(r.s3a, r.s3a.option.BucketsPath, "", func(entry *filer_pb.Entry, isLast bool) error {
  57. r.LoadBucketMetadata(entry)
  58. return nil
  59. }, "", false, math.MaxUint32)
  60. return err
  61. }
  62. func (r *BucketRegistry) LoadBucketMetadata(entry *filer_pb.Entry) {
  63. bucketMetadata := buildBucketMetadata(r.s3a.iam, entry)
  64. r.metadataCacheLock.Lock()
  65. defer r.metadataCacheLock.Unlock()
  66. r.metadataCache[entry.Name] = bucketMetadata
  67. }
  68. func buildBucketMetadata(accountManager s3acl.AccountManager, entry *filer_pb.Entry) *BucketMetaData {
  69. entryJson, _ := json.Marshal(entry)
  70. glog.V(3).Infof("build bucket metadata,entry=%s", entryJson)
  71. bucketMetadata := &BucketMetaData{
  72. Name: entry.Name,
  73. //Default ownership: OwnershipBucketOwnerEnforced, which means Acl is disabled
  74. ObjectOwnership: s3_constants.OwnershipBucketOwnerEnforced,
  75. // Default owner: `AccountAdmin`
  76. Owner: &s3.Owner{
  77. ID: &AccountAdmin.Id,
  78. DisplayName: &AccountAdmin.DisplayName,
  79. },
  80. }
  81. if entry.Extended != nil {
  82. //ownership control
  83. ownership, ok := entry.Extended[s3_constants.ExtOwnershipKey]
  84. if ok {
  85. ownership := string(ownership)
  86. valid := s3_constants.ValidateOwnership(ownership)
  87. if valid {
  88. bucketMetadata.ObjectOwnership = ownership
  89. } else {
  90. glog.Warningf("Invalid ownership: %s, bucket: %s", ownership, bucketMetadata.Name)
  91. }
  92. }
  93. //owner
  94. acpOwnerBytes, ok := entry.Extended[s3_constants.ExtAmzOwnerKey]
  95. if ok && len(acpOwnerBytes) > 0 {
  96. ownerAccountId := string(acpOwnerBytes)
  97. ownerAccountName := accountManager.GetAccountNameById(ownerAccountId)
  98. if ownerAccountName == "" {
  99. glog.Warningf("owner[id=%s] is invalid, bucket: %s", ownerAccountId, bucketMetadata.Name)
  100. } else {
  101. bucketMetadata.Owner = &s3.Owner{
  102. ID: &ownerAccountId,
  103. DisplayName: &ownerAccountName,
  104. }
  105. }
  106. }
  107. //grants
  108. acpGrantsBytes, ok := entry.Extended[s3_constants.ExtAmzAclKey]
  109. if ok {
  110. if len(acpGrantsBytes) > 0 {
  111. var grants []*s3.Grant
  112. err := json.Unmarshal(acpGrantsBytes, &grants)
  113. if err == nil {
  114. bucketMetadata.Acl = grants
  115. } else {
  116. glog.Warningf("Unmarshal ACP grants: %s(%v), bucket: %s", string(acpGrantsBytes), err, bucketMetadata.Name)
  117. }
  118. }
  119. } else {
  120. bucketMetadata.Acl = []*s3.Grant{
  121. {
  122. Grantee: &s3.Grantee{
  123. Type: &s3_constants.GrantTypeCanonicalUser,
  124. ID: bucketMetadata.Owner.ID,
  125. },
  126. Permission: &s3_constants.PermissionFullControl,
  127. },
  128. }
  129. }
  130. }
  131. return bucketMetadata
  132. }
  133. func (r *BucketRegistry) RemoveBucketMetadata(entry *filer_pb.Entry) {
  134. r.removeMetadataCache(entry.Name)
  135. r.unMarkNotFound(entry.Name)
  136. }
  137. func (r *BucketRegistry) GetBucketMetadata(bucketName string) (*BucketMetaData, s3err.ErrorCode) {
  138. bucketMetadata := r.getMetadataCache(bucketName)
  139. if bucketMetadata != nil {
  140. return bucketMetadata, s3err.ErrNone
  141. }
  142. if r.isNotFound(bucketName) {
  143. return nil, s3err.ErrNoSuchBucket
  144. }
  145. bucketMetadata, errCode := r.LoadBucketMetadataFromFiler(bucketName)
  146. if errCode != s3err.ErrNone {
  147. return nil, errCode
  148. }
  149. r.setMetadataCache(bucketMetadata)
  150. r.unMarkNotFound(bucketName)
  151. return bucketMetadata, s3err.ErrNone
  152. }
  153. func (r *BucketRegistry) LoadBucketMetadataFromFiler(bucketName string) (*BucketMetaData, s3err.ErrorCode) {
  154. r.notFoundLock.Lock()
  155. defer r.notFoundLock.Unlock()
  156. //check if already exists
  157. bucketMetaData := r.getMetadataCache(bucketName)
  158. if bucketMetaData != nil {
  159. return bucketMetaData, s3err.ErrNone
  160. }
  161. //if not exists, load from filer
  162. bucketMetadata, err := loadBucketMetadataFromFiler(r, bucketName)
  163. if err != nil {
  164. if err == filer_pb.ErrNotFound {
  165. // The bucket doesn't actually exist and should no longer loaded from the filer
  166. glog.V(4).Info("bucket not found in filer: ", bucketName)
  167. r.notFound[bucketName] = struct{}{}
  168. return nil, s3err.ErrNoSuchBucket
  169. }
  170. return nil, s3err.ErrInternalError
  171. }
  172. return bucketMetadata, s3err.ErrNone
  173. }
  174. func (r *BucketRegistry) getMetadataCache(bucket string) *BucketMetaData {
  175. r.metadataCacheLock.RLock()
  176. defer r.metadataCacheLock.RUnlock()
  177. if cache, ok := r.metadataCache[bucket]; ok {
  178. return cache
  179. }
  180. return nil
  181. }
  182. func (r *BucketRegistry) setMetadataCache(metadata *BucketMetaData) {
  183. r.metadataCacheLock.Lock()
  184. defer r.metadataCacheLock.Unlock()
  185. r.metadataCache[metadata.Name] = metadata
  186. }
  187. func (r *BucketRegistry) removeMetadataCache(bucket string) {
  188. r.metadataCacheLock.Lock()
  189. defer r.metadataCacheLock.Unlock()
  190. delete(r.metadataCache, bucket)
  191. }
  192. func (r *BucketRegistry) isNotFound(bucket string) bool {
  193. r.notFoundLock.RLock()
  194. defer r.notFoundLock.RUnlock()
  195. _, ok := r.notFound[bucket]
  196. return ok
  197. }
  198. func (r *BucketRegistry) unMarkNotFound(bucket string) {
  199. r.notFoundLock.Lock()
  200. defer r.notFoundLock.Unlock()
  201. delete(r.notFound, bucket)
  202. }
  203. func (r *BucketRegistry) ClearCache(bucket string) {
  204. r.removeMetadataCache(bucket)
  205. r.unMarkNotFound(bucket)
  206. }