mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-21 14:19:49 +08:00
feature: s3gateway
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SBucket struct {
|
||||
region *SRegion
|
||||
|
||||
Name string
|
||||
Location string
|
||||
CreationDate time.Time
|
||||
StorageClass string
|
||||
Acl string
|
||||
}
|
||||
|
||||
func (b *SBucket) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *SBucket) GetGlobalId() string {
|
||||
return b.Name
|
||||
}
|
||||
|
||||
func (b *SBucket) GetName() string {
|
||||
return b.Name
|
||||
}
|
||||
|
||||
func (b *SBucket) GetAcl() string {
|
||||
return b.Acl
|
||||
}
|
||||
|
||||
func (b *SBucket) GetLocation() string {
|
||||
return b.Location
|
||||
}
|
||||
|
||||
func (b *SBucket) GetIRegion() cloudprovider.ICloudRegion {
|
||||
return b.region
|
||||
}
|
||||
|
||||
func (b *SBucket) GetCreateAt() time.Time {
|
||||
return b.CreationDate
|
||||
}
|
||||
|
||||
func (b *SBucket) GetStorageClass() string {
|
||||
return b.StorageClass
|
||||
}
|
||||
|
||||
func (b *SBucket) GetAccessUrls() []cloudprovider.SBucketAccessUrl {
|
||||
return []cloudprovider.SBucketAccessUrl{
|
||||
{
|
||||
Url: fmt.Sprintf("https://%s.aliyuncs.com", b.Location),
|
||||
Description: "ExtranetEndpoint",
|
||||
},
|
||||
{
|
||||
Url: fmt.Sprintf("https://%s-internal.aliyuncs.com", b.Location),
|
||||
Description: "IntranetEndpoint",
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
"yunion.io/x/pkg/utils"
|
||||
@@ -917,3 +918,136 @@ func (region *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAc
|
||||
}
|
||||
return iAcl, region.AddAccessControlListEntry(aclId, acl.Entrys)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
|
||||
osscli, err := region.GetOssClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "region.GetOssClient")
|
||||
}
|
||||
result, err := osscli.ListBuckets()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "oss.ListBuckets")
|
||||
}
|
||||
|
||||
ret := make([]cloudprovider.ICloudBucket, 0)
|
||||
for _, bInfo := range result.Buckets {
|
||||
if bInfo.Location[4:] != region.GetId() {
|
||||
continue
|
||||
}
|
||||
acl := string(oss.ACLPrivate)
|
||||
aclResp, err := osscli.GetBucketACL(bInfo.Name)
|
||||
if err == nil {
|
||||
acl = aclResp.ACL
|
||||
}
|
||||
b := SBucket{
|
||||
region: region,
|
||||
|
||||
Name: bInfo.Name,
|
||||
Location: bInfo.Location,
|
||||
CreationDate: bInfo.CreationDate,
|
||||
StorageClass: bInfo.StorageClass,
|
||||
Acl: acl,
|
||||
}
|
||||
ret = append(ret, &b)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error {
|
||||
osscli, err := region.GetOssClient()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "region.GetOssClient")
|
||||
}
|
||||
opts := make([]oss.Option, 0)
|
||||
if len(storageClassStr) > 0 {
|
||||
storageClass := oss.StorageStandard
|
||||
if strings.EqualFold(storageClassStr, string(oss.StorageStandard)) {
|
||||
//
|
||||
} else if strings.EqualFold(storageClassStr, string(oss.StorageIA)) {
|
||||
storageClass = oss.StorageIA
|
||||
} else if strings.EqualFold(storageClassStr, string(oss.StorageArchive)) {
|
||||
storageClass = oss.StorageArchive
|
||||
} else {
|
||||
return errors.Error("not supported storageClass")
|
||||
}
|
||||
opt := oss.StorageClass(storageClass)
|
||||
opts = append(opts, opt)
|
||||
}
|
||||
if len(aclStr) > 0 {
|
||||
acl := oss.ACLPrivate
|
||||
if strings.EqualFold(aclStr, string(oss.ACLPrivate)) {
|
||||
// private, default
|
||||
} else if strings.EqualFold(aclStr, string(oss.ACLPublicRead)) {
|
||||
acl = oss.ACLPublicRead
|
||||
} else if strings.EqualFold(aclStr, string(oss.ACLPublicReadWrite)) {
|
||||
acl = oss.ACLPublicReadWrite
|
||||
} else {
|
||||
return errors.Error("not supported acl")
|
||||
}
|
||||
opt := oss.ACL(acl)
|
||||
opts = append(opts, opt)
|
||||
}
|
||||
err = osscli.CreateBucket(name, opts...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "oss.CreateBucket")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ossErrorCode(err error) int {
|
||||
if srvErr, ok := err.(oss.ServiceError); ok {
|
||||
return srvErr.StatusCode
|
||||
}
|
||||
if srvErr, ok := err.(*oss.ServiceError); ok {
|
||||
return srvErr.StatusCode
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteIBucket(name string) error {
|
||||
osscli, err := region.GetOssClient()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "region.GetOssClient")
|
||||
}
|
||||
err = osscli.DeleteBucket(name)
|
||||
if err != nil {
|
||||
if ossErrorCode(err) == 404 {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "DeleteBucket")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) IBucketExist(name string) (bool, error) {
|
||||
osscli, err := region.GetOssClient()
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "region.GetOssClient")
|
||||
}
|
||||
exist, err := osscli.IsBucketExist(name)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "IsBucketExist")
|
||||
}
|
||||
return exist, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
|
||||
osscli, err := region.GetOssClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "region.GetOssClient")
|
||||
}
|
||||
bi, err := osscli.GetBucketInfo(name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Bucket")
|
||||
}
|
||||
bInfo := bi.BucketInfo
|
||||
b := SBucket{
|
||||
region: region,
|
||||
Name: bInfo.Name,
|
||||
Location: bInfo.Location,
|
||||
CreationDate: bInfo.CreationDate,
|
||||
StorageClass: bInfo.StorageClass,
|
||||
Acl: bInfo.ACL,
|
||||
}
|
||||
return &b, nil
|
||||
}
|
||||
|
||||
@@ -59,15 +59,11 @@ func init() {
|
||||
type OssListOptions struct {
|
||||
}
|
||||
shellutils.R(&OssListOptions{}, "oss-list", "List OSS buckets", func(cli *aliyun.SRegion, args *OssListOptions) error {
|
||||
oss, err := cli.GetOssClient()
|
||||
buckets, err := cli.GetIBuckets()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := oss.ListBuckets()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result.Buckets, len(result.Buckets), 0, 50, nil)
|
||||
printList(buckets, len(buckets), 0, 50, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -92,12 +88,25 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&OssListBucketOptions{}, "oss-create-bucket", "Create a OSS bucket", func(cli *aliyun.SRegion, args *OssListBucketOptions) error {
|
||||
oss, err := cli.GetOssClient()
|
||||
type OssCreateBucketOptions struct {
|
||||
BUCKET string `help:"bucket name"`
|
||||
StorageClass string `help:"storage class" choices:"Standard|IA|Archive"`
|
||||
|
||||
Acl string `help:"ACL" choices:"private|public-read|public-read-write"`
|
||||
}
|
||||
shellutils.R(&OssCreateBucketOptions{}, "oss-create-bucket", "Create a OSS bucket", func(cli *aliyun.SRegion, args *OssCreateBucketOptions) error {
|
||||
err := cli.CreateIBucket(args.BUCKET, args.StorageClass, args.Acl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = oss.CreateBucket(args.BUCKET)
|
||||
return nil
|
||||
})
|
||||
|
||||
type OssDeleteBucketOptions struct {
|
||||
BUCKET string `help:"bucket name"`
|
||||
}
|
||||
shellutils.R(&OssDeleteBucketOptions{}, "oss-delete-bucket", "Delete a OSS bucket", func(cli *aliyun.SRegion, args *OssDeleteBucketOptions) error {
|
||||
err := cli.DeleteIBucket(args.BUCKET)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+2
-2
@@ -154,9 +154,9 @@ func (self *SAwsClient) GetRegion(regionId string) *SRegion {
|
||||
if len(regionId) == 0 {
|
||||
regionId = AWS_INTERNATIONAL_DEFAULT_REGION
|
||||
switch self.accessUrl {
|
||||
case "InternationalCloud":
|
||||
case AWS_INTERNATIONAL_CLOUDENV:
|
||||
regionId = AWS_INTERNATIONAL_DEFAULT_REGION
|
||||
case "ChinaCloud":
|
||||
case AWS_CHINA_CLOUDENV:
|
||||
regionId = AWS_CHINA_DEFAULT_REGION
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SBucket struct {
|
||||
region *SRegion
|
||||
|
||||
Name string
|
||||
Location string
|
||||
CreationDate time.Time
|
||||
}
|
||||
|
||||
func (b *SBucket) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *SBucket) GetGlobalId() string {
|
||||
return b.Name
|
||||
}
|
||||
|
||||
func (b *SBucket) GetName() string {
|
||||
return b.Name
|
||||
}
|
||||
|
||||
func (b *SBucket) GetLocation() string {
|
||||
return b.Location
|
||||
}
|
||||
|
||||
func (b *SBucket) GetIRegion() cloudprovider.ICloudRegion {
|
||||
return b.region
|
||||
}
|
||||
|
||||
func (b *SBucket) GetCreateAt() time.Time {
|
||||
return b.CreationDate
|
||||
}
|
||||
|
||||
func (b *SBucket) GetStorageClass() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *SBucket) GetAcl() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *SBucket) GetAccessUrls() []cloudprovider.SBucketAccessUrl {
|
||||
return []cloudprovider.SBucketAccessUrl{
|
||||
{
|
||||
Url: fmt.Sprintf("https://%s.%s", b.Name, b.region.getS3Endpoint()),
|
||||
Description: "bucket domain",
|
||||
},
|
||||
{
|
||||
Url: fmt.Sprintf("https://%s/%s", b.region.getS3Endpoint(), b.Name),
|
||||
Description: "s3 domain",
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
sdk "github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
@@ -26,6 +27,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -524,3 +526,109 @@ func (region *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbala
|
||||
func (region *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
|
||||
s3cli, err := region.GetS3Client()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetS3Client")
|
||||
}
|
||||
output, err := s3cli.ListBuckets(&s3.ListBucketsInput{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "ListBuckets")
|
||||
}
|
||||
ret := make([]cloudprovider.ICloudBucket, 0)
|
||||
for _, bInfo := range output.Buckets {
|
||||
input := &s3.GetBucketLocationInput{}
|
||||
input.Bucket = bInfo.Name
|
||||
output, err := s3cli.GetBucketLocation(input)
|
||||
if err != nil {
|
||||
log.Errorf("s3cli.GetBucketLocation error %s", err)
|
||||
continue
|
||||
}
|
||||
if *output.LocationConstraint != region.GetId() {
|
||||
continue
|
||||
}
|
||||
b := SBucket{
|
||||
region: region,
|
||||
Name: *bInfo.Name,
|
||||
Location: region.GetId(),
|
||||
CreationDate: *bInfo.CreationDate,
|
||||
}
|
||||
ret = append(ret, &b)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateIBucket(name string, storageClassStr string, acl string) error {
|
||||
s3cli, err := region.GetS3Client()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetS3Client")
|
||||
}
|
||||
input := &s3.CreateBucketInput{}
|
||||
input.Bucket = &name
|
||||
input.CreateBucketConfiguration = &s3.CreateBucketConfiguration{}
|
||||
location := region.GetId()
|
||||
input.CreateBucketConfiguration.LocationConstraint = &location
|
||||
_, err = s3cli.CreateBucket(input)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "CreateBucket")
|
||||
}
|
||||
// if *output.Location != region.GetId() {
|
||||
// log.Warningf("Request location %s != got locaiton %s", region.GetId(), *output.Location)
|
||||
// }
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteIBucket(name string) error {
|
||||
s3cli, err := region.GetS3Client()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetS3Client")
|
||||
}
|
||||
input := &s3.DeleteBucketInput{}
|
||||
input.Bucket = &name
|
||||
_, err = s3cli.DeleteBucket(input)
|
||||
if err != nil {
|
||||
if strings.Index(err.Error(), "NoSuchBucket") >= 0 {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "DeleteBucket")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) IBucketExist(name string) (bool, error) {
|
||||
s3cli, err := region.GetS3Client()
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "GetS3Client")
|
||||
}
|
||||
input := &s3.HeadBucketInput{}
|
||||
input.Bucket = &name
|
||||
_, err = s3cli.HeadBucket(input)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "IsBucketExist")
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
|
||||
return cloudprovider.GetIBucketByName(region, name)
|
||||
}
|
||||
|
||||
func (region *SRegion) getBaseEndpoint() string {
|
||||
if len(region.RegionEndpoint) > 4 {
|
||||
return region.RegionEndpoint[4:]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (region *SRegion) getS3Endpoint() string {
|
||||
base := region.getBaseEndpoint()
|
||||
if len(base) > 0 {
|
||||
return "s3." + base
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (region *SRegion) getEc2Endpoint() string {
|
||||
return region.RegionEndpoint
|
||||
}
|
||||
|
||||
@@ -16,9 +16,12 @@ package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"os"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/printutils"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
"yunion.io/x/onecloud/pkg/util/streamutils"
|
||||
)
|
||||
@@ -27,15 +30,34 @@ func init() {
|
||||
type S3BucketListOptions struct {
|
||||
}
|
||||
shellutils.R(&S3BucketListOptions{}, "s3-list", "List all buckets", func(cli *aws.SRegion, args *S3BucketListOptions) error {
|
||||
s3cli, err := cli.GetS3Client()
|
||||
buckets, err := cli.GetIBuckets()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
output, err := s3cli.ListBuckets(&s3.ListBucketsInput{})
|
||||
printList(buckets, 0, 0, 0, nil)
|
||||
printutils.PrintGetterList(buckets, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type S3CreateBucketOptions struct {
|
||||
BUCKET string `help:"bucket name"`
|
||||
}
|
||||
shellutils.R(&S3CreateBucketOptions{}, "s3-create-bucket", "Create a bucket", func(cli *aws.SRegion, args *S3CreateBucketOptions) error {
|
||||
err := cli.CreateIBucket(args.BUCKET, "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
type S3DeleteBucketOptions struct {
|
||||
BUCKET string `help:"bucket name"`
|
||||
}
|
||||
shellutils.R(&S3DeleteBucketOptions{}, "s3-delete-bucket", "Delete a bucket", func(cli *aws.SRegion, args *S3DeleteBucketOptions) error {
|
||||
err := cli.DeleteIBucket(args.BUCKET)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(output.Buckets, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -608,3 +609,48 @@ func (region *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbala
|
||||
func (region *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
|
||||
accounts, err := region.GetStorageAccounts()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "region.GetStorageAccounts")
|
||||
}
|
||||
ret := make([]cloudprovider.ICloudBucket, len(accounts))
|
||||
for i := range accounts {
|
||||
ret[i] = &accounts[i]
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateIBucket(name string, storageClassStr string, acl string) error {
|
||||
_, err := region.createStorageAccount(name, storageClassStr)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "region.createStorageAccount")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteIBucket(name string) error {
|
||||
accounts, err := region.GetStorageAccounts()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetStorageAccounts")
|
||||
}
|
||||
for i := range accounts {
|
||||
if accounts[i].Name == name {
|
||||
err = region.client.Delete(accounts[i].ID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "region.client.Delete")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) IBucketExist(name string) (bool, error) {
|
||||
return region.checkStorageAccountNameExist(name)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
|
||||
return cloudprovider.GetIBucketByName(region, name)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/azure"
|
||||
"yunion.io/x/onecloud/pkg/util/printutils"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type BucketListOptions struct {
|
||||
}
|
||||
shellutils.R(&BucketListOptions{}, "bucket-list", "List buckets", func(cli *azure.SRegion, args *BucketListOptions) error {
|
||||
buckets, err := cli.GetIBuckets()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printutils.PrintGetterList(buckets, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type BucketCreateOptions struct {
|
||||
BUCKET string `help:"bucket name"`
|
||||
STORAGECLASS string `help:"storage class"`
|
||||
}
|
||||
shellutils.R(&BucketCreateOptions{}, "bucket-create", "Create bucket", func(cli *azure.SRegion, args *BucketCreateOptions) error {
|
||||
err := cli.CreateIBucket(args.BUCKET, args.STORAGECLASS, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
type BucketDeleteOptions struct {
|
||||
BUCKET string `help:"bucket name"`
|
||||
}
|
||||
shellutils.R(&BucketDeleteOptions{}, "bucket-delete", "Delete a bucket", func(cli *azure.SRegion, args *BucketDeleteOptions) error {
|
||||
err := cli.DeleteIBucket(args.BUCKET)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
type BucketShowOptions struct {
|
||||
BUCKET string `help:"bucket name"`
|
||||
}
|
||||
shellutils.R(&BucketShowOptions{}, "bucket-show", "Show a bucket", func(cli *azure.SRegion, args *BucketShowOptions) error {
|
||||
bucket, err := cli.GetIBucketByName(args.BUCKET)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(bucket)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -23,14 +23,12 @@ import (
|
||||
|
||||
func init() {
|
||||
type StorageAccountListOptions struct {
|
||||
Limit int `help:"page size"`
|
||||
Offset int `help:"page offset"`
|
||||
}
|
||||
shellutils.R(&StorageAccountListOptions{}, "storage-account-list", "List storage account", func(cli *azure.SRegion, args *StorageAccountListOptions) error {
|
||||
if accounts, err := cli.GetStorageAccounts(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
printList(accounts, len(accounts), args.Offset, args.Limit, []string{})
|
||||
printList(accounts, len(accounts), 0, 0, []string{})
|
||||
return nil
|
||||
}
|
||||
})
|
||||
@@ -152,4 +150,14 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type SStorageAccountSkuOptions struct {
|
||||
}
|
||||
shellutils.R(&SStorageAccountSkuOptions{}, "storage-account-skus", "List skus of storage account", func(cli *azure.SRegion, args *SStorageAccountSkuOptions) error {
|
||||
skus, err := cli.GetStorageAccountSkus()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(skus, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -26,8 +26,10 @@ import (
|
||||
"github.com/Microsoft/azure-vhd-utils/vhdcore/diskstream"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
type SContainer struct {
|
||||
@@ -35,7 +37,7 @@ type SContainer struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
type Sku struct {
|
||||
type SSku struct {
|
||||
Name string
|
||||
Tier string
|
||||
Kind string
|
||||
@@ -48,7 +50,7 @@ type Identity struct {
|
||||
Type string
|
||||
}
|
||||
|
||||
type PrimaryEndpoints struct {
|
||||
type SStorageEndpoints struct {
|
||||
Blob string
|
||||
Queue string
|
||||
Table string
|
||||
@@ -60,10 +62,11 @@ type AccountProperties struct {
|
||||
ClassicStorageProperties
|
||||
|
||||
//normal
|
||||
PrimaryEndpoints PrimaryEndpoints `json:"primaryEndpoints,omitempty"`
|
||||
ProvisioningState string
|
||||
PrimaryLocation string
|
||||
SecondaryLocation string
|
||||
PrimaryEndpoints SStorageEndpoints `json:"primaryEndpoints,omitempty"`
|
||||
ProvisioningState string
|
||||
PrimaryLocation string
|
||||
SecondaryEndpoints SStorageEndpoints `json:"secondaryEndpoints,omitempty"`
|
||||
SecondaryLocation string
|
||||
//CreationTime time.Time
|
||||
AccessTier string `json:"accessTier,omitempty"`
|
||||
EnableHTTPSTrafficOnly *bool `json:"supportsHttpsTrafficOnly,omitempty"`
|
||||
@@ -74,7 +77,7 @@ type AccountProperties struct {
|
||||
type SStorageAccount struct {
|
||||
region *SRegion
|
||||
accountKey string
|
||||
Sku Sku `json:"sku,omitempty"`
|
||||
Sku SSku `json:"sku,omitempty"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Identity *Identity
|
||||
Properties AccountProperties
|
||||
@@ -125,6 +128,119 @@ func (self *SRegion) GetUniqStorageAccountName() string {
|
||||
}
|
||||
}
|
||||
|
||||
type sStorageAccountCheckNameAvailabilityInput struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
type sStorageAccountCheckNameAvailabilityOutput struct {
|
||||
NameAvailable bool `json:"nameAvailable"`
|
||||
Reason string `json:"reason"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (self *SRegion) checkStorageAccountNameExist(name string) (bool, error) {
|
||||
url := fmt.Sprintf("/subscriptions/%s/providers/Microsoft.Storage/checkNameAvailability?api-version=2019-04-01", self.client.subscriptionId)
|
||||
body := jsonutils.Marshal(sStorageAccountCheckNameAvailabilityInput{
|
||||
Name: name,
|
||||
Type: "Microsoft.Storage/storageAccounts",
|
||||
})
|
||||
resp, err := self.client.jsonRequest("POST", url, body.String())
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "jsonRequest")
|
||||
}
|
||||
output := sStorageAccountCheckNameAvailabilityOutput{}
|
||||
err = resp.Unmarshal(&output)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "Unmarshal")
|
||||
}
|
||||
if output.NameAvailable {
|
||||
return false, nil
|
||||
} else {
|
||||
if output.Reason == "AlreadyExists" {
|
||||
return true, nil
|
||||
} else {
|
||||
return false, errors.Error(output.Reason)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type SStorageAccountSku struct {
|
||||
ResourceType string `json:"resourceType"`
|
||||
Name string `json:"name"`
|
||||
Tier string `json:"tier"`
|
||||
Kind string `json:"kind"`
|
||||
Locations []string `json:"locations"`
|
||||
Capabilities []struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
} `json:"capabilities"`
|
||||
Restrictions []struct {
|
||||
Type string `json:"type"`
|
||||
Values []string `json:"values"`
|
||||
ReasonCode string `json:"reasonCode"`
|
||||
} `json:"restrictions"`
|
||||
}
|
||||
|
||||
func (self *SRegion) GetStorageAccountSkus() ([]SStorageAccountSku, error) {
|
||||
skus := make([]SStorageAccountSku, 0)
|
||||
err := self.client.List("providers/Microsoft.Storage/skus?api-version=2019-04-01", &skus)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "List")
|
||||
}
|
||||
ret := make([]SStorageAccountSku, 0)
|
||||
for i := range skus {
|
||||
if utils.IsInStringArray(self.GetId(), skus[i].Locations) {
|
||||
ret = append(ret, skus[i])
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) getStorageAccountSkuByName(name string) (*SStorageAccountSku, error) {
|
||||
skus, err := self.GetStorageAccountSkus()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getStorageAccountSkus")
|
||||
}
|
||||
for _, kind := range []string{
|
||||
"StorageV2",
|
||||
"Storage",
|
||||
} {
|
||||
for i := range skus {
|
||||
if skus[i].Name == name && skus[i].Kind == kind {
|
||||
return &skus[i], nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRegion) createStorageAccount(name string, skuName string) (*SStorageAccount, error) {
|
||||
sku, err := self.getStorageAccountSkuByName(skuName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getStorageAccountSkuByName")
|
||||
}
|
||||
stoargeaccount := SStorageAccount{
|
||||
region: self,
|
||||
Sku: SSku{
|
||||
Name: sku.Name,
|
||||
},
|
||||
Location: self.Name,
|
||||
Kind: "Storage",
|
||||
Properties: AccountProperties{
|
||||
IsHnsEnabled: true,
|
||||
AzureFilesAadIntegration: true,
|
||||
},
|
||||
Name: name,
|
||||
Type: "Microsoft.Storage/storageAccounts",
|
||||
}
|
||||
err = self.client.Create(jsonutils.Marshal(stoargeaccount), &stoargeaccount)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Create")
|
||||
}
|
||||
return &stoargeaccount, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateStorageAccount(storageAccount string) (*SStorageAccount, error) {
|
||||
account, err := self.getStorageAccountID(storageAccount)
|
||||
if err == nil {
|
||||
@@ -134,7 +250,7 @@ func (self *SRegion) CreateStorageAccount(storageAccount string) (*SStorageAccou
|
||||
uniqName := self.GetUniqStorageAccountName()
|
||||
stoargeaccount := SStorageAccount{
|
||||
region: self,
|
||||
Sku: Sku{
|
||||
Sku: SSku{
|
||||
Name: "Standard_GRS",
|
||||
},
|
||||
Location: self.Name,
|
||||
@@ -430,3 +546,81 @@ func (self *SStorageAccount) UploadFile(containerName string, filePath string) (
|
||||
}
|
||||
return container.UploadFile(filePath)
|
||||
}
|
||||
|
||||
func (b *SStorageAccount) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *SStorageAccount) GetGlobalId() string {
|
||||
return b.Name
|
||||
}
|
||||
|
||||
func (b *SStorageAccount) GetName() string {
|
||||
return b.Name
|
||||
}
|
||||
|
||||
func (b *SStorageAccount) GetLocation() string {
|
||||
return b.Location
|
||||
}
|
||||
|
||||
func (b *SStorageAccount) GetIRegion() cloudprovider.ICloudRegion {
|
||||
return b.region
|
||||
}
|
||||
|
||||
func (b *SStorageAccount) GetCreateAt() time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (b *SStorageAccount) GetStorageClass() string {
|
||||
return b.Sku.Tier
|
||||
}
|
||||
|
||||
func (b *SStorageAccount) GetAcl() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func getDesc(prefix, name string) string {
|
||||
if len(prefix) > 0 {
|
||||
return prefix + "-" + name
|
||||
} else {
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
func (ep SStorageEndpoints) getUrls(prefix string) []cloudprovider.SBucketAccessUrl {
|
||||
ret := make([]cloudprovider.SBucketAccessUrl, 0)
|
||||
if len(ep.Blob) > 0 {
|
||||
ret = append(ret, cloudprovider.SBucketAccessUrl{
|
||||
Url: ep.Blob,
|
||||
Description: getDesc(prefix, "blob"),
|
||||
})
|
||||
}
|
||||
if len(ep.Queue) > 0 {
|
||||
ret = append(ret, cloudprovider.SBucketAccessUrl{
|
||||
Url: ep.Queue,
|
||||
Description: getDesc(prefix, "queue"),
|
||||
})
|
||||
}
|
||||
if len(ep.Table) > 0 {
|
||||
ret = append(ret, cloudprovider.SBucketAccessUrl{
|
||||
Url: ep.Table,
|
||||
Description: getDesc(prefix, "table"),
|
||||
})
|
||||
}
|
||||
if len(ep.File) > 0 {
|
||||
ret = append(ret, cloudprovider.SBucketAccessUrl{
|
||||
Url: ep.File,
|
||||
Description: getDesc(prefix, "file"),
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (b *SStorageAccount) GetAccessUrls() []cloudprovider.SBucketAccessUrl {
|
||||
primary := b.Properties.PrimaryEndpoints.getUrls("")
|
||||
secondary := b.Properties.SecondaryEndpoints.getUrls("secondary")
|
||||
if len(secondary) > 0 {
|
||||
primary = append(primary, secondary...)
|
||||
}
|
||||
return primary
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ const (
|
||||
type SESXiClient struct {
|
||||
cloudprovider.SFakeOnPremiseRegion
|
||||
multicloud.SRegion
|
||||
multicloud.SNoObjectStorageRegion
|
||||
|
||||
providerId string
|
||||
providerName string
|
||||
|
||||
@@ -132,9 +132,10 @@ func GetClient(insecure bool, timeout time.Duration) *http.Client {
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 5 * time.Second,
|
||||
}).DialContext,
|
||||
IdleConnTimeout: 5 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure},
|
||||
IdleConnTimeout: 5 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecure},
|
||||
}
|
||||
return &http.Client{
|
||||
Transport: tr,
|
||||
@@ -223,6 +224,26 @@ func JSONRequest(client *http.Client, ctx context.Context, method THttpMethod, u
|
||||
return ParseJSONResponse(resp, err, debug)
|
||||
}
|
||||
|
||||
// closeResponse close non nil response with any response Body.
|
||||
// convenient wrapper to drain any remaining data on response body.
|
||||
//
|
||||
// Subsequently this allows golang http RoundTripper
|
||||
// to re-use the same connection for future requests.
|
||||
func closeResponse(resp *http.Response) {
|
||||
// Callers should close resp.Body when done reading from it.
|
||||
// If resp.Body is not closed, the Client's underlying RoundTripper
|
||||
// (typically Transport) may not be able to re-use a persistent TCP
|
||||
// connection to the server for a subsequent "keep-alive" request.
|
||||
if resp != nil && resp.Body != nil {
|
||||
// Drain any remaining Body and then close the connection.
|
||||
// Without this closing connection would disallow re-using
|
||||
// the same connection for future uses.
|
||||
// - http://stackoverflow.com/a/17961593/4465767
|
||||
io.Copy(ioutil.Discard, resp.Body)
|
||||
resp.Body.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func ParseJSONResponse(resp *http.Response, err error, debug bool) (http.Header, jsonutils.JSONObject, error) {
|
||||
if err != nil {
|
||||
ce := JSONClientError{}
|
||||
@@ -230,7 +251,7 @@ func ParseJSONResponse(resp *http.Response, err error, debug bool) (http.Header,
|
||||
ce.Details = err.Error()
|
||||
return nil, nil, &ce
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
defer closeResponse(resp)
|
||||
if debug {
|
||||
if resp.StatusCode < 300 {
|
||||
green("Status:", resp.StatusCode)
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package huawei
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SBucket struct {
|
||||
region *SRegion
|
||||
|
||||
Name string
|
||||
Location string
|
||||
CreationDate time.Time
|
||||
|
||||
StorageClass string
|
||||
Acl string
|
||||
|
||||
Size int64
|
||||
ObjectNumber int
|
||||
}
|
||||
|
||||
func (b *SBucket) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *SBucket) GetGlobalId() string {
|
||||
return b.Name
|
||||
}
|
||||
|
||||
func (b *SBucket) GetName() string {
|
||||
return b.Name
|
||||
}
|
||||
|
||||
func (b *SBucket) GetLocation() string {
|
||||
return b.Location
|
||||
}
|
||||
|
||||
func (b *SBucket) GetIRegion() cloudprovider.ICloudRegion {
|
||||
return b.region
|
||||
}
|
||||
|
||||
func (b *SBucket) GetCreateAt() time.Time {
|
||||
return b.CreationDate
|
||||
}
|
||||
|
||||
func (b *SBucket) GetStorageClass() string {
|
||||
return b.StorageClass
|
||||
}
|
||||
|
||||
func (b *SBucket) GetAcl() string {
|
||||
return b.Acl
|
||||
}
|
||||
|
||||
func (b *SBucket) GetAccessUrls() []cloudprovider.SBucketAccessUrl {
|
||||
return []cloudprovider.SBucketAccessUrl{
|
||||
{
|
||||
Url: fmt.Sprintf("https://%s.%s", b.Name, b.region.getOBSEndpoint()),
|
||||
Description: "bucket url",
|
||||
},
|
||||
{
|
||||
Url: fmt.Sprintf("https://%s/%s", b.region.getOBSEndpoint(), b.Name),
|
||||
Description: "obs url",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (b *SBucket) GetSizeByte() int64 {
|
||||
return b.Size
|
||||
}
|
||||
|
||||
func (b *SBucket) GetObjectNumber() int {
|
||||
return b.ObjectNumber
|
||||
}
|
||||
+114
-1
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -86,9 +87,13 @@ func (self *SRegion) getECSClient() (*client.Client, error) {
|
||||
return self.ecsClient, err
|
||||
}
|
||||
|
||||
func (self *SRegion) getOBSEndpoint() string {
|
||||
return fmt.Sprintf("obs.%s.myhuaweicloud.com", self.GetId())
|
||||
}
|
||||
|
||||
func (self *SRegion) getOBSClient() (*obs.ObsClient, error) {
|
||||
if self.obsClient == nil {
|
||||
endpoint := fmt.Sprintf("obs.%s.myhuaweicloud.com", self.GetId())
|
||||
endpoint := self.getOBSEndpoint()
|
||||
obsClient, err := obs.New(self.client.accessKey, self.client.secret, endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -674,3 +679,111 @@ func (region *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbala
|
||||
func (region *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
|
||||
obsClient, err := region.getOBSClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "region.getOBSClient")
|
||||
}
|
||||
input := &obs.ListBucketsInput{}
|
||||
input.QueryLocation = true
|
||||
output, err := obsClient.ListBuckets(input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "ListBuckets")
|
||||
}
|
||||
ret := make([]cloudprovider.ICloudBucket, len(output.Buckets))
|
||||
for i, bInfo := range output.Buckets {
|
||||
b := SBucket{
|
||||
region: region,
|
||||
|
||||
Name: bInfo.Name,
|
||||
Location: bInfo.Location,
|
||||
CreationDate: bInfo.CreationDate,
|
||||
}
|
||||
ret[i] = &b
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error {
|
||||
obsClient, err := region.getOBSClient()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "region.getOBSClient")
|
||||
}
|
||||
input := &obs.CreateBucketInput{}
|
||||
input.Bucket = name
|
||||
input.Location = region.GetId()
|
||||
if len(aclStr) > 0 {
|
||||
if strings.EqualFold(aclStr, string(obs.AclPrivate)) {
|
||||
input.ACL = obs.AclPrivate
|
||||
} else if strings.EqualFold(aclStr, string(obs.AclPublicRead)) {
|
||||
input.ACL = obs.AclPublicRead
|
||||
} else if strings.EqualFold(aclStr, string(obs.AclPublicReadWrite)) {
|
||||
input.ACL = obs.AclPublicReadWrite
|
||||
} else {
|
||||
return errors.Error("unsupported acl")
|
||||
}
|
||||
}
|
||||
if len(storageClassStr) > 0 {
|
||||
if strings.EqualFold(storageClassStr, string(obs.StorageClassStandard)) {
|
||||
input.StorageClass = obs.StorageClassStandard
|
||||
} else if strings.EqualFold(storageClassStr, string(obs.StorageClassWarm)) {
|
||||
input.StorageClass = obs.StorageClassWarm
|
||||
} else if strings.EqualFold(storageClassStr, string(obs.StorageClassCold)) {
|
||||
input.StorageClass = obs.StorageClassCold
|
||||
} else {
|
||||
return errors.Error("unsupported storageClass")
|
||||
}
|
||||
}
|
||||
_, err = obsClient.CreateBucket(input)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "obsClient.CreateBucket")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteIBucket(name string) error {
|
||||
obsClient, err := region.getOBSClient()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "region.getOBSClient")
|
||||
}
|
||||
_, err = obsClient.DeleteBucket(name)
|
||||
if err != nil {
|
||||
if strings.Index(err.Error(), "Code=NoSuchBucket") >= 0 {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "DeleteBucket")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) IBucketExist(name string) (bool, error) {
|
||||
obsClient, err := region.getOBSClient()
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "region.getOBSClient")
|
||||
}
|
||||
_, err = obsClient.HeadBucket(name)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "HeadBucket")
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
|
||||
obsClient, err := region.getOBSClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "region.getOBSClient")
|
||||
}
|
||||
info, err := obsClient.GetBucketStorageInfo(name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "obsClient.GetBucketStorageInfo")
|
||||
}
|
||||
b := SBucket{
|
||||
region: region,
|
||||
|
||||
Name: name,
|
||||
Size: info.Size,
|
||||
ObjectNumber: info.ObjectNumber,
|
||||
}
|
||||
return &b, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/huawei"
|
||||
"yunion.io/x/onecloud/pkg/util/printutils"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ObsBucketListOptions struct {
|
||||
}
|
||||
shellutils.R(&ObsBucketListOptions{}, "obs-list", "List all buckets", func(cli *huawei.SRegion, args *ObsBucketListOptions) error {
|
||||
buckets, err := cli.GetIBuckets()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(buckets, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
shellutils.R(&ObsBucketListOptions{}, "bucket-list", "List all buckets", func(cli *huawei.SRegion, args *ObsBucketListOptions) error {
|
||||
buckets, err := cli.GetIBuckets()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printutils.PrintGetterList(buckets, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type ObsBucketShowOptions struct {
|
||||
BUCKET string `help:"bucket name to show"`
|
||||
}
|
||||
shellutils.R(&ObsBucketShowOptions{}, "obs-show", "Show bucket detail", func(cli *huawei.SRegion, args *ObsBucketShowOptions) error {
|
||||
bucket, err := cli.GetIBucketByName(args.BUCKET)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(bucket)
|
||||
return nil
|
||||
})
|
||||
|
||||
type ObsBucketCreateOptions struct {
|
||||
BUCKET string `help:"bucket name to show"`
|
||||
StorageClass string `help:"storage class"`
|
||||
Acl string `help:"acl"`
|
||||
}
|
||||
shellutils.R(&ObsBucketCreateOptions{}, "obs-create", "Create new OBS bucket", func(cli *huawei.SRegion, args *ObsBucketCreateOptions) error {
|
||||
err := cli.CreateIBucket(args.BUCKET, args.StorageClass, args.Acl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&ObsBucketShowOptions{}, "obs-delete", "Delete OBS bucket", func(cli *huawei.SRegion, args *ObsBucketShowOptions) error {
|
||||
err := cli.DeleteIBucket(args.BUCKET)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -482,3 +482,23 @@ func (region *SRegion) GetISkus(zoneId string) ([]cloudprovider.ICloudSku, error
|
||||
func (region *SRegion) GetISkuById(skuId string) (cloudprovider.ICloudSku, error) {
|
||||
return region.GetFlavor(skuId)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateIBucket(name string, storageClassStr string, acl string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteIBucket(name string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (region *SRegion) IBucketExist(name string) (bool, error) {
|
||||
return false, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package qcloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SBucket struct {
|
||||
region *SRegion
|
||||
|
||||
Name string
|
||||
FullName string
|
||||
Location string
|
||||
CreateDate time.Time
|
||||
Acl string
|
||||
}
|
||||
|
||||
func (b *SBucket) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *SBucket) GetGlobalId() string {
|
||||
return b.Name
|
||||
}
|
||||
|
||||
func (b *SBucket) GetName() string {
|
||||
return b.Name
|
||||
}
|
||||
|
||||
func (b *SBucket) GetLocation() string {
|
||||
return b.Location
|
||||
}
|
||||
|
||||
func (b *SBucket) GetIRegion() cloudprovider.ICloudRegion {
|
||||
return b.region
|
||||
}
|
||||
|
||||
func (b *SBucket) GetCreateAt() time.Time {
|
||||
return b.CreateDate
|
||||
}
|
||||
|
||||
func (b *SBucket) GetStorageClass() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *SBucket) GetAcl() string {
|
||||
return b.Acl
|
||||
}
|
||||
|
||||
func (b *SBucket) GetAccessUrls() []cloudprovider.SBucketAccessUrl {
|
||||
return []cloudprovider.SBucketAccessUrl{
|
||||
{
|
||||
Url: fmt.Sprintf("https://%s.%s", b.FullName, b.region.getCosEndpoint()),
|
||||
Description: "bucket domain",
|
||||
},
|
||||
{
|
||||
Url: fmt.Sprintf("https://%s/%s", b.region.getCosEndpoint(), b.FullName),
|
||||
Description: "cos domain",
|
||||
},
|
||||
}
|
||||
}
|
||||
+110
-4
@@ -20,16 +20,22 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
coslib "github.com/nelsonken/cos-go-sdk-v5/cos"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
|
||||
sdkerrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
|
||||
tchttp "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/appctx"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/pkg/util/timeutils"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -179,7 +185,7 @@ func (r *vpc2017JsonResponse) ParseErrorFromHTTPResponse(body []byte) (err error
|
||||
return
|
||||
}
|
||||
if resp.Code != 0 {
|
||||
return errors.NewTencentCloudSDKError(resp.CodeDesc, resp.Message, "")
|
||||
return sdkerrors.NewTencentCloudSDKError(resp.CodeDesc, resp.Message, "")
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -212,7 +218,7 @@ func (r *wssJsonResponse) ParseErrorFromHTTPResponse(body []byte) (err error) {
|
||||
return
|
||||
}
|
||||
if resp.Code != 0 {
|
||||
return errors.NewTencentCloudSDKError(resp.CodeDesc, resp.Message, "")
|
||||
return sdkerrors.NewTencentCloudSDKError(resp.CodeDesc, resp.Message, "")
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -234,7 +240,7 @@ func (r *lbJsonResponse) ParseErrorFromHTTPResponse(body []byte) (err error) {
|
||||
return
|
||||
}
|
||||
if resp.Code != 0 {
|
||||
return errors.NewTencentCloudSDKError(resp.CodeDesc, resp.Message, "")
|
||||
return sdkerrors.NewTencentCloudSDKError(resp.CodeDesc, resp.Message, "")
|
||||
}
|
||||
|
||||
// hook 由于目前只能从这个方法中拿到原始的body.这里将原始body hook 到 Response
|
||||
@@ -581,3 +587,103 @@ func (client *SQcloudClient) GetIProjects() ([]cloudprovider.ICloudProject, erro
|
||||
}
|
||||
return iprojects, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
|
||||
ctx := appctx.Background
|
||||
cos, err := region.GetCosClient()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetCosClient")
|
||||
}
|
||||
result, err := cos.GetBucketList(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetBucketList")
|
||||
}
|
||||
ret := make([]cloudprovider.ICloudBucket, 0)
|
||||
for i := range result.Buckets.Bucket {
|
||||
bInfo := result.Buckets.Bucket[i]
|
||||
// ignore buckets not belong to this region
|
||||
if bInfo.Location != region.GetId() {
|
||||
continue
|
||||
}
|
||||
createAt, _ := timeutils.ParseTimeStr(bInfo.CreateDate)
|
||||
name := bInfo.Name
|
||||
// name = name[:len(name)-len(result.Owner.ID)-1]
|
||||
name = name[:strings.LastIndexByte(name, '-')]
|
||||
b := SBucket{
|
||||
region: region,
|
||||
|
||||
Name: name,
|
||||
FullName: bInfo.Name,
|
||||
Location: bInfo.Location,
|
||||
CreateDate: createAt,
|
||||
}
|
||||
ret = append(ret, &b)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error {
|
||||
ctx := appctx.Background
|
||||
cos, err := region.GetCosClient()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetCosClient")
|
||||
}
|
||||
acl := &coslib.AccessControl{}
|
||||
if len(aclStr) > 0 {
|
||||
if utils.IsInStringArray(aclStr, []string{
|
||||
"private", "public-read", "public-read-write", "authenticated-read",
|
||||
}) {
|
||||
acl.ACL = aclStr
|
||||
} else {
|
||||
return errors.Error("invalid acl")
|
||||
}
|
||||
}
|
||||
err = cos.CreateBucket(ctx, name, acl)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "oss.CreateBucket")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func cosHttpCode(err error) int {
|
||||
if httpErr, ok := err.(coslib.HTTPError); ok {
|
||||
return httpErr.Code
|
||||
}
|
||||
if httpErr, ok := err.(*coslib.HTTPError); ok {
|
||||
return httpErr.Code
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteIBucket(name string) error {
|
||||
ctx := appctx.Background
|
||||
cos, err := region.GetCosClient()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetCosClient")
|
||||
}
|
||||
err = cos.DeleteBucket(ctx, name)
|
||||
if err != nil {
|
||||
if cosHttpCode(err) == 404 {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "DeleteBucket")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) IBucketExist(name string) (bool, error) {
|
||||
ctx := appctx.Background
|
||||
cos, err := region.GetCosClient()
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "GetCosClient")
|
||||
}
|
||||
err = cos.BucketExists(ctx, name)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "BucketExists")
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
|
||||
return cloudprovider.GetIBucketByName(region, name)
|
||||
}
|
||||
|
||||
@@ -816,3 +816,7 @@ func (self *SRegion) GetInstanceStatus(instanceId string) (string, error) {
|
||||
func (self *SRegion) QueryAccountBalance() (*SAccountBalance, error) {
|
||||
return self.client.QueryAccountBalance()
|
||||
}
|
||||
|
||||
func (self *SRegion) getCosEndpoint() string {
|
||||
return fmt.Sprintf("cos.%s.myqcloud.com", self.GetId())
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
coslib "github.com/nelsonken/cos-go-sdk-v5/cos"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/printutils"
|
||||
"yunion.io/x/onecloud/pkg/util/qcloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
@@ -28,15 +29,43 @@ func init() {
|
||||
type CosListOptions struct {
|
||||
}
|
||||
shellutils.R(&CosListOptions{}, "cos-list", "List COS buckets", func(cli *qcloud.SRegion, args *CosListOptions) error {
|
||||
cos, err := cli.GetCosClient()
|
||||
buckets, err := cli.GetIBuckets()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := cos.GetBucketList(context.Background())
|
||||
printList(buckets, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&CosListOptions{}, "bucket-list", "List COS buckets", func(cli *qcloud.SRegion, args *CosListOptions) error {
|
||||
buckets, err := cli.GetIBuckets()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printutils.PrintGetterList(buckets, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type CosCreateBucketOptions struct {
|
||||
BUCKET string `help:"name of bucket to create"`
|
||||
Acl string `help:"Acl"`
|
||||
}
|
||||
shellutils.R(&CosCreateBucketOptions{}, "cos-create-bucket", "Create a COS bucket", func(cli *qcloud.SRegion, args *CosCreateBucketOptions) error {
|
||||
err := cli.CreateIBucket(args.BUCKET, "", args.Acl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
type CosDeleteBucketOptions struct {
|
||||
BUCKET string `help:"name of bucket to delete"`
|
||||
}
|
||||
shellutils.R(&CosDeleteBucketOptions{}, "cos-delete-bucket", "Delete a COS bucket", func(cli *qcloud.SRegion, args *CosDeleteBucketOptions) error {
|
||||
err := cli.DeleteIBucket(args.BUCKET)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result.Buckets.Bucket, len(result.Buckets.Bucket), 0, len(result.Buckets.Bucket), nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
|
||||
@@ -151,6 +151,8 @@ func parseUcloudResponse(params SParams, resp jsonutils.JSONObject) (jsonutils.J
|
||||
return nil, e
|
||||
}
|
||||
|
||||
err.Action, _ = params.data.GetString("Action")
|
||||
|
||||
if err.RetCode > 0 {
|
||||
log.Debugf("Ucloud json request err %s", params.PrettyString())
|
||||
return nil, err
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -634,3 +635,87 @@ func (self *SRegion) syncSecgroupRules(secgroupId string, rules []secrules.Secur
|
||||
func (self *SRegion) GetClient() *SUcloudClient {
|
||||
return self.client
|
||||
}
|
||||
|
||||
func (region *SRegion) listBuckets(name string, offset int, limit int) ([]SBucket, error) {
|
||||
params := NewUcloudParams()
|
||||
if len(name) > 0 {
|
||||
params.Set("BucketName", name)
|
||||
} else {
|
||||
params.Set("Limit", limit)
|
||||
params.Set("Offset", offset)
|
||||
}
|
||||
buckets := make([]SBucket, 0)
|
||||
err := region.DoAction("DescribeBucket", params, &buckets)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "DoAction DescribeBucket")
|
||||
}
|
||||
return buckets, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
|
||||
buckets := make([]SBucket, 0)
|
||||
offset := 0
|
||||
limit := 50
|
||||
for {
|
||||
parts, err := region.listBuckets("", offset, limit)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "region.listBuckets")
|
||||
}
|
||||
if len(parts) > 0 {
|
||||
buckets = append(buckets, parts...)
|
||||
}
|
||||
if len(parts) < limit {
|
||||
break
|
||||
} else {
|
||||
offset += limit
|
||||
}
|
||||
}
|
||||
ret := make([]cloudprovider.ICloudBucket, len(buckets))
|
||||
for i := range buckets {
|
||||
buckets[i].region = region
|
||||
ret[i] = &buckets[i]
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error {
|
||||
if aclStr != "private" && aclStr != "public" {
|
||||
return errors.Error("invalid acl")
|
||||
}
|
||||
return region.CreateBucket(name, aclStr)
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteIBucket(name string) error {
|
||||
err := region.DeleteBucket(name)
|
||||
if err != nil {
|
||||
if strings.Index(err.Error(), "bucket not found") >= 0 {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "region.DeleteBucket")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) IBucketExist(name string) (bool, error) {
|
||||
parts, err := region.listBuckets(name, 0, 1)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "region.listBuckets")
|
||||
}
|
||||
if len(parts) == 0 {
|
||||
return false, cloudprovider.ErrNotFound
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
|
||||
parts, err := region.listBuckets(name, 0, 1)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "region.listBuckets")
|
||||
}
|
||||
if len(parts) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
bucket := parts[0]
|
||||
bucket.region = region
|
||||
return &bucket, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/printutils"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
"yunion.io/x/onecloud/pkg/util/ucloud"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type UFileBucketListOptions struct {
|
||||
}
|
||||
shellutils.R(&UFileBucketListOptions{}, "bucket-list", "List buckets", func(cli *ucloud.SRegion, args *UFileBucketListOptions) error {
|
||||
buckets, err := cli.GetIBuckets()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printutils.PrintGetterList(buckets, nil)
|
||||
return nil
|
||||
})
|
||||
|
||||
type UFileBucketCreateOptions struct {
|
||||
BUCKET string `help:"Name of bucket"`
|
||||
Acl string `help:"Acl" choices:"private|public"`
|
||||
}
|
||||
shellutils.R(&UFileBucketCreateOptions{}, "bucket-create", "create a bucket", func(cli *ucloud.SRegion, args *UFileBucketCreateOptions) error {
|
||||
err := cli.CreateIBucket(args.BUCKET, "", args.Acl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
type UFileBucketDeleteOptions struct {
|
||||
BUCKET string `help:"Name of bucket"`
|
||||
}
|
||||
shellutils.R(&UFileBucketDeleteOptions{}, "bucket-delete", "delete a bucket", func(cli *ucloud.SRegion, args *UFileBucketDeleteOptions) error {
|
||||
err := cli.DeleteIBucket(args.BUCKET)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -19,16 +19,21 @@ import (
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/coredns/coredns/plugin/pkg/log"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/util/httputils"
|
||||
)
|
||||
|
||||
type SBucket struct {
|
||||
region *SRegion
|
||||
|
||||
Domain Domain `json:"Domain"`
|
||||
BucketID string `json:"BucketId"`
|
||||
Region string `json:"Region"`
|
||||
@@ -143,3 +148,53 @@ func (self *SFile) request(req *http.Request) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *SBucket) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *SBucket) GetGlobalId() string {
|
||||
return b.BucketName
|
||||
}
|
||||
|
||||
func (b *SBucket) GetName() string {
|
||||
return b.BucketName
|
||||
}
|
||||
|
||||
func (b *SBucket) GetLocation() string {
|
||||
return b.Region
|
||||
}
|
||||
|
||||
func (b *SBucket) GetIRegion() cloudprovider.ICloudRegion {
|
||||
return b.region
|
||||
}
|
||||
|
||||
func (b *SBucket) GetCreateAt() time.Time {
|
||||
return time.Unix(b.CreateTime, 0)
|
||||
}
|
||||
|
||||
func (b *SBucket) GetStorageClass() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *SBucket) GetAcl() string {
|
||||
return b.Type
|
||||
}
|
||||
|
||||
func (b *SBucket) GetAccessUrls() []cloudprovider.SBucketAccessUrl {
|
||||
ret := make([]cloudprovider.SBucketAccessUrl, 0)
|
||||
regionId := b.region.GetId()
|
||||
// hack, remove trailing digits
|
||||
for len(regionId) > 0 {
|
||||
lastDigit := regionId[len(regionId)-1]
|
||||
if lastDigit >= '0' && lastDigit <= '9' {
|
||||
regionId = regionId[:len(regionId)-1]
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
ret = append(ret, cloudprovider.SBucketAccessUrl{
|
||||
Url: fmt.Sprintf("https://%s.%s.ufileos.com", b.BucketName, regionId),
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -50,10 +50,10 @@ func doListPart(client *SUcloudClient, action string, params SParams, resultKey
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
total, err := ret.Int("TotalCount")
|
||||
if err != nil {
|
||||
log.Debugf("%s TotalCount %s", action, err.Error())
|
||||
}
|
||||
total, _ := ret.Int("TotalCount")
|
||||
// if err != nil {
|
||||
// log.Debugf("%s TotalCount %s", action, err.Error())
|
||||
//}
|
||||
|
||||
var lst []jsonutils.JSONObject
|
||||
lst, err = ret.GetArray(resultKey)
|
||||
|
||||
@@ -29,6 +29,8 @@ import (
|
||||
|
||||
type SRegion struct {
|
||||
multicloud.SRegion
|
||||
multicloud.SNoObjectStorageRegion
|
||||
|
||||
client *SZStackClient
|
||||
|
||||
Name string
|
||||
|
||||
Reference in New Issue
Block a user