feature: s3gateway

This commit is contained in:
Qiu Jian
2019-07-24 21:28:37 +08:00
parent 79a824e6dc
commit 870813f04b
188 changed files with 42409 additions and 98 deletions
+63
View File
@@ -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",
},
}
}
+134
View File
@@ -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
}
+18 -9
View File
@@ -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
View File
@@ -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
}
}
+61
View File
@@ -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",
},
}
}
+108
View File
@@ -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
}
+26 -4
View File
@@ -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
})
+46
View File
@@ -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)
}
+55
View File
@@ -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
})
}
+11 -3
View File
@@ -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
})
}
+202 -8
View File
@@ -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
}
+1
View File
@@ -45,6 +45,7 @@ const (
type SESXiClient struct {
cloudprovider.SFakeOnPremiseRegion
multicloud.SRegion
multicloud.SNoObjectStorageRegion
providerId string
providerName string
+25 -4
View File
@@ -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)
+75
View File
@@ -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
View File
@@ -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
}
+61
View File
@@ -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
})
}
+20
View File
@@ -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
}
+63
View File
@@ -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
View File
@@ -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)
}
+4
View File
@@ -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())
}
+32 -3
View File
@@ -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
})
+2
View File
@@ -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
+85
View File
@@ -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
}
+43
View File
@@ -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
})
}
+56 -1
View File
@@ -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
}
+4 -4
View File
@@ -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)
+2
View File
@@ -29,6 +29,8 @@ import (
type SRegion struct {
multicloud.SRegion
multicloud.SNoObjectStorageRegion
client *SZStackClient
Name string