| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package models
- import (
- "context"
- "database/sql"
- "fmt"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/compare"
- "yunion.io/x/pkg/util/rbacscope"
- "yunion.io/x/pkg/utils"
- "yunion.io/x/sqlchemy"
- api "yunion.io/x/onecloud/pkg/apis/compute"
- "yunion.io/x/onecloud/pkg/cloudcommon/db"
- "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
- "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
- "yunion.io/x/onecloud/pkg/httperrors"
- "yunion.io/x/onecloud/pkg/mcclient"
- "yunion.io/x/onecloud/pkg/util/seclib2"
- "yunion.io/x/onecloud/pkg/util/stringutils2"
- )
- // +onecloud:swagger-gen-model-singular=dbinstanceaccount
- // +onecloud:swagger-gen-model-plural=dbinstanceaccounts
- type SDBInstanceAccountManager struct {
- db.SStatusStandaloneResourceBaseManager
- SDBInstanceResourceBaseManager
- }
- var DBInstanceAccountManager *SDBInstanceAccountManager
- func init() {
- DBInstanceAccountManager = &SDBInstanceAccountManager{
- SStatusStandaloneResourceBaseManager: db.NewStatusStandaloneResourceBaseManager(
- SDBInstanceAccount{},
- "dbinstanceaccounts_tbl",
- "dbinstanceaccount",
- "dbinstanceaccounts",
- ),
- }
- DBInstanceAccountManager.SetVirtualObject(DBInstanceAccountManager)
- }
- type SDBInstanceAccount struct {
- db.SStatusStandaloneResourceBase
- Host string `width:"32" charset:"ascii" nullable:"false" list:"user" create:"optional" default:"%"`
- SDBInstanceResourceBase `width:"36" charset:"ascii" name:"dbinstance_id" nullable:"false" list:"user" create:"required" index:"true"`
- // 数据库密码
- Secret string `width:"256" charset:"ascii" nullable:"false" list:"user" create:"optional"`
- }
- func (manager *SDBInstanceAccountManager) GetContextManagers() [][]db.IModelManager {
- return [][]db.IModelManager{
- {DBInstanceManager},
- }
- }
- func (manager *SDBInstanceAccountManager) ResourceScope() rbacscope.TRbacScope {
- return rbacscope.ScopeProject
- }
- func (self *SDBInstanceAccount) GetOwnerId() mcclient.IIdentityProvider {
- instance, err := self.GetDBInstance()
- if err != nil {
- log.Errorf("failed to get instance for account %s(%s)", self.Name, self.Id)
- return nil
- }
- return instance.GetOwnerId()
- }
- func (manager *SDBInstanceAccountManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
- dbinstanceId, _ := data.GetString("dbinstance_id")
- if len(dbinstanceId) > 0 {
- instance, err := db.FetchById(DBInstanceManager, dbinstanceId)
- if err != nil {
- return nil, errors.Wrapf(err, "db.FetchById(DBInstanceManager, %s)", dbinstanceId)
- }
- return instance.(*SDBInstance).GetOwnerId(), nil
- }
- return db.FetchProjectInfo(ctx, data)
- }
- func (manager *SDBInstanceAccountManager) FilterByOwner(ctx context.Context, q *sqlchemy.SQuery, man db.FilterByOwnerProvider, userCred mcclient.TokenCredential, owner mcclient.IIdentityProvider, scope rbacscope.TRbacScope) *sqlchemy.SQuery {
- if owner != nil {
- sq := DBInstanceManager.Query("id")
- switch scope {
- case rbacscope.ScopeProject:
- sq = sq.Equals("tenant_id", owner.GetProjectId())
- return q.In("dbinstance_id", sq.SubQuery())
- case rbacscope.ScopeDomain:
- sq = sq.Equals("domain_id", owner.GetProjectDomainId())
- return q.In("dbinstance_id", sq.SubQuery())
- }
- }
- return q
- }
- func (self *SDBInstanceAccount) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.DBInstanceAccountUpdateInput) (api.DBInstanceAccountUpdateInput, error) {
- var err error
- input.StatusStandaloneResourceBaseUpdateInput, err = self.SStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.StatusStandaloneResourceBaseUpdateInput)
- if err != nil {
- return input, errors.Wrapf(err, "SStatusStandaloneResourceBase.ValidateUpdateData")
- }
- if len(input.Name) > 0 && input.Name != self.Name {
- return input, httperrors.NewForbiddenError("not allow update rds account name")
- }
- return input, nil
- }
- func (self *SDBInstanceAccount) getPrivilegesDetails() ([]api.DBInstancePrivilege, error) {
- out := []api.DBInstancePrivilege{}
- privileges, err := self.GetDBInstancePrivileges()
- if err != nil {
- return nil, errors.Wrap(err, "GetDBInstancePrivileges")
- }
- for _, privilege := range privileges {
- detail, err := privilege.GetPrivilege()
- if err != nil {
- return nil, errors.Wrap(err, "GetDetailedJson")
- }
- out = append(out, detail)
- }
- return out, nil
- }
- func (self *SDBInstanceAccount) getMoreDetails(ctx context.Context, userCred mcclient.TokenCredential, out api.DBInstanceAccountDetails) (api.DBInstanceAccountDetails, error) {
- privileges, err := self.getPrivilegesDetails()
- if err != nil {
- return out, err
- }
- out.DBInstanceprivileges = privileges
- return out, nil
- }
- func (manager *SDBInstanceAccountManager) FetchCustomizeColumns(
- ctx context.Context,
- userCred mcclient.TokenCredential,
- query jsonutils.JSONObject,
- objs []interface{},
- fields stringutils2.SSortedStrings,
- isList bool,
- ) []api.DBInstanceAccountDetails {
- rows := make([]api.DBInstanceAccountDetails, len(objs))
- stdRows := manager.SStatusStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
- dbRows := manager.SDBInstanceResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
- dbinstanceIds := make([]string, len(objs))
- for i := range rows {
- rows[i] = api.DBInstanceAccountDetails{
- StatusStandaloneResourceDetails: stdRows[i],
- DBInstanceResourceInfo: dbRows[i],
- }
- account := objs[i].(*SDBInstanceAccount)
- rows[i], _ = account.getMoreDetails(ctx, userCred, rows[i])
- dbinstanceIds[i] = account.DBInstanceId
- }
- dbinstances := make(map[string]SDBInstance)
- err := db.FetchStandaloneObjectsByIds(DBInstanceManager, dbinstanceIds, &dbinstances)
- if err != nil {
- log.Errorf("FetchStandaloneObjectsByIds fail: %v", err)
- return rows
- }
- virObjs := make([]interface{}, len(objs))
- for i := range rows {
- if dbinstance, ok := dbinstances[dbinstanceIds[i]]; ok {
- virObjs[i] = &dbinstance
- rows[i].ProjectId = dbinstance.ProjectId
- }
- }
- projRows := DBInstanceManager.SProjectizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, virObjs, stringutils2.SSortedStrings{}, isList)
- for i := range rows {
- rows[i].ProjectizedResourceInfo = projRows[i]
- }
- return rows
- }
- // RDS账号列表
- func (manager *SDBInstanceAccountManager) ListItemFilter(
- ctx context.Context,
- q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential,
- query api.DBInstanceAccountListInput,
- ) (*sqlchemy.SQuery, error) {
- q, err := manager.SStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StatusStandaloneResourceListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.ListItemFilter")
- }
- q, err = manager.SDBInstanceResourceBaseManager.ListItemFilter(ctx, q, userCred, query.DBInstanceFilterListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SDBInstanceResourceBaseManager.ListItemFilter")
- }
- return q, nil
- }
- func (manager *SDBInstanceAccountManager) OrderByExtraFields(
- ctx context.Context,
- q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential,
- query api.DBInstanceAccountListInput,
- ) (*sqlchemy.SQuery, error) {
- q, err := manager.SStatusStandaloneResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StatusStandaloneResourceListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.OrderByExtraFields")
- }
- q, err = manager.SDBInstanceResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.DBInstanceFilterListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SDBInstanceResourceBaseManager.OrderByExtraFields")
- }
- return q, nil
- }
- func (manager *SDBInstanceAccountManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
- q, err := manager.SStatusStandaloneResourceBaseManager.QueryDistinctExtraField(q, field)
- if err == nil {
- return q, nil
- }
- q, err = manager.SDBInstanceResourceBaseManager.QueryDistinctExtraField(q, field)
- if err == nil {
- return q, nil
- }
- return q, httperrors.ErrNotFound
- }
- type sRdsAccount struct {
- Name string
- DBInstanceId string `json:"dbinstance_id"`
- Host string
- }
- func (self *SDBInstanceAccount) GetUniqValues() jsonutils.JSONObject {
- return jsonutils.Marshal(sRdsAccount{Name: self.Name, DBInstanceId: self.DBInstanceId, Host: self.Host})
- }
- func (manager *SDBInstanceAccountManager) FetchUniqValues(ctx context.Context, data jsonutils.JSONObject) jsonutils.JSONObject {
- info := sRdsAccount{}
- data.Unmarshal(&info)
- return jsonutils.Marshal(info)
- }
- func (manager *SDBInstanceAccountManager) FilterByUniqValues(q *sqlchemy.SQuery, values jsonutils.JSONObject) *sqlchemy.SQuery {
- info := sRdsAccount{}
- values.Unmarshal(&info)
- if len(info.DBInstanceId) > 0 {
- q = q.Equals("dbinstance_id", info.DBInstanceId)
- }
- if len(info.Name) > 0 {
- q = q.Equals("name", info.Name)
- }
- if len(info.Host) > 0 {
- q = q.Equals("host", info.Host)
- }
- return q
- }
- func (manager *SDBInstanceAccountManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.DBInstanceAccountCreateInput) (*jsonutils.JSONDict, error) {
- if len(input.Password) > 0 {
- err := seclib2.ValidatePassword(input.Password)
- if err != nil {
- return nil, err
- }
- } else {
- input.Password = seclib2.RandomPassword2(12)
- }
- for _, instance := range []string{input.DBInstance, input.DBInstanceId} {
- if len(instance) > 0 {
- input.DBInstance = instance
- break
- }
- }
- if len(input.DBInstance) == 0 {
- return nil, httperrors.NewMissingParameterError("dbinstance")
- }
- _instance, err := DBInstanceManager.FetchByIdOrName(ctx, userCred, input.DBInstance)
- if err != nil {
- if err == sql.ErrNoRows {
- return nil, httperrors.NewResourceNotFoundError("failed to found dbinstance %s", input.DBInstance)
- }
- return nil, httperrors.NewGeneralError(errors.Wrap(err, "DBInstanceManager.FetchByIdOrName"))
- }
- instance := _instance.(*SDBInstance)
- input.DBInstanceId = instance.Id
- if instance.Status != api.DBINSTANCE_RUNNING {
- return nil, httperrors.NewInputParameterError("DBInstance %s(%s) status is %s require status is %s", instance.Name, instance.Id, instance.Status, api.DBINSTANCE_RUNNING)
- }
- region, err := instance.GetRegion()
- if err != nil {
- return nil, httperrors.NewGeneralError(errors.Wrapf(err, "GetRegion"))
- }
- for i, privilege := range input.Privileges {
- database, err := instance.GetDBInstanceDatabase(privilege.Database)
- if err != nil {
- return nil, httperrors.NewInputParameterError("failed to found dbinstance %s(%s) database %s: %v", instance.Name, instance.Id, privilege.Database, err)
- }
- input.Privileges[i].DBInstancedatabaseId = database.Id
- }
- input, err = region.GetDriver().ValidateCreateDBInstanceAccountData(ctx, userCred, ownerId, instance, input)
- if err != nil {
- return nil, err
- }
- input.StatusStandaloneResourceCreateInput, err = manager.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusStandaloneResourceCreateInput)
- if err != nil {
- return nil, err
- }
- return input.JSON(input), nil
- }
- func (self *SDBInstanceAccount) SetPassword(passwd string) error {
- return self.savePassword(passwd)
- }
- func (self *SDBInstanceAccount) savePassword(secret string) error {
- sec, err := utils.EncryptAESBase64(self.Id, secret)
- if err != nil {
- return err
- }
- _, err = db.Update(self, func() error {
- self.Secret = sec
- return nil
- })
- return err
- }
- func (self *SDBInstanceAccount) GetPassword() (string, error) {
- return utils.DescryptAESBase64(self.Id, self.Secret)
- }
- func (self *SDBInstanceAccount) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
- self.SStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
- input := &api.DBInstanceAccountCreateInput{}
- data.Unmarshal(input)
- self.savePassword(input.Password)
- self.StartDBInstanceAccountCreateTask(ctx, userCred, data.(*jsonutils.JSONDict), "")
- }
- func (self *SDBInstanceAccount) StartDBInstanceAccountCreateTask(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, parentTaskId string) error {
- self.SetStatus(ctx, userCred, api.DBINSTANCE_USER_CREATING, "")
- task, err := taskman.TaskManager.NewTask(ctx, "DBInstanceAccountCreateTask", self, userCred, data, parentTaskId, "", nil)
- if err != nil {
- return err
- }
- task.ScheduleRun(nil)
- return nil
- }
- func (self *SDBInstanceAccount) PerformGrantPrivilege(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
- instance, err := self.GetDBInstance()
- if err != nil {
- return nil, errors.Wrap(err, "failed to found dbinstance")
- }
- databaseStr, _ := data.GetString("database")
- if len(databaseStr) == 0 {
- return nil, httperrors.NewMissingParameterError("database")
- }
- database, err := instance.GetDBInstanceDatabase(databaseStr)
- if err != nil {
- return nil, httperrors.NewInputParameterError("Failed to found database %s for dbinstance %s(%s): %v", databaseStr, instance.Name, instance.Id, err)
- }
- privilegeStr, _ := data.GetString("privilege")
- if len(privilegeStr) == 0 {
- return nil, httperrors.NewMissingParameterError("privilege")
- }
- privilege, _ := instance.GetDBInstancePrivilege(self.Id, database.Id)
- if privilege != nil {
- return nil, httperrors.NewInputParameterError("The account %s(%s) has permission %s to the database %s(%s)", self.Name, self.Id, privilege.Privilege, database.Name, database.Id)
- }
- region, err := instance.GetRegion()
- if err != nil {
- return nil, httperrors.NewGeneralError(errors.Wrapf(err, "GetRegion"))
- }
- err = region.GetDriver().ValidateDBInstanceAccountPrivilege(ctx, userCred, instance, self.Name, privilegeStr)
- if err != nil {
- return nil, err
- }
- return nil, self.StartGrantPrivilegeTask(ctx, userCred, databaseStr, privilegeStr, "")
- }
- func (self *SDBInstanceAccount) PerformSetPrivileges(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
- instance, err := self.GetDBInstance()
- if err != nil {
- return nil, errors.Wrap(err, "failed to found dbinstance")
- }
- input := api.SDBInstanceSetPrivilegesInput{}
- err = data.Unmarshal(&input)
- if err != nil {
- return nil, httperrors.NewInputParameterError("failed to unmarshal input params: %v", err)
- }
- setPrivilege := map[string]map[string]string{
- "grant": map[string]string{},
- "revoke": map[string]string{},
- "input": map[string]string{},
- }
- region, err := instance.GetRegion()
- if err != nil {
- return nil, errors.Wrapf(err, "GetRegion")
- }
- for i, privilege := range input.Privileges {
- database, err := instance.GetDBInstanceDatabase(privilege.Database)
- if err != nil {
- return nil, httperrors.NewInputParameterError("Failed to found database %s for dbinstance %s(%s): %v", privilege.Database, instance.Name, instance.Id, err)
- }
- input.Privileges[i].DBInstancedatabaseId = database.Id
- err = region.GetDriver().ValidateDBInstanceAccountPrivilege(ctx, userCred, instance, self.Name, privilege.Privilege)
- if err != nil {
- return nil, err
- }
- dbPrivilege, _ := instance.GetDBInstancePrivilege(self.Id, database.Id)
- if dbPrivilege == nil {
- setPrivilege["grant"][database.Id] = privilege.Privilege
- } else if dbPrivilege.Privilege != privilege.Privilege {
- setPrivilege["grant"][database.Id] = privilege.Privilege
- setPrivilege["revoke"][database.Id] = dbPrivilege.Privilege
- }
- setPrivilege["input"][database.Id] = privilege.Privilege
- }
- dbPrivileges, err := self.GetDBInstancePrivileges()
- if err != nil {
- return nil, err
- }
- for _, privilege := range dbPrivileges {
- if _, ok := setPrivilege["input"][privilege.DBInstancedatabaseId]; !ok {
- setPrivilege["revoke"][privilege.DBInstancedatabaseId] = privilege.Privilege
- }
- }
- return nil, self.StartSetPrivilegesTask(ctx, userCred, jsonutils.Marshal(setPrivilege))
- }
- func (self *SDBInstanceAccount) StartSetPrivilegesTask(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error {
- self.SetStatus(ctx, userCred, api.DBINSTANCE_USER_SET_PRIVILEGE, "")
- task, err := taskman.TaskManager.NewTask(ctx, "DBInstanceAccountSetPrivilegesTask", self, userCred, data.(*jsonutils.JSONDict), "", "", nil)
- if err != nil {
- return errors.Wrap(err, "NewTask")
- }
- task.ScheduleRun(nil)
- return nil
- }
- func (self *SDBInstanceAccount) StartGrantPrivilegeTask(ctx context.Context, userCred mcclient.TokenCredential, database string, privilege string, parentTaskId string) error {
- self.SetStatus(ctx, userCred, api.DBINSTANCE_USER_GRANT_PRIVILEGE, "")
- params := jsonutils.NewDict()
- params.Add(jsonutils.NewString(database), "database")
- params.Add(jsonutils.NewString(privilege), "privilege")
- task, err := taskman.TaskManager.NewTask(ctx, "DBInstanceAccountGrantPrivilegeTask", self, userCred, params, parentTaskId, "", nil)
- if err != nil {
- return errors.Wrap(err, "NewTask")
- }
- task.ScheduleRun(nil)
- return nil
- }
- func (self *SDBInstanceAccount) PerformRevokePrivilege(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
- if self.Status != api.DBINSTANCE_USER_AVAILABLE {
- return nil, httperrors.NewInvalidStatusError("Account status is not %s current status is %s", api.DBINSTANCE_USER_AVAILABLE, self.Status)
- }
- instance, err := self.GetDBInstance()
- if err != nil {
- return nil, errors.Wrap(err, "failed to found dbinstance")
- }
- if instance.Status != api.DBINSTANCE_RUNNING {
- return nil, httperrors.NewInvalidStatusError("Instance status is not %s current status is %s", api.DBINSTANCE_RUNNING, instance.Status)
- }
- databaseStr, _ := data.GetString("database")
- if len(databaseStr) == 0 {
- return nil, httperrors.NewMissingParameterError("database")
- }
- database, err := instance.GetDBInstanceDatabase(databaseStr)
- if err != nil {
- return nil, httperrors.NewInputParameterError("Failed to found database %s for dbinstance %s(%s): %v", databaseStr, instance.Name, instance.Id, err)
- }
- if database.Status != api.DBINSTANCE_DATABASE_RUNNING {
- return nil, httperrors.NewInvalidStatusError("Database status is not %s current is %s", api.DBINSTANCE_DATABASE_RUNNING, database.Status)
- }
- privilege, err := instance.GetDBInstancePrivilege(self.Id, database.Id)
- if err != nil {
- if err == sql.ErrNoRows {
- return nil, httperrors.NewInputParameterError("Account %s(%s) does not have database %s(%s) permissions", self.Name, self.Id, database.Name, database.Id)
- }
- return nil, httperrors.NewGeneralError(err)
- }
- return nil, self.StartRevokePrivilegeTask(ctx, userCred, databaseStr, privilege.Privilege, "")
- }
- func (self *SDBInstanceAccount) StartRevokePrivilegeTask(ctx context.Context, userCred mcclient.TokenCredential, database string, privilege string, parentTaskId string) error {
- self.SetStatus(ctx, userCred, api.DBINSTANCE_USER_REVOKE_PRIVILEGE, "")
- params := jsonutils.NewDict()
- params.Add(jsonutils.NewString(database), "database")
- params.Add(jsonutils.NewString(privilege), "privilege")
- task, err := taskman.TaskManager.NewTask(ctx, "DBInstanceAccountRevokePrivilegeTask", self, userCred, params, parentTaskId, "", nil)
- if err != nil {
- return errors.Wrap(err, "NewTask")
- }
- task.ScheduleRun(nil)
- return nil
- }
- func (self *SDBInstanceAccount) PerformResetPassword(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
- instance, err := self.GetDBInstance()
- if err != nil {
- return nil, err
- }
- passwdStr, _ := data.GetString("password")
- if len(passwdStr) > 0 {
- err = seclib2.ValidatePassword(passwdStr)
- if err != nil {
- return nil, err
- }
- }
- region, err := instance.GetRegion()
- if err != nil {
- return nil, err
- }
- err = region.GetDriver().ValidateResetDBInstancePassword(ctx, userCred, instance, self.Name)
- if err != nil {
- return nil, err
- }
- return nil, self.StartDBInstanceAccountResetPasswordTask(ctx, userCred, passwdStr)
- }
- func (self *SDBInstanceAccount) StartDBInstanceAccountResetPasswordTask(ctx context.Context, userCred mcclient.TokenCredential, password string) error {
- params := jsonutils.NewDict()
- if len(password) > 0 {
- params.Add(jsonutils.NewString(password), "password")
- } else {
- params.Add(jsonutils.NewString(seclib2.RandomPassword2(20)), "password")
- }
- self.SetStatus(ctx, userCred, api.DBINSTANCE_USER_RESET_PASSWD, "")
- task, err := taskman.TaskManager.NewTask(ctx, "DBInstanceAccountResetPasswordTask", self, userCred, params, "", "", nil)
- if err != nil {
- return errors.Wrapf(err, "NewTask")
- }
- task.ScheduleRun(nil)
- return nil
- }
- func (self *SDBInstanceAccount) GetDBInstancePrivileges() ([]SDBInstancePrivilege, error) {
- privileges := []SDBInstancePrivilege{}
- q := DBInstancePrivilegeManager.Query().Equals("dbinstanceaccount_id", self.Id)
- err := db.FetchModelObjects(DBInstancePrivilegeManager, q, &privileges)
- if err != nil {
- return nil, errors.Wrapf(err, "GetDBInstancePrivileges.FetchModelObjects for account %s", self.Id)
- }
- return privileges, nil
- }
- func (self *SDBInstanceAccount) GetDBInstanceDatabaseByName(dbName string) (*SDBInstanceDatabase, error) {
- q := DBInstanceDatabaseManager.Query().Equals("dbinstance_id", self.DBInstanceId).Equals("name", dbName)
- count, err := q.CountWithError()
- if err != nil {
- return nil, err
- }
- if count == 1 {
- database := &SDBInstanceDatabase{}
- database.SetModelManager(DBInstanceDatabaseManager, database)
- err = q.First(database)
- if err != nil {
- return nil, err
- }
- return database, nil
- }
- if count > 1 {
- return nil, sqlchemy.ErrDuplicateEntry
- }
- return nil, sql.ErrNoRows
- }
- func (manager *SDBInstanceAccountManager) SyncDBInstanceAccounts(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, cloudAccounts []cloudprovider.ICloudDBInstanceAccount) ([]SDBInstanceAccount, []cloudprovider.ICloudDBInstanceAccount, compare.SyncResult) {
- lockman.LockRawObject(ctx, "dbinstance-accounts", instance.Id)
- defer lockman.ReleaseRawObject(ctx, "dbinstance-accounts", instance.Id)
- result := compare.SyncResult{}
- localAccounts := []SDBInstanceAccount{}
- remoteAccounts := []cloudprovider.ICloudDBInstanceAccount{}
- dbAccounts, err := instance.GetDBInstanceAccounts()
- if err != nil {
- result.Error(err)
- return nil, nil, result
- }
- accountMaps := map[string][]SDBInstanceAccount{}
- for i := range dbAccounts {
- key := fmt.Sprintf("%s:%s", dbAccounts[i].Name, dbAccounts[i].Host)
- _, ok := accountMaps[key]
- if !ok {
- accountMaps[key] = []SDBInstanceAccount{}
- }
- accountMaps[key] = append(accountMaps[key], dbAccounts[i])
- }
- remoteMaps := map[string]cloudprovider.ICloudDBInstanceAccount{}
- for i := range cloudAccounts {
- remoteMaps[fmt.Sprintf("%s:%s", cloudAccounts[i].GetName(), cloudAccounts[i].GetHost())] = cloudAccounts[i]
- }
- for key, account := range remoteMaps {
- locals, ok := accountMaps[key]
- if !ok {
- _account, err := manager.newFromCloudDBInstanceAccount(ctx, userCred, instance, account)
- if err != nil {
- result.AddError(err)
- continue
- }
- result.Add()
- remoteAccounts = append(remoteAccounts, account)
- localAccounts = append(localAccounts, *_account)
- continue
- }
- password := ""
- for i := range locals {
- if i == 0 {
- err = locals[i].SyncWithCloudDBInstanceAccount(ctx, userCred, instance, account)
- if err != nil {
- result.UpdateError(err)
- continue
- }
- result.Update()
- remoteAccounts = append(remoteAccounts, account)
- localAccounts = append(localAccounts, locals[0])
- } else {
- if passwd, err := locals[i].GetPassword(); err == nil && len(passwd) > 0 {
- password = passwd
- }
- err := locals[i].RealDelete(ctx, userCred)
- if err != nil {
- result.DeleteError(err)
- continue
- }
- result.Delete()
- }
- }
- if len(password) > 0 {
- locals[0].savePassword(password)
- }
- }
- for key, accounts := range accountMaps {
- _, ok := remoteMaps[key]
- if !ok {
- for i := range accounts {
- err := accounts[i].RealDelete(ctx, userCred)
- if err != nil {
- result.DeleteError(err)
- continue
- }
- result.Delete()
- }
- }
- }
- return localAccounts, remoteAccounts, result
- }
- func (self *SDBInstanceAccount) SyncWithCloudDBInstanceAccount(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, extAccount cloudprovider.ICloudDBInstanceAccount) error {
- _, err := db.UpdateWithLock(ctx, self, func() error {
- self.Status = extAccount.GetStatus()
- return nil
- })
- if err != nil {
- return errors.Wrapf(err, "SyncWithCloudDBInstanceAccount.UpdateWithLock")
- }
- return nil
- }
- func (manager *SDBInstanceAccountManager) newFromCloudDBInstanceAccount(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, extAccount cloudprovider.ICloudDBInstanceAccount) (*SDBInstanceAccount, error) {
- lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, userCred))
- defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, userCred))
- account := SDBInstanceAccount{}
- account.SetModelManager(manager, &account)
- account.Name = extAccount.GetName()
- account.DBInstanceId = instance.Id
- account.Status = extAccount.GetStatus()
- account.Host = extAccount.GetHost()
- err := manager.TableSpec().Insert(ctx, &account)
- if err != nil {
- return nil, errors.Wrapf(err, "newFromCloudDBInstanceAccount.Insert")
- }
- return &account, nil
- }
- func (self *SDBInstanceAccount) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
- log.Infof("dbinstance account delete do nothing")
- return nil
- }
- func (self *SDBInstanceAccount) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
- return self.SStatusStandaloneResourceBase.Delete(ctx, userCred)
- }
- func (self *SDBInstanceAccount) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
- return self.StartDBInstanceAccountDeleteTask(ctx, userCred, "")
- }
- func (self *SDBInstanceAccount) StartDBInstanceAccountDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
- self.SetStatus(ctx, userCred, api.DBINSTANCE_USER_DELETING, "")
- task, err := taskman.TaskManager.NewTask(ctx, "DBInstanceAccountDeleteTask", self, userCred, nil, parentTaskId, "", nil)
- if err != nil {
- return err
- }
- task.ScheduleRun(nil)
- return nil
- }
- func (manager *SDBInstanceAccountManager) ListItemExportKeys(ctx context.Context,
- q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential,
- keys stringutils2.SSortedStrings,
- ) (*sqlchemy.SQuery, error) {
- var err error
- q, err = manager.SStatusStandaloneResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
- if err != nil {
- return nil, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.ListItemExportKeys")
- }
- if keys.ContainsAny(manager.SDBInstanceResourceBaseManager.GetExportKeys()...) {
- q, err = manager.SDBInstanceResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
- if err != nil {
- return nil, errors.Wrap(err, "SDBInstanceResourceBaseManager.ListItemExportKeys")
- }
- }
- return q, nil
- }
- func (manager *SDBInstanceAccountManager) InitializeData() error {
- sq := DBInstanceManager.Query("id")
- q := manager.Query().NotIn("dbinstance_id", sq.SubQuery())
- accounts := []SDBInstanceAccount{}
- err := db.FetchModelObjects(manager, q, &accounts)
- if err != nil {
- return errors.Wrapf(err, "db.FetchModelObjects")
- }
- for i := range accounts {
- err = accounts[i].RealDelete(context.Background(), nil)
- if err != nil {
- return errors.Wrapf(err, "purge %s", accounts[i].Id)
- }
- }
- log.Debugf("SDBInstanceAccountManager cleaned %d dirty data.", len(accounts))
- return nil
- }
|