diff --git a/cmd/climc/shell/dbinstance_accounts.go b/cmd/climc/shell/dbinstance_accounts.go new file mode 100644 index 0000000000..b343277056 --- /dev/null +++ b/cmd/climc/shell/dbinstance_accounts.go @@ -0,0 +1,64 @@ +// 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 shell + +import ( + "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/pkg/mcclient/modules" + "yunion.io/x/onecloud/pkg/mcclient/options" +) + +func init() { + type DBInstanceAccountListOptions struct { + options.BaseListOptions + DBInstance string `help:"ID or Name of DBInstance" json:"dbinstance"` + } + R(&DBInstanceAccountListOptions{}, "dbinstance-account-list", "List DB instance accounts", func(s *mcclient.ClientSession, opts *DBInstanceAccountListOptions) error { + params, err := options.ListStructToParams(opts) + if err != nil { + return err + } + + result, err := modules.DBInstanceAccounts.List(s, params) + if err != nil { + return err + } + printList(result, modules.DBInstanceAccounts.GetColumns(s)) + return nil + }) + + type DBInstanceAccountIdOptions struct { + ID string `help:"ID or Name of DBInstanceaccount"` + } + + R(&DBInstanceAccountIdOptions{}, "dbinstance-account-show", "Show DB instance account", func(s *mcclient.ClientSession, opts *DBInstanceAccountIdOptions) error { + account, err := modules.DBInstanceAccounts.Get(s, opts.ID, nil) + if err != nil { + return err + } + printObject(account) + return nil + }) + + R(&DBInstanceAccountIdOptions{}, "dbinstance-account-delete", "Delete DB instance account", func(s *mcclient.ClientSession, opts *DBInstanceAccountIdOptions) error { + account, err := modules.DBInstanceAccounts.Delete(s, opts.ID, nil) + if err != nil { + return err + } + printObject(account) + return nil + }) + +} diff --git a/cmd/climc/shell/dbinstances.go b/cmd/climc/shell/dbinstances.go index aeb405015e..6fee226c4d 100644 --- a/cmd/climc/shell/dbinstances.go +++ b/cmd/climc/shell/dbinstances.go @@ -312,37 +312,6 @@ func init() { return nil }) - type DBInstanceAccountListOptions struct { - options.BaseListOptions - DBInstance string `help:"ID or Name of DBInstance" json:"dbinstance"` - } - R(&DBInstanceAccountListOptions{}, "dbinstance-account-list", "List DB instance accounts", func(s *mcclient.ClientSession, opts *DBInstanceAccountListOptions) error { - params, err := options.ListStructToParams(opts) - if err != nil { - return err - } - - result, err := modules.DBInstanceAccounts.List(s, params) - if err != nil { - return err - } - printList(result, modules.DBInstanceAccounts.GetColumns(s)) - return nil - }) - - type DBInstanceAccountIdOptions struct { - ID string `help:"ID or Name of DBInstanceaccount"` - } - - R(&DBInstanceAccountIdOptions{}, "dbinstance-account-show", "Show DB instance account", func(s *mcclient.ClientSession, opts *DBInstanceAccountIdOptions) error { - account, err := modules.DBInstanceAccounts.Get(s, opts.ID, nil) - if err != nil { - return err - } - printObject(account) - return nil - }) - type DBInstancePrivilegeListOptions struct { options.BaseListOptions DBInstanceaccount string `help:"ID or Name of DBInstanceaccount" json:"dbinstanceaccount"` @@ -362,4 +331,21 @@ func init() { return nil }) + type DBInstanceChangeOwnerOptions struct { + ID string `help:"DBInstance to change owner" json:"-"` + PROJECT string `help:"Project ID or change" json:"tenant"` + } + R(&DBInstanceChangeOwnerOptions{}, "dbinstance-change-owner", "Change owner porject of a dbinstance", func(s *mcclient.ClientSession, opts *DBInstanceChangeOwnerOptions) error { + params, err := options.StructToParams(opts) + if err != nil { + return err + } + result, err := modules.DBInstance.PerformAction(s, opts.ID, "change-owner", params) + if err != nil { + return err + } + printObject(result) + return nil + }) + } diff --git a/pkg/apis/compute/dbinstance_const.go b/pkg/apis/compute/dbinstance_const.go index a9b31ef33a..52c46e0c31 100644 --- a/pkg/apis/compute/dbinstance_const.go +++ b/pkg/apis/compute/dbinstance_const.go @@ -56,11 +56,12 @@ const ( BACKUP_MODE_MANUAL = "manual" //手动 //实例数据库状态 - DBINSTANCE_DATABASE_CREATING = "creating" //创建中 - DBINSTANCE_DATABASE_CREATE_FAILE = "create_failed" //创建失败 - DBINSTANCE_DATABASE_RUNNING = "running" //正常 - DBINSTANCE_DATABASE_DELETING = "deleting" //删除中 - DBINSTANCE_DATABASE_DELETE_FAILED = "delete_failed" //删除失败 + DBINSTANCE_DATABASE_CREATING = "creating" //创建中 + DBINSTANCE_DATABASE_CREATE_FAILE = "create_failed" //创建失败 + DBINSTANCE_DATABASE_RUNNING = "running" //正常 + DBINSTANCE_DATABASE_GRANT_PRIVILEGE = "grant_privilege" //赋予权限中 + DBINSTANCE_DATABASE_DELETING = "deleting" //删除中 + DBINSTANCE_DATABASE_DELETE_FAILED = "delete_failed" //删除失败 //实例用户状态 DBINSTANCE_USER_UNAVAILABLE = "unavailable" //不可用 diff --git a/pkg/apis/compute/dbinstance_database.go b/pkg/apis/compute/dbinstance_database.go index 955b46b769..863fb0b09a 100644 --- a/pkg/apis/compute/dbinstance_database.go +++ b/pkg/apis/compute/dbinstance_database.go @@ -18,7 +18,7 @@ import "yunion.io/x/onecloud/pkg/apis" type SDBInstanceDatabasePrivilege struct { Account string - DBInstancedccountId string + DBInstanceaccountId string Privilege string } diff --git a/pkg/compute/models/dbinstance_databases.go b/pkg/compute/models/dbinstance_databases.go index 943da7af45..df10f569cc 100644 --- a/pkg/compute/models/dbinstance_databases.go +++ b/pkg/compute/models/dbinstance_databases.go @@ -138,7 +138,7 @@ func (manager *SDBInstanceDatabaseManager) ValidateCreateData(ctx context.Contex if err != nil { return nil, httperrors.NewInputParameterError("failed to found dbinstance %s(%s) account %s: %v", instance.Name, instance.Id, _account.Account, err) } - input.Accounts[i].DBInstancedccountId = account.Id + input.Accounts[i].DBInstanceaccountId = account.Id } input, err = region.GetDriver().ValidateCreateDBInstanceDatabaseData(ctx, userCred, ownerId, instance, input) @@ -178,6 +178,15 @@ func (self *SDBInstanceDatabase) GetDBInstance() (*SDBInstance, error) { return instance.(*SDBInstance), nil } +func (self *SDBInstanceDatabase) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) { + extra, err := self.SVirtualResourceBase.GetExtraDetails(ctx, userCred, query) + if err != nil { + return nil, err + } + + return self.getMoreDetails(ctx, userCred, extra) +} + func (self *SDBInstanceDatabase) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict { extra := self.SVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query) extra, _ = self.getMoreDetails(ctx, userCred, extra) diff --git a/pkg/compute/tasks/dbinstance_account_create_task.go b/pkg/compute/tasks/dbinstance_account_create_task.go index 73c697afcc..48ecf03403 100644 --- a/pkg/compute/tasks/dbinstance_account_create_task.go +++ b/pkg/compute/tasks/dbinstance_account_create_task.go @@ -16,6 +16,7 @@ package tasks import ( "context" + "fmt" "yunion.io/x/jsonutils" "yunion.io/x/pkg/errors" @@ -72,13 +73,58 @@ func (self *DBInstanceAccountCreateTask) CreateDBInstanceAccount(ctx context.Con return } - account.SetStatus(self.UserCred, api.DBINSTANCE_USER_AVAILABLE, "") - input := api.SDBInstanceAccountCreateInput{} self.GetParams().Unmarshal(&input) - for _, _privilege := range input.Privileges { - account.StartGrantPrivilegeTask(ctx, self.UserCred, _privilege.Database, _privilege.Privilege, "") + if len(input.Privileges) == 0 { + account.SetStatus(self.UserCred, api.DBINSTANCE_USER_AVAILABLE, "") + self.SetStageComplete(ctx, nil) + return } + iAccounts, err := iRds.GetIDBInstanceAccounts() + if err != nil { + msg := fmt.Sprintf("failed to found accounts from cloud dbinstance error: %v", err) + db.OpsLog.LogEvent(account, db.ACT_GRANT_PRIVILEGE, msg, self.GetUserCred()) + logclient.AddActionLogWithStartable(self, account, logclient.ACT_GRANT_PRIVILEGE, msg, self.UserCred, false) + account.SetStatus(self.UserCred, api.DBINSTANCE_USER_AVAILABLE, "") + self.SetStageComplete(ctx, nil) + return + } + + var iAccount cloudprovider.ICloudDBInstanceAccount = nil + for i := range iAccounts { + if iAccounts[i].GetName() == account.Name { + iAccount = iAccounts[i] + break + } + } + + if iAccount == nil { + msg := fmt.Sprintf("failed to found account %s from cloud dbinstance", account.Name) + db.OpsLog.LogEvent(account, db.ACT_GRANT_PRIVILEGE, msg, self.GetUserCred()) + logclient.AddActionLogWithStartable(self, account, logclient.ACT_GRANT_PRIVILEGE, msg, self.UserCred, false) + account.SetStatus(self.UserCred, api.DBINSTANCE_USER_AVAILABLE, "") + self.SetStageComplete(ctx, nil) + return + } + + account.SetStatus(self.UserCred, api.DBINSTANCE_USER_GRANT_PRIVILEGE, "") + for _, privilege := range input.Privileges { + err = iAccount.GrantPrivilege(privilege.Database, privilege.Privilege) + if err != nil { + db.OpsLog.LogEvent(account, db.ACT_GRANT_PRIVILEGE, err, self.GetUserCred()) + logclient.AddActionLogWithStartable(self, account, logclient.ACT_GRANT_PRIVILEGE, err, self.UserCred, false) + continue + } + _privilege := models.SDBInstancePrivilege{ + Privilege: privilege.Privilege, + DBInstanceaccountId: account.Id, + DBInstancedatabaseId: privilege.DBInstancedatabaseId, + } + models.DBInstancePrivilegeManager.TableSpec().Insert(&_privilege) + logclient.AddActionLogWithStartable(self, account, logclient.ACT_GRANT_PRIVILEGE, privilege, self.UserCred, true) + } + + account.SetStatus(self.UserCred, api.DBINSTANCE_USER_AVAILABLE, "") self.SetStageComplete(ctx, nil) } diff --git a/pkg/compute/tasks/dbinstance_database_create_task.go b/pkg/compute/tasks/dbinstance_database_create_task.go index f32d326143..6af06af7cf 100644 --- a/pkg/compute/tasks/dbinstance_database_create_task.go +++ b/pkg/compute/tasks/dbinstance_database_create_task.go @@ -16,9 +16,9 @@ package tasks import ( "context" + "fmt" "yunion.io/x/jsonutils" - "yunion.io/x/log" "yunion.io/x/pkg/errors" api "yunion.io/x/onecloud/pkg/apis/compute" @@ -74,18 +74,52 @@ func (self *DBInstanceDatabaseCreateTask) CreateDBInstanceDatabase(ctx context.C return } - database.SetStatus(self.UserCred, api.DBINSTANCE_DATABASE_RUNNING, "") - input := api.SDBInstanceDatabaseCreateInput{} self.GetParams().Unmarshal(&input) - for _, _account := range input.Accounts { - account, err := instance.GetDBInstanceAccount(_account.DBInstancedccountId) - if err != nil { - log.Errorf("failed to found account %s(%s) for instance %s(%s) error: %v", _account.Account, _account.DBInstancedccountId, instance.Name, instance.Id, err) - } else { - account.StartGrantPrivilegeTask(ctx, self.UserCred, database.Name, _account.Privilege, "") - } + if len(input.Accounts) == 0 { + database.SetStatus(self.UserCred, api.DBINSTANCE_DATABASE_RUNNING, "") + self.SetStageComplete(ctx, nil) + return } + _iAccounts, err := iRds.GetIDBInstanceAccounts() + if err != nil { + msg := fmt.Sprintf("failed to found accounts from cloud dbinstance error: %v", err) + db.OpsLog.LogEvent(database, db.ACT_GRANT_PRIVILEGE, msg, self.GetUserCred()) + logclient.AddActionLogWithStartable(self, database, logclient.ACT_GRANT_PRIVILEGE, msg, self.UserCred, false) + database.SetStatus(self.UserCred, api.DBINSTANCE_DATABASE_RUNNING, "") + self.SetStageComplete(ctx, nil) + return + } + + database.SetStatus(self.UserCred, api.DBINSTANCE_DATABASE_GRANT_PRIVILEGE, "") + iAccounts := map[string]cloudprovider.ICloudDBInstanceAccount{} + for _, iAccount := range _iAccounts { + iAccounts[iAccount.GetName()] = iAccount + } + + for _, account := range input.Accounts { + iAccount, ok := iAccounts[account.Account] + if !ok { + msg := fmt.Sprintf("failed to found account %s from dbinstance", account.Account) + db.OpsLog.LogEvent(database, db.ACT_GRANT_PRIVILEGE, msg, self.GetUserCred()) + logclient.AddActionLogWithStartable(self, database, logclient.ACT_GRANT_PRIVILEGE, msg, self.UserCred, false) + continue + } + err = iAccount.GrantPrivilege(database.Name, account.Privilege) + if err != nil { + db.OpsLog.LogEvent(database, db.ACT_GRANT_PRIVILEGE, err, self.GetUserCred()) + logclient.AddActionLogWithStartable(self, database, logclient.ACT_GRANT_PRIVILEGE, err, self.UserCred, false) + continue + } + privilege := models.SDBInstancePrivilege{ + Privilege: account.Privilege, + DBInstanceaccountId: account.DBInstanceaccountId, + DBInstancedatabaseId: database.Id, + } + models.DBInstancePrivilegeManager.TableSpec().Insert(&privilege) + logclient.AddActionLogWithStartable(self, database, logclient.ACT_GRANT_PRIVILEGE, account, self.UserCred, true) + } + database.SetStatus(self.UserCred, api.DBINSTANCE_DATABASE_RUNNING, "") self.SetStageComplete(ctx, nil) } diff --git a/pkg/multicloud/aliyun/shell/dbinstance_account.go b/pkg/multicloud/aliyun/shell/dbinstance_account.go index f511de62a7..016214e5fe 100644 --- a/pkg/multicloud/aliyun/shell/dbinstance_account.go +++ b/pkg/multicloud/aliyun/shell/dbinstance_account.go @@ -63,7 +63,7 @@ func init() { AccountType string `help:"account type" choices:"Normal|Super" default:"Normal"` } - shellutils.R(&DBInstanceAccountResetOptions{}, "dbinstance-account-delete", "Delete dbintance account", func(cli *aliyun.SRegion, args *DBInstanceAccountResetOptions) error { + shellutils.R(&DBInstanceAccountResetOptions{}, "dbinstance-account-reset-password", "Reset dbintance account password", func(cli *aliyun.SRegion, args *DBInstanceAccountResetOptions) error { return cli.ResetDBInstanceAccountPassword(args.INSTANCE, args.NAME, args.PASSWORD, args.AccountType) })