diff --git a/pkg/compute/models/buckets.go b/pkg/compute/models/buckets.go index 8aaca848ed..ade03163be 100644 --- a/pkg/compute/models/buckets.go +++ b/pkg/compute/models/buckets.go @@ -782,11 +782,15 @@ func (bucket *SBucket) PerformSync( return nil, nil } +func (bucket *SBucket) ValidatePurgeCondition(ctx context.Context) error { + return bucket.SVirtualResourceBase.ValidateDeleteCondition(ctx) +} + func (bucket *SBucket) ValidateDeleteCondition(ctx context.Context) error { if bucket.ObjectCnt > 0 { return httperrors.NewNotEmptyError("not an empty bucket") } - return bucket.SVirtualResourceBase.ValidateDeleteCondition(ctx) + return bucket.ValidatePurgeCondition(ctx) } func (bucket *SBucket) AllowGetDetailsAcl( diff --git a/pkg/compute/models/purge.go b/pkg/compute/models/purge.go index 3021f00999..1273b453c5 100644 --- a/pkg/compute/models/purge.go +++ b/pkg/compute/models/purge.go @@ -1044,7 +1044,7 @@ func (bucket *SBucket) purge(ctx context.Context, userCred mcclient.TokenCredent lockman.LockObject(ctx, bucket) defer lockman.ReleaseObject(ctx, bucket) - err := bucket.ValidateDeleteCondition(ctx) + err := bucket.ValidatePurgeCondition(ctx) if err != nil { return err } diff --git a/pkg/multicloud/qcloud/bucket.go b/pkg/multicloud/qcloud/bucket.go index 9d603de729..6536f39dbf 100644 --- a/pkg/multicloud/qcloud/bucket.go +++ b/pkg/multicloud/qcloud/bucket.go @@ -37,7 +37,6 @@ type SBucket struct { region *SRegion Name string - FullName string Location string CreateDate time.Time } @@ -130,8 +129,12 @@ func (b *SBucket) SetAcl(aclStr cloudprovider.TBucketACLType) error { return nil } +func (b *SBucket) getFullName() string { + return fmt.Sprintf("%s-%s", b.Name, b.region.client.AppID) +} + func (b *SBucket) getBucketUrl() string { - return fmt.Sprintf("https://%s.%s", b.FullName, b.region.getCosEndpoint()) + return fmt.Sprintf("https://%s.%s", b.getFullName(), b.region.getCosEndpoint()) } func (b *SBucket) GetAccessUrls() []cloudprovider.SBucketAccessUrl { @@ -141,7 +144,7 @@ func (b *SBucket) GetAccessUrls() []cloudprovider.SBucketAccessUrl { Description: "bucket domain", }, { - Url: fmt.Sprintf("https://%s/%s", b.region.getCosEndpoint(), b.FullName), + Url: fmt.Sprintf("https://%s/%s", b.region.getCosEndpoint(), b.getFullName()), Description: "cos domain", }, } diff --git a/pkg/multicloud/qcloud/qcloud.go b/pkg/multicloud/qcloud/qcloud.go index 16001bfc13..76347b5625 100644 --- a/pkg/multicloud/qcloud/qcloud.go +++ b/pkg/multicloud/qcloud/qcloud.go @@ -33,10 +33,11 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/pkg/errors" + "yunion.io/x/pkg/util/timeutils" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudprovider" - "yunion.io/x/pkg/util/timeutils" + "yunion.io/x/onecloud/pkg/util/httputils" ) const ( @@ -61,7 +62,7 @@ type SQcloudClient struct { ownerName string iregions []cloudprovider.ICloudRegion - iBuckets []cloudprovider.ICloudBucket + ibuckets []cloudprovider.ICloudBucket Debug bool } @@ -79,6 +80,10 @@ func NewQcloudClient(providerId string, providerName string, secretID string, se if err != nil { return nil, errors.Wrap(err, "fetchRegions") } + err = client.verifyAppId() + if err != nil { + return nil, errors.Wrap(err, "verifyAppId") + } err = client.fetchBuckets() if err != nil { return nil, errors.Wrap(err, "fetchBuckets") @@ -501,17 +506,41 @@ func (client *SQcloudClient) getCosClient(bucket *SBucket) (*cos.Client, error) } func (self *SQcloudClient) invalidateIBuckets() { - self.iBuckets = nil + self.ibuckets = nil } func (self *SQcloudClient) getIBuckets() ([]cloudprovider.ICloudBucket, error) { - if self.iBuckets == nil { + if self.ibuckets == nil { err := self.fetchBuckets() if err != nil { return nil, errors.Wrap(err, "fetchBuckets") } } - return self.iBuckets, nil + return self.ibuckets, nil +} + +func (client *SQcloudClient) verifyAppId() error { + region, err := client.getDefaultRegion() + if err != nil { + return errors.Wrap(err, "getDefaultRegion") + } + bucket := SBucket{ + region: region.(*SRegion), + Name: "yuniondocument", + } + cli, err := client.getCosClient(&bucket) + if err != nil { + return errors.Wrap(err, "getCosClient") + } + resp, err := cli.Bucket.Head(context.Background()) + if resp != nil { + defer httputils.CloseResponse(resp.Response) + if resp.StatusCode < 400 || resp.StatusCode == 404 { + return nil + } + return errors.Error(fmt.Sprintf("invalid AppId: %d", resp.StatusCode)) + } + return errors.Wrap(err, "Head") } func (client *SQcloudClient) fetchBuckets() error { @@ -539,16 +568,14 @@ func (client *SQcloudClient) fetchBuckets() error { continue } b := SBucket{ - region: region.(*SRegion), - + region: region.(*SRegion), Name: name, - FullName: bInfo.Name, Location: bInfo.Region, CreateDate: createAt, } ret = append(ret, &b) } - client.iBuckets = ret + client.ibuckets = ret return nil } diff --git a/pkg/multicloud/qcloud/region.go b/pkg/multicloud/qcloud/region.go index 95772e9db2..81b5c9b0bd 100644 --- a/pkg/multicloud/qcloud/region.go +++ b/pkg/multicloud/qcloud/region.go @@ -843,9 +843,8 @@ func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) { func (region *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error { bucket := &SBucket{ - region: region, - Name: name, - FullName: fmt.Sprintf("%s-%s", name, region.client.AppID), + region: region, + Name: name, } coscli, err := region.GetCosClient(bucket) if err != nil { @@ -878,9 +877,8 @@ func cosHttpCode(err error) int { func (region *SRegion) DeleteIBucket(name string) error { bucket := &SBucket{ - region: region, - Name: name, - FullName: fmt.Sprintf("%s-%s", name, region.client.AppID), + region: region, + Name: name, } coscli, err := region.GetCosClient(bucket) if err != nil { @@ -898,9 +896,8 @@ func (region *SRegion) DeleteIBucket(name string) error { func (region *SRegion) IBucketExist(name string) (bool, error) { bucket := &SBucket{ - region: region, - Name: name, - FullName: fmt.Sprintf("%s-%s", name, region.client.AppID), + region: region, + Name: name, } coscli, err := region.GetCosClient(bucket) if err != nil { diff --git a/pkg/util/httputils/httputils.go b/pkg/util/httputils/httputils.go index d233d5fe95..9641a29f35 100644 --- a/pkg/util/httputils/httputils.go +++ b/pkg/util/httputils/httputils.go @@ -233,7 +233,7 @@ func JSONRequest(client *http.Client, ctx context.Context, method THttpMethod, u // // Subsequently this allows golang http RoundTripper // to re-use the same connection for future requests. -func closeResponse(resp *http.Response) { +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 @@ -255,7 +255,7 @@ func ParseJSONResponse(resp *http.Response, err error, debug bool) (http.Header, ce.Details = err.Error() return nil, nil, &ce } - defer closeResponse(resp) + defer CloseResponse(resp) if debug { if resp.StatusCode < 300 { green("Status:", resp.StatusCode)