mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #7241 from ioito/automated-cherry-pick-of-#7225-upstream-release-3.2
Automated cherry pick of #7225: fix: rds备份恢复优化
This commit is contained in:
@@ -675,22 +675,19 @@ func (self *SDBInstance) AllowPerformRecovery(ctx context.Context, userCred mccl
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "recovery")
|
||||
}
|
||||
|
||||
func (self *SDBInstance) PerformRecovery(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
func (self *SDBInstance) PerformRecovery(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SDBInstanceRecoveryConfigInput) (jsonutils.JSONObject, error) {
|
||||
if !utils.IsInStringArray(self.Status, []string{api.DBINSTANCE_RUNNING}) {
|
||||
return nil, httperrors.NewInvalidStatusError("Cannot do recovery dbinstance in status %s required status %s", self.Status, api.DBINSTANCE_RUNNING)
|
||||
}
|
||||
|
||||
params := data.(*jsonutils.JSONDict)
|
||||
backupV := validators.NewModelIdOrNameValidator("dbinstancebackup", "dbinstancebackup", userCred)
|
||||
err := backupV.Validate(params)
|
||||
_backup, err := DBInstanceBackupManager.FetchByIdOrName(userCred, input.DBInstancebackupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
input := &api.SDBInstanceRecoveryConfigInput{}
|
||||
err = params.Unmarshal(input)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Failed to unmarshal input config: %v", err)
|
||||
if errors.Cause(err) == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2("dbinstancebackup", input.DBInstancebackupId)
|
||||
}
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
input.DBInstancebackupId = _backup.GetId()
|
||||
|
||||
databases, err := self.GetDBInstanceDatabases()
|
||||
if err != nil {
|
||||
@@ -702,7 +699,7 @@ func (self *SDBInstance) PerformRecovery(ctx context.Context, userCred mcclient.
|
||||
dbDatabases = append(dbDatabases, database.Name)
|
||||
}
|
||||
|
||||
backup := backupV.Model.(*SDBInstanceBackup)
|
||||
backup := _backup.(*SDBInstanceBackup)
|
||||
for src, dest := range input.Databases {
|
||||
if len(dest) == 0 {
|
||||
dest = src
|
||||
@@ -725,6 +722,20 @@ func (self *SDBInstance) PerformRecovery(ctx context.Context, userCred mcclient.
|
||||
return nil, httperrors.NewInputParameterError("backup and instance not in same cloudregion")
|
||||
}
|
||||
|
||||
if len(backup.Engine) > 0 && backup.Engine != self.Engine {
|
||||
return nil, httperrors.NewInputParameterError("can not recover data from diff rds engine")
|
||||
}
|
||||
|
||||
driver, err := self.GetRegionDriver()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
|
||||
err = driver.ValidateDBInstanceRecovery(ctx, userCred, self, backup, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, self.StartDBInstanceRecoveryTask(ctx, userCred, input.JSON(input), "")
|
||||
}
|
||||
|
||||
|
||||
@@ -162,6 +162,8 @@ type IDBInstanceDriver interface {
|
||||
|
||||
InitDBInstanceUser(dbinstance *SDBInstance, task taskman.ITask, desc *cloudprovider.SManagedDBInstanceCreateConfig) error
|
||||
IsDBInstanceNeedSecgroup() bool
|
||||
|
||||
ValidateDBInstanceRecovery(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, backup *SDBInstanceBackup, input api.SDBInstanceRecoveryConfigInput) error
|
||||
}
|
||||
|
||||
type IElasticcacheDriver interface {
|
||||
|
||||
@@ -174,26 +174,25 @@ func (manager *SWireResourceBaseManager) ListItemFilter(
|
||||
return nil, errors.Wrap(err, "SVpcResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
|
||||
if len(query.Zone) > 0 || len(query.Zones) > 0 {
|
||||
if len(query.ZoneList()) > 0 {
|
||||
region := &SCloudregion{}
|
||||
if len(query.Zone) > 0 {
|
||||
sq := ZoneManager.Query().SubQuery()
|
||||
q := CloudregionManager.Query()
|
||||
q = q.Join(sq, sqlchemy.Equals(sq.Field("cloudregion_id"), q.Field("id"))).Filter(sqlchemy.OR(
|
||||
sqlchemy.Equals(sq.Field("id"), query.Zone),
|
||||
sqlchemy.Equals(sq.Field("name"), query.Zone),
|
||||
))
|
||||
count, err := q.CountWithError()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CountWithError")
|
||||
}
|
||||
if count < 1 {
|
||||
return nil, httperrors.NewResourceNotFoundError2("zone", query.Zone)
|
||||
}
|
||||
err = q.First(region)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "q.First")
|
||||
}
|
||||
firstZone := query.FirstZone()
|
||||
sq := ZoneManager.Query().SubQuery()
|
||||
q := CloudregionManager.Query()
|
||||
q = q.Join(sq, sqlchemy.Equals(sq.Field("cloudregion_id"), q.Field("id"))).Filter(sqlchemy.OR(
|
||||
sqlchemy.Equals(sq.Field("id"), firstZone),
|
||||
sqlchemy.Equals(sq.Field("name"), firstZone),
|
||||
))
|
||||
count, err := q.CountWithError()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CountWithError")
|
||||
}
|
||||
if count < 1 {
|
||||
return nil, httperrors.NewResourceNotFoundError2("zone", firstZone)
|
||||
}
|
||||
err = q.First(region)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "q.First")
|
||||
}
|
||||
if utils.IsInStringArray(region.Provider, api.REGIONAL_NETWORK_PROVIDERS) {
|
||||
vpcQ := VpcManager.Query().SubQuery()
|
||||
|
||||
@@ -975,6 +975,10 @@ func (self *SAliyunRegionDriver) IsSecurityGroupBelongVpc() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SAliyunRegionDriver) ValidateDBInstanceRecovery(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, backup *models.SDBInstanceBackup, input api.SDBInstanceRecoveryConfigInput) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAliyunRegionDriver) ValidateCreateDBInstanceData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input api.DBInstanceCreateInput, skus []models.SDBInstanceSku, network *models.SNetwork) (api.DBInstanceCreateInput, error) {
|
||||
if input.BillingType == billing_api.BILLING_TYPE_PREPAID && len(input.MasterInstanceId) > 0 {
|
||||
return input, httperrors.NewInputParameterError("slave dbinstance not support prepaid billing type")
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -336,6 +337,10 @@ func (self *SBaseRegionDriver) IsSupportKeepDBInstanceManualBackup() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) ValidateDBInstanceRecovery(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, backup *models.SDBInstanceBackup, input api.SDBInstanceRecoveryConfigInput) error {
|
||||
return errors.Wrap(cloudprovider.ErrNotImplemented, "ValidateDBInstanceRecovery")
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) IsSupportedDBInstance() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -184,6 +184,10 @@ func (self *SGoogleRegionDriver) IsSupportedDBInstance() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SGoogleRegionDriver) ValidateDBInstanceRecovery(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, backup *models.SDBInstanceBackup, input api.SDBInstanceRecoveryConfigInput) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGoogleRegionDriver) ValidateCreateDBInstanceData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input api.DBInstanceCreateInput, skus []models.SDBInstanceSku, network *models.SNetwork) (api.DBInstanceCreateInput, error) {
|
||||
if input.BillingType == billing_api.BILLING_TYPE_PREPAID {
|
||||
return input, httperrors.NewInputParameterError("Google dbinstance not support prepaid billing type")
|
||||
|
||||
@@ -2275,6 +2275,28 @@ func (self *SHuaWeiRegionDriver) ValidateDBInstanceAccountPrivilege(ctx context.
|
||||
return nil
|
||||
}
|
||||
|
||||
// https://support.huaweicloud.com/api-rds/rds_09_0009.html
|
||||
func (self *SHuaWeiRegionDriver) ValidateDBInstanceRecovery(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, backup *models.SDBInstanceBackup, input api.SDBInstanceRecoveryConfigInput) error {
|
||||
if backup.Engine == api.DBINSTANCE_TYPE_POSTGRESQL {
|
||||
return httperrors.NewNotSupportedError("%s not support recovery", backup.Engine)
|
||||
}
|
||||
if backup.DBInstanceId == instance.Id && instance.Engine != api.DBINSTANCE_TYPE_SQLSERVER {
|
||||
return httperrors.NewNotSupportedError("Huawei %s rds not support recovery from it self rds backup", instance.Engine)
|
||||
}
|
||||
if len(input.Databases) > 0 {
|
||||
if instance.Engine != api.DBINSTANCE_TYPE_SQLSERVER {
|
||||
return httperrors.NewInputParameterError("Huawei only %s engine support databases recovery", instance.Engine)
|
||||
}
|
||||
invalidDbs := []string{"rdsadmin", "master", "msdb", "tempdb", "model"}
|
||||
for _, db := range input.Databases {
|
||||
if utils.IsInStringArray(strings.ToLower(db), invalidDbs) {
|
||||
return httperrors.NewInputParameterError("New databases name can not be one of %s", invalidDbs)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validatorSlaveZones(ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict, optional bool) error {
|
||||
s, err := data.GetString("slave_zones")
|
||||
if err != nil {
|
||||
|
||||
@@ -60,16 +60,22 @@ func (self *DBInstanceRecoveryTask) OnInit(ctx context.Context, obj db.IStandalo
|
||||
return
|
||||
}
|
||||
|
||||
backup, err := instance.GetDBInstanceBackup(input.DBInstancebackupId)
|
||||
_backup, err := models.DBInstanceBackupManager.FetchById(input.DBInstancebackupId)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, instance, errors.Wrapf(err, "instance.GetDBInstanceBackup(%s)", input.DBInstancebackupId))
|
||||
return
|
||||
}
|
||||
|
||||
backup := _backup.(*models.SDBInstanceBackup)
|
||||
origin, _ := backup.GetDBInstance()
|
||||
|
||||
conf := &cloudprovider.SDBInstanceRecoveryConfig{
|
||||
BackupId: backup.ExternalId,
|
||||
Databases: input.Databases,
|
||||
}
|
||||
if origin != nil {
|
||||
conf.OriginDBInstanceExternalId = origin.ExternalId
|
||||
}
|
||||
|
||||
err = iRds.RecoveryFromBackup(conf)
|
||||
if err != nil {
|
||||
@@ -77,12 +83,14 @@ func (self *DBInstanceRecoveryTask) OnInit(ctx context.Context, obj db.IStandalo
|
||||
return
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(iRds, api.DBINSTANCE_RUNNING, time.Second*10, time.Second*40)
|
||||
err = cloudprovider.WaitStatus(iRds, api.DBINSTANCE_RUNNING, time.Second*10, time.Minute*40)
|
||||
if err != nil {
|
||||
self.taskFailed(ctx, instance, errors.Wrap(err, "cloudprovider.WaitStatus(running)"))
|
||||
return
|
||||
}
|
||||
|
||||
db.OpsLog.LogEvent(instance, db.ACT_RESTORE, nil, self.GetUserCred())
|
||||
logclient.AddActionLogWithStartable(self, instance, logclient.ACT_RESTORE, backup, self.UserCred, true)
|
||||
instance.SetStatus(self.UserCred, api.DBINSTANCE_RUNNING, "")
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user