Merge pull request #8637 from tb365/bugfix/tb-qcloud-redis-bugfix-20201103

Bugfix/tb qcloud redis bugfix 20201103
This commit is contained in:
Zexi Li
2020-11-04 11:21:28 +08:00
committed by GitHub
7 changed files with 71 additions and 23 deletions
+9
View File
@@ -22,6 +22,7 @@ import (
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/billing"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/billing"
@@ -60,6 +61,14 @@ func (self *SBillingResourceBase) getBillingBaseInfo() SBillingBaseInfo {
return info
}
func (self *SBillingResourceBase) IsNotDeletablePrePaid() bool {
if options.Options.PrepaidDeleteExpireCheck {
return self.IsValidPrePaid()
}
return false
}
func (self *SBillingResourceBase) IsValidPrePaid() bool {
if self.BillingType == api.BILLING_TYPE_PREPAID {
now := time.Now().UTC()
+1 -1
View File
@@ -1101,7 +1101,7 @@ func (self *SDisk) validateDeleteCondition(ctx context.Context, isPurge bool) er
if cnt > 0 {
return httperrors.NewNotEmptyError("Virtual disk %s(%s) used by virtual servers", self.Name, self.Id)
}
if !isPurge && self.IsValidPrePaid() {
if !isPurge && self.IsNotDeletablePrePaid() {
return httperrors.NewForbiddenError("not allow to delete prepaid disk in valid status")
}
return self.SVirtualResourceBase.ValidateDeleteCondition(ctx)
+1 -1
View File
@@ -1096,7 +1096,7 @@ func (self *SElasticcache) ValidateDeleteCondition(ctx context.Context) error {
return httperrors.NewInvalidStatusError("Elastic cache is locked, cannot delete")
}
if self.GetChargeType() == billing.BILLING_TYPE_PREPAID && self.ExpiredAt.Sub(time.Now()).Seconds() > 0 {
if self.IsNotDeletablePrePaid() {
return httperrors.NewInvalidStatusError("Elastic cache is not expired, cannot delete")
}
+1 -1
View File
@@ -623,7 +623,7 @@ func (guest *SGuest) validateDeleteCondition(ctx context.Context, isPurge bool)
if guest.DisableDelete.IsTrue() {
return httperrors.NewInvalidStatusError("Virtual server is locked, cannot delete")
}
if !isPurge && guest.IsValidPrePaid() {
if !isPurge && guest.IsNotDeletablePrePaid() {
return httperrors.NewForbiddenError("not allow to delete prepaid server in valid status")
}
return guest.SVirtualResourceBase.ValidateDeleteCondition(ctx)
+1
View File
@@ -40,6 +40,7 @@ type ComputeOptions struct {
pending_delete.SPendingDeleteOptions
PrepaidExpireCheck bool `default:"false" help:"clean expired servers or disks"`
PrepaidDeleteExpireCheck bool `default:"true" help:"check prepaid expired before delete"`
PrepaidExpireCheckSeconds int `default:"600" help:"How long to wait to scan expired prepaid VM or disks, default is 10 minutes"`
ExpiredPrepaidMaxCleanBatchSize int `default:"50" help:"How many expired prepaid servers can be deleted in a batch"`
+22 -5
View File
@@ -602,12 +602,17 @@ func (self *SElasticcache) Restart() error {
// https://cloud.tencent.com/document/product/239/34440
func (self *SElasticcache) Delete() error {
err := self.Destroy()
if err != nil {
return errors.Wrap(err, "Destroy")
if self.GetBillingType() == billing_api.BILLING_TYPE_POSTPAID {
if err := self.DestroyPostpaidInstance(); err != nil {
return errors.Wrap(err, "DestroyPostpaidInstance")
}
} else {
if err := self.DestroyPrepaidInstance(); err != nil {
return errors.Wrap(err, "DestroyPrepaidInstance")
}
}
err = cloudprovider.WaitStatus(self, api.ELASTIC_CACHE_STATUS_RELEASING, 5*time.Second, 180*time.Second)
err := cloudprovider.WaitStatus(self, api.ELASTIC_CACHE_STATUS_RELEASING, 5*time.Second, 180*time.Second)
if err != nil {
return errors.Wrap(err, "WaitStatus.releasing")
}
@@ -621,7 +626,19 @@ func (self *SElasticcache) Delete() error {
}
// https://cloud.tencent.com/document/product/239/34439
func (self *SElasticcache) Destroy() error {
func (self *SElasticcache) DestroyPrepaidInstance() error {
params := map[string]string{}
params["InstanceId"] = self.GetId()
_, err := self.region.redisRequest("DestroyPrepaidInstance", params)
if err != nil {
return errors.Wrap(err, "DestroyPrepaidInstance")
}
return nil
}
// https://cloud.tencent.com/document/product/239/34439
func (self *SElasticcache) DestroyPostpaidInstance() error {
params := map[string]string{}
params["InstanceId"] = self.GetId()
_, err := self.region.redisRequest("DestroyPostpaidInstance", params)
+36 -15
View File
@@ -1063,23 +1063,44 @@ func (r *SRegion) CreateIElasticcaches(ec *cloudprovider.SCloudElasticCacheInput
return nil, errors.Wrap(err, "CreateInstances")
}
instanceId, err := resp.GetString("DealId")
if err != nil {
return nil, errors.Wrap(err, "dealId")
instanceId := ""
if resp.Contains("InstanceIds") {
ids := []string{}
if err := resp.Unmarshal(&ids, "InstanceIds"); err != nil {
log.Debugf("Unmarshal.InstanceIds %s", resp)
} else {
if len(ids) > 0 {
instanceId = ids[0]
}
}
}
// try to fetch instance id from deal id
if len(instanceId) == 0 {
dealId, err := resp.GetString("DealId")
if err != nil {
return nil, errors.Wrap(err, "dealId")
}
// maybe is a dealId not a instance ID.
if strings.HasPrefix(dealId, "crs-") {
instanceId = dealId
} else {
err = cloudprovider.Wait(5*time.Second, 900*time.Second, func() (bool, error) {
_realInstanceId, err := r.GetElasticcacheIdByDeal(dealId)
if err != nil {
return false, nil
}
instanceId = _realInstanceId
return true, nil
})
if err != nil {
return nil, errors.Wrap(err, "Wait.GetElasticcacheIdByDeal")
}
}
}
//instanceId := ""
//err = cloudprovider.Wait(5*time.Second, 900*time.Second, func() (bool, error) {
// instanceId, err = r.GetElasticcacheIdByDeal(dealId)
// if err != nil {
// return false, nil
// }
//
// return true, nil
//})
//if err != nil {
// return nil, errors.Wrap(err, "Wait.GetElasticcacheIdByDeal")
//}
err = r.SetResourceTags("redis", "instance", []string{instanceId}, ec.Tags, false)
if err != nil {
log.Errorf("SetResourceTags(redis:%s,error:%s)", instanceId, err)