yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/hcs/bucket.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package hcs 16 17 import ( 18 "context" 19 "fmt" 20 "io" 21 "net/http" 22 "strconv" 23 "strings" 24 "time" 25 26 "github.com/huaweicloud/huaweicloud-sdk-go-obs/obs" 27 28 "yunion.io/x/jsonutils" 29 "yunion.io/x/log" 30 "yunion.io/x/pkg/errors" 31 "yunion.io/x/pkg/utils" 32 "yunion.io/x/s3cli" 33 34 "yunion.io/x/cloudmux/pkg/cloudprovider" 35 "yunion.io/x/cloudmux/pkg/multicloud" 36 "yunion.io/x/cloudmux/pkg/multicloud/huawei" 37 ) 38 39 type SBucket struct { 40 multicloud.SBaseBucket 41 huawei.HuaweiTags 42 43 region *SRegion 44 45 Name string 46 Location string 47 CreationDate time.Time 48 } 49 50 func (b *SBucket) GetProjectId() string { 51 resp, err := b.region.HeadBucket(b.Name) 52 if err != nil { 53 return "" 54 } 55 epid, _ := resp.ResponseHeaders["epid"] 56 if len(epid) > 0 { 57 return epid[0] 58 } 59 return "" 60 } 61 62 func (b *SBucket) GetGlobalId() string { 63 return b.Name 64 } 65 66 func (b *SBucket) GetName() string { 67 return b.Name 68 } 69 70 func (b *SBucket) GetLocation() string { 71 return b.Location 72 } 73 74 func (b *SBucket) GetIRegion() cloudprovider.ICloudRegion { 75 return b.region 76 } 77 78 func (b *SBucket) GetCreateAt() time.Time { 79 return b.CreationDate 80 } 81 82 func (b *SBucket) GetStorageClass() string { 83 obscli, err := b.region.getOBSClient() 84 if err != nil { 85 log.Errorf("b.region.getOBSClient error %s", err) 86 return "" 87 } 88 output, err := obscli.GetBucketStoragePolicy(b.Name) 89 if err != nil { 90 log.Errorf("obscli.GetBucketStoragePolicy error %s", err) 91 return "" 92 } 93 return output.StorageClass 94 } 95 96 func obsAcl2CannedAcl(acls []obs.Grant) cloudprovider.TBucketACLType { 97 switch { 98 case len(acls) == 1: 99 if acls[0].Grantee.URI == "" && acls[0].Permission == s3cli.PERMISSION_FULL_CONTROL { 100 return cloudprovider.ACLPrivate 101 } 102 case len(acls) == 2: 103 for _, g := range acls { 104 if g.Grantee.URI == s3cli.GRANTEE_GROUP_URI_AUTH_USERS && g.Permission == s3cli.PERMISSION_READ { 105 return cloudprovider.ACLAuthRead 106 } 107 if g.Grantee.URI == s3cli.GRANTEE_GROUP_URI_ALL_USERS && g.Permission == s3cli.PERMISSION_READ { 108 return cloudprovider.ACLPublicRead 109 } 110 } 111 case len(acls) == 3: 112 for _, g := range acls { 113 if g.Grantee.URI == s3cli.GRANTEE_GROUP_URI_ALL_USERS && g.Permission == s3cli.PERMISSION_WRITE { 114 return cloudprovider.ACLPublicReadWrite 115 } 116 } 117 } 118 return cloudprovider.ACLUnknown 119 } 120 121 func (b *SBucket) GetAcl() cloudprovider.TBucketACLType { 122 acl := cloudprovider.ACLPrivate 123 obscli, err := b.region.getOBSClient() 124 if err != nil { 125 log.Errorf("b.region.getOBSClient error %s", err) 126 return acl 127 } 128 output, err := obscli.GetBucketAcl(b.Name) 129 if err != nil { 130 log.Errorf("obscli.GetBucketAcl error %s", err) 131 return acl 132 } 133 acl = obsAcl2CannedAcl(output.Grants) 134 return acl 135 } 136 137 func (b *SBucket) SetAcl(acl cloudprovider.TBucketACLType) error { 138 obscli, err := b.region.getOBSClient() 139 if err != nil { 140 return errors.Wrap(err, "b.region.getOBSClient") 141 } 142 input := &obs.SetBucketAclInput{} 143 input.Bucket = b.Name 144 input.ACL = obs.AclType(string(acl)) 145 _, err = obscli.SetBucketAcl(input) 146 if err != nil { 147 return errors.Wrap(err, "obscli.SetBucketAcl") 148 } 149 return nil 150 } 151 152 func (b *SBucket) GetAccessUrls() []cloudprovider.SBucketAccessUrl { 153 return []cloudprovider.SBucketAccessUrl{ 154 { 155 Url: fmt.Sprintf("https://%s.%s", b.Name, b.region.getOBSEndpoint()), 156 Description: "bucket url", 157 Primary: true, 158 }, 159 { 160 Url: fmt.Sprintf("https://%s/%s", b.region.getOBSEndpoint(), b.Name), 161 Description: "obs url", 162 }, 163 } 164 } 165 166 func (b *SBucket) GetStats() cloudprovider.SBucketStats { 167 stats := cloudprovider.SBucketStats{} 168 obscli, err := b.region.getOBSClient() 169 if err != nil { 170 log.Errorf("b.region.getOBSClient error %s", err) 171 stats.SizeBytes = -1 172 stats.ObjectCount = -1 173 return stats 174 } 175 output, err := obscli.GetBucketStorageInfo(b.Name) 176 if err != nil { 177 log.Errorf("obscli.GetBucketStorageInfo error %s", err) 178 stats.SizeBytes = -1 179 stats.ObjectCount = -1 180 return stats 181 } 182 stats.SizeBytes = output.Size 183 stats.ObjectCount = output.ObjectNumber 184 return stats 185 } 186 187 func (b *SBucket) ListObjects(prefix string, marker string, delimiter string, maxCount int) (cloudprovider.SListObjectResult, error) { 188 result := cloudprovider.SListObjectResult{} 189 obscli, err := b.region.getOBSClient() 190 if err != nil { 191 return result, errors.Wrap(err, "GetOBSClient") 192 } 193 input := &obs.ListObjectsInput{} 194 input.Bucket = b.Name 195 if len(prefix) > 0 { 196 input.Prefix = prefix 197 } 198 if len(marker) > 0 { 199 input.Marker = marker 200 } 201 if len(delimiter) > 0 { 202 input.Delimiter = delimiter 203 } 204 if maxCount > 0 { 205 input.MaxKeys = maxCount 206 } 207 oResult, err := obscli.ListObjects(input) 208 if err != nil { 209 return result, errors.Wrap(err, "ListObjects") 210 } 211 result.Objects = make([]cloudprovider.ICloudObject, 0) 212 for _, object := range oResult.Contents { 213 obj := &SObject{ 214 bucket: b, 215 SBaseCloudObject: cloudprovider.SBaseCloudObject{ 216 StorageClass: string(object.StorageClass), 217 Key: object.Key, 218 SizeBytes: object.Size, 219 ETag: object.ETag, 220 LastModified: object.LastModified, 221 }, 222 } 223 result.Objects = append(result.Objects, obj) 224 } 225 if oResult.CommonPrefixes != nil { 226 result.CommonPrefixes = make([]cloudprovider.ICloudObject, 0) 227 for _, commonPrefix := range oResult.CommonPrefixes { 228 obj := &SObject{ 229 bucket: b, 230 SBaseCloudObject: cloudprovider.SBaseCloudObject{ 231 Key: commonPrefix, 232 }, 233 } 234 result.CommonPrefixes = append(result.CommonPrefixes, obj) 235 } 236 } 237 result.IsTruncated = oResult.IsTruncated 238 result.NextMarker = oResult.NextMarker 239 return result, nil 240 } 241 242 func (b *SBucket) PutObject(ctx context.Context, key string, reader io.Reader, sizeBytes int64, cannedAcl cloudprovider.TBucketACLType, storageClassStr string, meta http.Header) error { 243 obscli, err := b.region.getOBSClient() 244 if err != nil { 245 return errors.Wrap(err, "GetOBSClient") 246 } 247 input := &obs.PutObjectInput{} 248 input.Bucket = b.Name 249 input.Key = key 250 input.Body = reader 251 252 if sizeBytes > 0 { 253 input.ContentLength = sizeBytes 254 } 255 if len(storageClassStr) > 0 { 256 input.StorageClass, err = str2StorageClass(storageClassStr) 257 if err != nil { 258 return err 259 } 260 } 261 if len(cannedAcl) == 0 { 262 cannedAcl = b.GetAcl() 263 } 264 input.ACL = obs.AclType(string(cannedAcl)) 265 if meta != nil { 266 val := meta.Get(cloudprovider.META_HEADER_CONTENT_TYPE) 267 if len(val) > 0 { 268 input.ContentType = val 269 } 270 val = meta.Get(cloudprovider.META_HEADER_CONTENT_MD5) 271 if len(val) > 0 { 272 input.ContentMD5 = val 273 } 274 extraMeta := make(map[string]string) 275 for k, v := range meta { 276 if utils.IsInStringArray(k, []string{ 277 cloudprovider.META_HEADER_CONTENT_TYPE, 278 cloudprovider.META_HEADER_CONTENT_MD5, 279 }) { 280 continue 281 } 282 if len(v[0]) > 0 { 283 extraMeta[k] = v[0] 284 } 285 } 286 input.Metadata = extraMeta 287 } 288 _, err = obscli.PutObject(input) 289 if err != nil { 290 return errors.Wrap(err, "PutObject") 291 } 292 return nil 293 } 294 295 func (b *SBucket) NewMultipartUpload(ctx context.Context, key string, cannedAcl cloudprovider.TBucketACLType, storageClassStr string, meta http.Header) (string, error) { 296 obscli, err := b.region.getOBSClient() 297 if err != nil { 298 return "", errors.Wrap(err, "GetOBSClient") 299 } 300 301 input := &obs.InitiateMultipartUploadInput{} 302 input.Bucket = b.Name 303 input.Key = key 304 if meta != nil { 305 val := meta.Get(cloudprovider.META_HEADER_CONTENT_TYPE) 306 if len(val) > 0 { 307 input.ContentType = val 308 } 309 extraMeta := make(map[string]string) 310 for k, v := range meta { 311 if utils.IsInStringArray(k, []string{ 312 cloudprovider.META_HEADER_CONTENT_TYPE, 313 }) { 314 continue 315 } 316 if len(v[0]) > 0 { 317 extraMeta[k] = v[0] 318 } 319 } 320 input.Metadata = extraMeta 321 } 322 if len(cannedAcl) == 0 { 323 cannedAcl = b.GetAcl() 324 } 325 input.ACL = obs.AclType(string(cannedAcl)) 326 if len(storageClassStr) > 0 { 327 input.StorageClass, err = str2StorageClass(storageClassStr) 328 if err != nil { 329 return "", errors.Wrap(err, "str2StorageClass") 330 } 331 } 332 output, err := obscli.InitiateMultipartUpload(input) 333 if err != nil { 334 return "", errors.Wrap(err, "InitiateMultipartUpload") 335 } 336 337 return output.UploadId, nil 338 } 339 340 func (b *SBucket) UploadPart(ctx context.Context, key string, uploadId string, partIndex int, part io.Reader, partSize int64, offset, totalSize int64) (string, error) { 341 obscli, err := b.region.getOBSClient() 342 if err != nil { 343 return "", errors.Wrap(err, "GetOBSClient") 344 } 345 346 input := &obs.UploadPartInput{} 347 input.Bucket = b.Name 348 input.Key = key 349 input.UploadId = uploadId 350 input.PartNumber = partIndex 351 input.PartSize = partSize 352 input.Body = part 353 output, err := obscli.UploadPart(input) 354 if err != nil { 355 return "", errors.Wrap(err, "UploadPart") 356 } 357 358 return output.ETag, nil 359 } 360 361 func (b *SBucket) CompleteMultipartUpload(ctx context.Context, key string, uploadId string, partEtags []string) error { 362 obscli, err := b.region.getOBSClient() 363 if err != nil { 364 return errors.Wrap(err, "GetOBSClient") 365 } 366 input := &obs.CompleteMultipartUploadInput{} 367 input.Bucket = b.Name 368 input.Key = key 369 input.UploadId = uploadId 370 parts := make([]obs.Part, len(partEtags)) 371 for i := range partEtags { 372 parts[i] = obs.Part{ 373 PartNumber: i + 1, 374 ETag: partEtags[i], 375 } 376 } 377 input.Parts = parts 378 _, err = obscli.CompleteMultipartUpload(input) 379 if err != nil { 380 return errors.Wrap(err, "CompleteMultipartUpload") 381 } 382 383 return nil 384 } 385 386 func (b *SBucket) AbortMultipartUpload(ctx context.Context, key string, uploadId string) error { 387 obscli, err := b.region.getOBSClient() 388 if err != nil { 389 return errors.Wrap(err, "GetOBSClient") 390 } 391 392 input := &obs.AbortMultipartUploadInput{} 393 input.Bucket = b.Name 394 input.Key = key 395 input.UploadId = uploadId 396 397 _, err = obscli.AbortMultipartUpload(input) 398 if err != nil { 399 return errors.Wrap(err, "AbortMultipartUpload") 400 } 401 402 return nil 403 } 404 405 func (b *SBucket) DeleteObject(ctx context.Context, key string) error { 406 obscli, err := b.region.getOBSClient() 407 if err != nil { 408 return errors.Wrap(err, "GetOBSClient") 409 } 410 input := &obs.DeleteObjectInput{} 411 input.Bucket = b.Name 412 input.Key = key 413 _, err = obscli.DeleteObject(input) 414 if err != nil { 415 return errors.Wrap(err, "DeleteObject") 416 } 417 return nil 418 } 419 420 func (b *SBucket) GetTempUrl(method string, key string, expire time.Duration) (string, error) { 421 obscli, err := b.region.getOBSClient() 422 if err != nil { 423 return "", errors.Wrap(err, "GetOBSClient") 424 } 425 input := obs.CreateSignedUrlInput{} 426 input.Bucket = b.Name 427 input.Key = key 428 input.Expires = int(expire / time.Second) 429 switch method { 430 case "GET": 431 input.Method = obs.HttpMethodGet 432 case "PUT": 433 input.Method = obs.HttpMethodPut 434 case "DELETE": 435 input.Method = obs.HttpMethodDelete 436 default: 437 return "", errors.Error("unsupported method") 438 } 439 output, err := obscli.CreateSignedUrl(&input) 440 return output.SignedUrl, nil 441 } 442 443 func (b *SBucket) LimitSupport() cloudprovider.SBucketStats { 444 return cloudprovider.SBucketStats{ 445 SizeBytes: 1, 446 ObjectCount: -1, 447 } 448 } 449 450 func (b *SBucket) GetLimit() cloudprovider.SBucketStats { 451 stats := cloudprovider.SBucketStats{} 452 obscli, err := b.region.getOBSClient() 453 if err != nil { 454 log.Errorf("getOBSClient error %s", err) 455 return stats 456 } 457 output, err := obscli.GetBucketQuota(b.Name) 458 if err != nil { 459 return stats 460 } 461 stats.SizeBytes = output.Quota 462 return stats 463 } 464 465 func (b *SBucket) SetLimit(limit cloudprovider.SBucketStats) error { 466 obscli, err := b.region.getOBSClient() 467 if err != nil { 468 return errors.Wrap(err, "getOBSClient") 469 } 470 input := &obs.SetBucketQuotaInput{} 471 input.Bucket = b.Name 472 input.Quota = limit.SizeBytes 473 _, err = obscli.SetBucketQuota(input) 474 if err != nil { 475 return errors.Wrap(err, "SetBucketQuota") 476 } 477 return nil 478 } 479 480 func (b *SBucket) CopyObject(ctx context.Context, destKey string, srcBucket, srcKey string, cannedAcl cloudprovider.TBucketACLType, storageClassStr string, meta http.Header) error { 481 obscli, err := b.region.getOBSClient() 482 if err != nil { 483 return errors.Wrap(err, "GetOBSClient") 484 } 485 input := &obs.CopyObjectInput{} 486 input.Bucket = b.Name 487 input.Key = destKey 488 input.CopySourceBucket = srcBucket 489 input.CopySourceKey = srcKey 490 if len(storageClassStr) > 0 { 491 input.StorageClass, err = str2StorageClass(storageClassStr) 492 if err != nil { 493 return err 494 } 495 } 496 if len(cannedAcl) == 0 { 497 cannedAcl = b.GetAcl() 498 } 499 input.ACL = obs.AclType(string(cannedAcl)) 500 if meta != nil { 501 val := meta.Get(cloudprovider.META_HEADER_CONTENT_TYPE) 502 if len(val) > 0 { 503 input.ContentType = val 504 } 505 extraMeta := make(map[string]string) 506 for k, v := range meta { 507 if utils.IsInStringArray(k, []string{ 508 cloudprovider.META_HEADER_CONTENT_TYPE, 509 }) { 510 continue 511 } 512 if len(v[0]) > 0 { 513 extraMeta[k] = v[0] 514 } 515 } 516 input.Metadata = extraMeta 517 input.MetadataDirective = obs.ReplaceMetadata 518 } else { 519 input.MetadataDirective = obs.CopyMetadata 520 } 521 _, err = obscli.CopyObject(input) 522 if err != nil { 523 return errors.Wrap(err, "obscli.CopyObject") 524 } 525 return nil 526 } 527 528 func (b *SBucket) GetObject(ctx context.Context, key string, rangeOpt *cloudprovider.SGetObjectRange) (io.ReadCloser, error) { 529 obscli, err := b.region.getOBSClient() 530 if err != nil { 531 return nil, errors.Wrap(err, "GetOBSClient") 532 } 533 input := &obs.GetObjectInput{} 534 input.Bucket = b.Name 535 input.Key = key 536 if rangeOpt != nil { 537 input.RangeStart = rangeOpt.Start 538 input.RangeEnd = rangeOpt.End 539 } 540 output, err := obscli.GetObject(input) 541 if err != nil { 542 return nil, errors.Wrap(err, "obscli.GetObject") 543 } 544 return output.Body, nil 545 } 546 547 func (b *SBucket) CopyPart(ctx context.Context, key string, uploadId string, partIndex int, srcBucket string, srcKey string, srcOffset int64, srcLength int64) (string, error) { 548 obscli, err := b.region.getOBSClient() 549 if err != nil { 550 return "", errors.Wrap(err, "GetOBSClient") 551 } 552 input := &obs.CopyPartInput{} 553 input.Bucket = b.Name 554 input.Key = key 555 input.UploadId = uploadId 556 input.PartNumber = partIndex 557 input.CopySourceBucket = srcBucket 558 input.CopySourceKey = srcKey 559 input.CopySourceRangeStart = srcOffset 560 input.CopySourceRangeEnd = srcOffset + srcLength - 1 561 output, err := obscli.CopyPart(input) 562 if err != nil { 563 return "", errors.Wrap(err, "CopyPart") 564 } 565 return output.ETag, nil 566 } 567 568 func (b *SBucket) SetWebsite(websitConf cloudprovider.SBucketWebsiteConf) error { 569 obscli, err := b.region.getOBSClient() 570 if err != nil { 571 return errors.Wrap(err, "GetOBSClient") 572 } 573 574 obsWebConf := obs.SetBucketWebsiteConfigurationInput{} 575 obsWebConf.Bucket = b.Name 576 obsWebConf.BucketWebsiteConfiguration = obs.BucketWebsiteConfiguration{ 577 IndexDocument: obs.IndexDocument{Suffix: websitConf.Index}, 578 ErrorDocument: obs.ErrorDocument{Key: websitConf.ErrorDocument}, 579 } 580 _, err = obscli.SetBucketWebsiteConfiguration(&obsWebConf) 581 if err != nil { 582 return errors.Wrap(err, "obscli.SetBucketWebsiteConfiguration(&obsWebConf)") 583 } 584 return nil 585 } 586 587 func (b *SBucket) GetWebsiteConf() (cloudprovider.SBucketWebsiteConf, error) { 588 result := cloudprovider.SBucketWebsiteConf{} 589 obscli, err := b.region.getOBSClient() 590 if err != nil { 591 return result, errors.Wrap(err, "GetOBSClient") 592 } 593 out, err := obscli.GetBucketWebsiteConfiguration(b.Name) 594 if out == nil { 595 return result, nil 596 } 597 result.Index = out.IndexDocument.Suffix 598 result.ErrorDocument = out.ErrorDocument.Key 599 result.Url = fmt.Sprintf("https://%s.obs-website.%s.myhuaweicloud.com", b.Name, b.region.GetId()) 600 return result, nil 601 } 602 603 func (b *SBucket) DeleteWebSiteConf() error { 604 obscli, err := b.region.getOBSClient() 605 if err != nil { 606 return errors.Wrap(err, "GetOBSClient") 607 } 608 _, err = obscli.DeleteBucketWebsiteConfiguration(b.Name) 609 if err != nil { 610 return errors.Wrapf(err, "obscli.DeleteBucketWebsiteConfiguration(%s)", b.Name) 611 } 612 return nil 613 } 614 615 func (b *SBucket) SetCORS(rules []cloudprovider.SBucketCORSRule) error { 616 obscli, err := b.region.getOBSClient() 617 if err != nil { 618 return errors.Wrap(err, "GetOBSClient") 619 } 620 opts := []obs.CorsRule{} 621 for i := range rules { 622 opts = append(opts, obs.CorsRule{ 623 AllowedOrigin: rules[i].AllowedOrigins, 624 AllowedMethod: rules[i].AllowedMethods, 625 AllowedHeader: rules[i].AllowedHeaders, 626 MaxAgeSeconds: rules[i].MaxAgeSeconds, 627 ExposeHeader: rules[i].ExposeHeaders, 628 }) 629 } 630 631 input := obs.SetBucketCorsInput{} 632 input.Bucket = b.Name 633 input.BucketCors.CorsRules = opts 634 _, err = obscli.SetBucketCors(&input) 635 if err != nil { 636 return errors.Wrapf(err, "obscli.SetBucketCors(%s)", jsonutils.Marshal(input).String()) 637 } 638 return nil 639 } 640 641 func (b *SBucket) GetCORSRules() ([]cloudprovider.SBucketCORSRule, error) { 642 obscli, err := b.region.getOBSClient() 643 if err != nil { 644 return nil, errors.Wrap(err, "GetOBSClient") 645 } 646 conf, err := obscli.GetBucketCors(b.Name) 647 if err != nil { 648 if !strings.Contains(err.Error(), "NoSuchCORSConfiguration") { 649 return nil, errors.Wrapf(err, "obscli.GetBucketCors(%s)", b.Name) 650 } 651 } 652 if conf == nil { 653 return nil, nil 654 } 655 result := []cloudprovider.SBucketCORSRule{} 656 for i := range conf.CorsRules { 657 result = append(result, cloudprovider.SBucketCORSRule{ 658 AllowedOrigins: conf.CorsRules[i].AllowedOrigin, 659 AllowedMethods: conf.CorsRules[i].AllowedMethod, 660 AllowedHeaders: conf.CorsRules[i].AllowedHeader, 661 MaxAgeSeconds: conf.CorsRules[i].MaxAgeSeconds, 662 ExposeHeaders: conf.CorsRules[i].ExposeHeader, 663 Id: strconv.Itoa(i), 664 }) 665 } 666 return result, nil 667 } 668 669 func (b *SBucket) DeleteCORS() error { 670 obscli, err := b.region.getOBSClient() 671 if err != nil { 672 return errors.Wrap(err, "GetOBSClient") 673 } 674 675 _, err = obscli.DeleteBucketCors(b.Name) 676 if err != nil { 677 return errors.Wrapf(err, "obscli.DeleteBucketCors(%s)", b.Name) 678 } 679 return nil 680 } 681 682 func (b *SBucket) GetTags() (map[string]string, error) { 683 obscli, err := b.region.getOBSClient() 684 if err != nil { 685 return nil, errors.Wrap(err, "GetOBSClient") 686 } 687 tagresult, err := obscli.GetBucketTagging(b.Name) 688 if err != nil { 689 if strings.Contains(err.Error(), "404") { 690 return nil, nil 691 } 692 return nil, errors.Wrapf(err, "osscli.GetBucketTagging(%s)", b.Name) 693 } 694 result := map[string]string{} 695 for i := range tagresult.Tags { 696 result[tagresult.Tags[i].Key] = tagresult.Tags[i].Value 697 } 698 return result, nil 699 } 700 701 func (b *SBucket) SetTags(tags map[string]string, replace bool) error { 702 obscli, err := b.region.getOBSClient() 703 if err != nil { 704 return errors.Wrap(err, "GetOBSClient") 705 } 706 707 _, err = obscli.DeleteBucketTagging(b.Name) 708 if err != nil { 709 return errors.Wrapf(err, "DeleteBucketTagging") 710 } 711 712 if len(tags) == 0 { 713 return nil 714 } 715 716 input := obs.SetBucketTaggingInput{BucketTagging: obs.BucketTagging{}} 717 input.Bucket = b.Name 718 for k, v := range tags { 719 input.BucketTagging.Tags = append(input.BucketTagging.Tags, obs.Tag{Key: k, Value: v}) 720 } 721 722 _, err = obscli.SetBucketTagging(&input) 723 if err != nil { 724 return errors.Wrapf(err, "obscli.SetBucketTagging(%s)", jsonutils.Marshal(input).String()) 725 } 726 return nil 727 } 728 729 func (b *SBucket) ListMultipartUploads() ([]cloudprovider.SBucketMultipartUploads, error) { 730 obscli, err := b.region.getOBSClient() 731 if err != nil { 732 return nil, errors.Wrap(err, "GetOBSClient") 733 } 734 result := []cloudprovider.SBucketMultipartUploads{} 735 736 input := obs.ListMultipartUploadsInput{Bucket: b.Name} 737 keyMarker := "" 738 uploadIDMarker := "" 739 for { 740 if len(keyMarker) > 0 { 741 input.KeyMarker = keyMarker 742 } 743 if len(uploadIDMarker) > 0 { 744 input.UploadIdMarker = uploadIDMarker 745 } 746 747 output, err := obscli.ListMultipartUploads(&input) 748 if err != nil { 749 return nil, errors.Wrap(err, " coscli.Bucket.ListMultipartUploads(context.Background(), &input)") 750 } 751 for i := range output.Uploads { 752 temp := cloudprovider.SBucketMultipartUploads{ 753 ObjectName: output.Uploads[i].Key, 754 UploadID: output.Uploads[i].UploadId, 755 Initiator: output.Uploads[i].Initiator.DisplayName, 756 Initiated: output.Uploads[i].Initiated, 757 } 758 result = append(result, temp) 759 } 760 keyMarker = output.NextKeyMarker 761 uploadIDMarker = output.NextUploadIdMarker 762 if !output.IsTruncated { 763 break 764 } 765 } 766 767 return result, nil 768 } 769 770 func (self *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error { 771 return self.CreateBucket(name, storageClassStr, aclStr) 772 } 773 774 func (self *SRegion) CreateBucket(name string, storageClassStr string, aclStr string) error { 775 obsClient, err := self.getOBSClient() 776 if err != nil { 777 return errors.Wrap(err, "self.getOBSClient") 778 } 779 input := &obs.CreateBucketInput{} 780 input.Bucket = name 781 input.Location = self.GetId() 782 if len(aclStr) > 0 { 783 if strings.EqualFold(aclStr, string(obs.AclPrivate)) { 784 input.ACL = obs.AclPrivate 785 } else if strings.EqualFold(aclStr, string(obs.AclPublicRead)) { 786 input.ACL = obs.AclPublicRead 787 } else if strings.EqualFold(aclStr, string(obs.AclPublicReadWrite)) { 788 input.ACL = obs.AclPublicReadWrite 789 } else { 790 return errors.Error("unsupported acl") 791 } 792 } 793 if len(storageClassStr) > 0 { 794 input.StorageClass, err = str2StorageClass(storageClassStr) 795 if err != nil { 796 return err 797 } 798 } 799 _, err = obsClient.CreateBucket(input) 800 if err != nil { 801 return errors.Wrap(err, "obsClient.CreateBucket") 802 } 803 return nil 804 }