Merge pull request #291 in YUNIONIO/onecloud from ~QUXUAN/onecloud:hotfix/qx-cloud-account to release/2.3.0

* commit 'e7bd5dfa66588a8e8fd2bcfb93ce401641945bc2':
  减少调用层级
  支持云账号主次之分
This commit is contained in:
邱剑
2018-10-17 21:16:44 +08:00
23 changed files with 1043 additions and 200 deletions
+213
View File
@@ -0,0 +1,213 @@
package shell
import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/mcclient/options"
)
func init() {
type CloudaccountListOptions struct {
options.BaseListOptions
}
R(&CloudaccountListOptions{}, "cloud-account-list", "List cloud accounts", func(s *mcclient.ClientSession, args *CloudaccountListOptions) error {
var params *jsonutils.JSONDict
{
var err error
params, err = args.BaseListOptions.Params()
if err != nil {
return err
}
}
result, err := modules.Cloudaccounts.List(s, params)
if err != nil {
return err
}
printList(result, modules.Cloudaccounts.GetColumns(s))
return nil
})
type CloudaccountCreateOptions struct {
NAME string `help:"Name of cloud account"`
ACCOUNT string `help:"Account to access the cloud account"`
SECRET string `help:"Secret to access the cloud account, clientId/clientScret for Azure"`
PROVIDER string `help:"Driver for cloud account" choices:"VMware|Aliyun|Azure|Qcloud"`
AccessURL string `helo:"hello" metavar:"Azure choices: <AzureGermanCloud、AzureChinaCloud、AzureUSGovernmentCloud、AzurePublicCloud>"`
Desc string `help:"Description"`
Enabled bool `help:"Enabled the account automatically"`
EnableProject bool `help:"Enable the account with same name project"`
Import bool `help:"Import all sub account automatically"`
}
R(&CloudaccountCreateOptions{}, "cloud-account-create", "Create a cloud account", func(s *mcclient.ClientSession, args *CloudaccountCreateOptions) error {
params := jsonutils.NewDict()
params.Add(jsonutils.NewString(args.NAME), "name")
params.Add(jsonutils.NewString(args.ACCOUNT), "account")
params.Add(jsonutils.NewString(args.SECRET), "secret")
params.Add(jsonutils.NewString(args.PROVIDER), "provider")
if args.Enabled {
params.Add(jsonutils.JSONTrue, "enabled")
}
if args.EnableProject {
params.Add(jsonutils.JSONTrue, "enable_project")
}
if args.Import {
params.Add(jsonutils.JSONTrue, "import")
}
if len(args.AccessURL) > 0 {
params.Add(jsonutils.NewString(args.AccessURL), "access_url")
}
if len(args.Desc) > 0 {
params.Add(jsonutils.NewString(args.Desc), "description")
}
result, err := modules.Cloudaccounts.Create(s, params)
if err != nil {
return err
}
printObject(result)
return nil
})
type CloudaccountUpdateOptions struct {
ID string `help:"ID or Name of cloud account"`
Name string `help:"New name to update"`
AccessUrl string `help:"New access url"`
Desc string `help:"Description"`
}
R(&CloudaccountUpdateOptions{}, "cloud-account-update", "Update a cloud account", func(s *mcclient.ClientSession, args *CloudaccountUpdateOptions) error {
params := jsonutils.NewDict()
if len(args.Name) > 0 {
params.Add(jsonutils.NewString(args.Name), "name")
}
if len(args.AccessUrl) > 0 {
params.Add(jsonutils.NewString(args.AccessUrl), "access_url")
}
if len(args.Desc) > 0 {
params.Add(jsonutils.NewString(args.Desc), "description")
}
if params.Size() == 0 {
return InvalidUpdateError()
}
result, err := modules.Cloudaccounts.Update(s, args.ID, params)
if err != nil {
return err
}
printObject(result)
return nil
})
type CloudaccountShowOptions struct {
ID string `help:"ID or Name of cloud account"`
}
R(&CloudaccountShowOptions{}, "cloud-account-show", "Get details of a cloud account", func(s *mcclient.ClientSession, args *CloudaccountShowOptions) error {
result, err := modules.Cloudaccounts.Get(s, args.ID, nil)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&CloudaccountShowOptions{}, "cloud-account-delete", "Delete a cloud account", func(s *mcclient.ClientSession, args *CloudaccountShowOptions) error {
result, err := modules.Cloudaccounts.Delete(s, args.ID, nil)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&CloudaccountShowOptions{}, "cloud-account-enable", "Enable cloud account", func(s *mcclient.ClientSession, args *CloudaccountShowOptions) error {
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "enable", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&CloudaccountShowOptions{}, "cloud-account-disable", "Disable cloud account", func(s *mcclient.ClientSession, args *CloudaccountShowOptions) error {
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "disable", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&CloudaccountShowOptions{}, "cloud-account-balance", "Get balance", func(s *mcclient.ClientSession, args *CloudaccountShowOptions) error {
result, err := modules.Cloudaccounts.GetSpecific(s, args.ID, "balance", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
type CloudaccountImportOptions struct {
ID string `help:"ID or Name of cloud account"`
Enabled bool `help:"Import sub accounts with enabled status"`
EnableProject bool `help:"Import sub account with project"`
}
R(&CloudaccountImportOptions{}, "cloud-account-import", "Import sub cloud account", func(s *mcclient.ClientSession, args *CloudaccountImportOptions) error {
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "import", jsonutils.Marshal(map[string]bool{"enabled": args.Enabled, "enable_project": args.EnableProject}))
if err != nil {
return err
}
printObject(result)
return nil
})
type CloudaccountUpdateCredentialOptions struct {
ID string `help:"ID or Name of cloud account"`
ACCOUNT string `help:"new account"`
SECRET string `help:"new secret"`
}
R(&CloudaccountUpdateCredentialOptions{}, "cloud-account-update-credential", "Update credential of a cloud account", func(s *mcclient.ClientSession, args *CloudaccountUpdateCredentialOptions) error {
params := jsonutils.NewDict()
params.Add(jsonutils.NewString(args.ACCOUNT), "account")
params.Add(jsonutils.NewString(args.SECRET), "secret")
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "update-credential", params)
if err != nil {
return err
}
printObject(result)
return nil
})
type CloudaccountSyncOptions struct {
ID string `help:"ID or Name of cloud account"`
Force bool `help:"Force sync no matter what"`
FullSync bool `help:"Synchronize everything"`
Region []string `help:"region to sync"`
Zone []string `help:"region to sync"`
Host []string `help:"region to sync"`
}
R(&CloudaccountSyncOptions{}, "cloud-account-sync", "Sync of a cloud account account", func(s *mcclient.ClientSession, args *CloudaccountSyncOptions) error {
params := jsonutils.NewDict()
if args.Force {
params.Add(jsonutils.JSONTrue, "force")
}
if args.FullSync {
params.Add(jsonutils.JSONTrue, "full_sync")
}
if len(args.Region) > 0 {
params.Add(jsonutils.NewStringArray(args.Region), "region")
}
if len(args.Zone) > 0 {
params.Add(jsonutils.NewStringArray(args.Zone), "zone")
}
if len(args.Host) > 0 {
params.Add(jsonutils.NewStringArray(args.Host), "host")
}
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "sync", params)
if err != nil {
return err
}
printObject(result)
return nil
})
}
+13
View File
@@ -91,6 +91,19 @@ func init() {
return nil
})
type CloudproviderChangeProjectOptions struct {
ID string `help:"ID or Name of cloud provider"`
TENANT string `help:"ID or Name of tenant"`
}
R(&CloudproviderChangeProjectOptions{}, "cloud-provider-change-project", "Change project for provider", func(s *mcclient.ClientSession, args *CloudproviderChangeProjectOptions) error {
result, err := modules.Cloudproviders.PerformAction(s, args.ID, "change-project", jsonutils.Marshal(map[string]string{"project": args.TENANT}))
if err != nil {
return err
}
printObject(result)
return nil
})
type CloudproviderShowOptions struct {
ID string `help:"ID or Name of cloud provider"`
}
+1
View File
@@ -41,6 +41,7 @@ func InitHandlers(app *appsrv.Application) {
for _, manager := range []db.IModelManager{
db.OpsLog,
models.CloudaccountManager,
models.CloudproviderManager,
models.CloudregionManager,
models.ZoneManager,
+502
View File
@@ -0,0 +1,502 @@
package models
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/util/timeutils"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SCloudaccountManager struct {
db.SEnabledStatusStandaloneResourceBaseManager
SInfrastructureManager
}
var CloudaccountManager *SCloudaccountManager
func init() {
CloudaccountManager = &SCloudaccountManager{SEnabledStatusStandaloneResourceBaseManager: db.NewEnabledStatusStandaloneResourceBaseManager(SCloudaccount{}, "cloudaccounts_tbl", "cloudaccount", "cloudaccounts")}
}
type SCloudaccount struct {
db.SEnabledStatusStandaloneResourceBase
SInfrastructure
AccessUrl string `width:"64" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
Account string `width:"128" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
Secret string `width:"256" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(256, charset='ascii'), nullable=False)
BalanceKey string `width:"256" charset:"ascii" nullable:"true" list:"admin" create:"admin_optional"`
LastSync time.Time `get:"admin" list:"admin"` // = Column(DateTime, nullable=True)
Version string `width:"32" charset:"ascii" nullable:"true" list:"admin"` // Column(VARCHAR(32, charset='ascii'), nullable=True)
Sysinfo jsonutils.JSONObject `get:"admin"` // Column(JSONEncodedDict, nullable=True)
Provider string `width:"64" charset:"ascii" list:"admin" create:"admin_required"`
}
func (self *SCloudaccount) GetCloudproviders() []SCloudprovider {
cloudproviders := []SCloudprovider{}
q := CloudproviderManager.Query().Equals("cloudaccount_id", self.Id)
if err := db.FetchModelObjects(CloudproviderManager, q, &cloudproviders); err != nil {
log.Errorf("getCloudproviders error: %v", err)
}
return cloudproviders
}
func (self *SCloudaccount) ValidateDeleteCondition(ctx context.Context) error {
if self.Enabled {
return httperrors.NewInvalidStatusError("account is enabled")
}
if len(self.GetCloudproviders()) > 0 {
return httperrors.NewNotEmptyError("Not an empty cloud account")
}
return self.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx)
}
func (self *SCloudaccount) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
return self.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
}
func (self *SCloudaccountManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
// check provider
name, _ := data.GetString("name")
provider, _ := data.GetString("provider")
if !cloudprovider.IsSupported(provider) {
return nil, httperrors.NewInputParameterError("Unsupported provider %s", provider)
}
// check duplication
// url, account, provider must be unique
account, _ := data.GetString("account")
secret, _ := data.GetString("secret")
url, _ := data.GetString("access_url")
q := self.Query().Equals("provider", provider)
if len(account) > 0 {
q = q.Equals("account", account)
}
if len(url) > 0 {
q = q.Equals("access_url", url)
}
if q.Count() > 0 {
return nil, httperrors.NewConflictError("The account has been registered")
}
if subAccount, err := GetSubAccounts(name, url, account, secret, provider); err != nil {
return nil, httperrors.NewInputParameterError("Invalidate account with secret")
} else if accounts, err := subAccount.GetArray("data"); err != nil {
return nil, err
} else {
data.Add(jsonutils.NewArray(accounts...), "accounts")
}
return self.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)
}
func (self *SCloudaccount) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data jsonutils.JSONObject) {
self.SEnabledStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerProjId, query, data)
self.savePassword(self.Secret)
_import, _ := data.Bool("import")
enableProject, _ := data.Bool("enable_project")
if subAccounts, err := data.GetArray("accounts"); err == nil && _import && len(subAccounts) > 0 {
for _, subAccount := range subAccounts {
name, _ := subAccount.GetString("name")
account, _ := subAccount.GetString("account")
if len(name) > 0 && len(account) > 0 {
if q := CloudproviderManager.Query().Equals("cloudaccount_id", self.Id).Equals("account", account); q.Count() > 0 {
log.Errorf("sub account conflict")
} else {
newCloudprovider := SCloudprovider{
Account: account,
CloudaccountId: self.Id,
Provider: self.Provider,
}
newCloudprovider.SetModelManager(CloudproviderManager)
if err := CloudproviderManager.TableSpec().Insert(&newCloudprovider); err != nil {
log.Errorf("Create cloudprovider error: %v", err)
} else if _, err := CloudproviderManager.TableSpec().Update(&newCloudprovider, func() error {
newCloudprovider.Name = name
return nil
}); err != nil {
log.Errorf("Update cloudprovider error: %v", err)
}
if enableProject {
newCloudprovider.SyncProject()
}
}
}
}
}
if self.Enabled {
self.startSyncCloudProviderInfoTask(ctx, userCred, nil, "")
}
}
func (self *SCloudaccount) savePassword(secret string) error {
sec, err := utils.EncryptAESBase64(self.Id, secret)
if err != nil {
return err
}
_, err = self.GetModelManager().TableSpec().Update(self, func() error {
self.Secret = sec
return nil
})
return err
}
func (self *SCloudaccount) getPassword() (string, error) {
return utils.DescryptAESBase64(self.Id, self.Secret)
}
func (self *SCloudaccount) CanSync() bool {
if self.Status == CLOUD_PROVIDER_SYNCING {
if self.LastSync.IsZero() || time.Now().Sub(self.LastSync) > 900*time.Second {
return true
} else {
return false
}
} else {
return true
}
}
func (self *SCloudaccount) AllowPerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return userCred.IsSystemAdmin()
}
func (self *SCloudaccount) PerformSync(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if !self.Enabled {
return nil, httperrors.NewInvalidStatusError("Account disabled")
}
syncRange := SSyncRange{}
err := data.Unmarshal(&syncRange)
if err != nil {
return nil, httperrors.NewInputParameterError("invalid input %s", err)
}
if self.CanSync() || syncRange.Force {
err = self.startSyncCloudProviderInfoTask(ctx, userCred, &syncRange, "")
}
return nil, err
}
func (self *SCloudaccount) AllowPerformUpdateCredential(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return userCred.IsSystemAdmin()
}
func (self *SCloudaccount) PerformUpdateCredential(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if !self.Enabled {
return nil, httperrors.NewInvalidStatusError("Account disabled")
}
var err error
changed := false
secret, _ := data.GetString("secret")
account, _ := data.GetString("account")
accessUrl, _ := data.GetString("access_url")
if len(secret) > 0 || len(account) > 0 || len(accessUrl) > 0 {
// check duplication
q := self.GetModelManager().Query()
q = q.Equals("access_url", accessUrl)
q = q.Equals("account", account)
q = q.NotEquals("id", self.Id)
if q.Count() > 0 {
return nil, httperrors.NewConflictError("Access url and account conflict")
}
}
if len(secret) > 0 {
err = self.savePassword(secret)
if err != nil {
return nil, err
}
changed = true
}
if (len(account) > 0 && account != self.Account) || (len(accessUrl) > 0 && accessUrl != self.AccessUrl) {
if len(account) > 0 && account != self.Account {
for _, cloudprovider := range self.GetCloudproviders() {
if cloudprovider.Account == self.Account {
if _, err = cloudprovider.GetModelManager().TableSpec().Update(&cloudprovider, func() error {
cloudprovider.Account = account
return nil
}); err != nil {
return nil, err
}
}
}
}
_, err = self.GetModelManager().TableSpec().Update(self, func() error {
if len(account) > 0 {
self.Account = account
}
if len(accessUrl) > 0 {
self.AccessUrl = accessUrl
}
return nil
})
if err != nil {
return nil, err
}
changed = true
}
if changed {
self.SetStatus(userCred, CLOUD_PROVIDER_INIT, "Change credential")
self.startSyncCloudProviderInfoTask(ctx, userCred, nil, "")
}
return nil, nil
}
func (self *SCloudaccount) startSyncCloudProviderInfoTask(ctx context.Context, userCred mcclient.TokenCredential, syncRange *SSyncRange, parentTaskId string) error {
params := jsonutils.NewDict()
if syncRange != nil {
params.Add(jsonutils.Marshal(syncRange), "sync_range")
}
cloudproviders := self.GetCloudproviders()
taskItems := make([]db.IStandaloneModel, 0)
for i := 0; i < len(cloudproviders); i++ {
if cloudproviders[i].Enabled {
taskItems = append(taskItems, &cloudproviders[i])
}
}
task, err := taskman.TaskManager.NewParallelTask(ctx, "CloudAccountSyncInfoTask", taskItems, userCred, params, "", "", nil)
if err != nil {
log.Errorf("CloudAccountSyncInfoTask newTask error %s", err)
} else {
task.ScheduleRun(nil)
}
return nil
}
func (self *SCloudaccount) MarkStartSync(userCred mcclient.TokenCredential) {
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
self.LastSync = timeutils.UtcNow()
return nil
})
if err != nil {
log.Errorf("Fail tp update last_sync %s", err)
return
}
self.SetStatus(userCred, CLOUD_PROVIDER_START_SYNC, "")
}
func (self *SCloudaccount) GetDriver() (cloudprovider.ICloudProvider, error) {
if !self.Enabled {
return nil, fmt.Errorf("Cloud provider is not enabled")
}
secret, err := self.getPassword()
if err != nil {
return nil, fmt.Errorf("Invalid password %s", err)
}
// log.Debugf("XXXXX secret: %s", secret)
return cloudprovider.GetProvider(self.Id, self.Name, self.AccessUrl, self.Account, secret, self.Provider)
}
func (self *SCloudaccount) GetSubAccounts() (jsonutils.JSONObject, error) {
if secret, err := self.getPassword(); err != nil {
return nil, err
} else {
return GetSubAccounts(self.Name, self.AccessUrl, self.Account, secret, self.Provider)
}
}
func (self *SCloudaccount) AllowPerformImport(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return userCred.IsSystemAdmin()
}
func (self *SCloudaccount) PerformImport(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if subAccounts, err := self.GetSubAccounts(); err != nil {
return nil, err
} else if accounts, err := subAccounts.GetArray("data"); err != nil {
return nil, err
} else {
enabled, _ := data.Bool("enabled")
enableProject, _ := data.Bool("enable_project")
for _, _account := range accounts {
name, _ := _account.GetString("name")
account, _ := _account.GetString("account")
if len(name) > 0 && len(account) > 0 {
if q := CloudproviderManager.Query().Equals("cloudaccount_id", self.Id).Equals("account", account); q.Count() > 0 {
log.Debugf("account %s has imported", account)
} else {
newCloudprovider := SCloudprovider{
Account: account,
CloudaccountId: self.Id,
Provider: self.Provider,
}
newCloudprovider.SetModelManager(CloudproviderManager)
if err := CloudproviderManager.TableSpec().Insert(&newCloudprovider); err != nil {
log.Errorf("Create cloudprovider error: %v", err)
return nil, err
} else if _, err := CloudproviderManager.TableSpec().Update(&newCloudprovider, func() error {
newCloudprovider.Name = name
newCloudprovider.Enabled = true
return nil
}); err != nil {
log.Errorf("Update cloudprovider error: %v", err)
return nil, err
}
if enableProject {
newCloudprovider.SyncProject()
}
if enabled {
newCloudprovider.StartSyncCloudProviderInfoTask(ctx, userCred, &SSyncRange{FullSync: true}, "")
}
}
}
}
}
return nil, nil
}
func GetSubAccounts(name, accessUrl, account, secret, provider string) (jsonutils.JSONObject, error) {
if provider, err := cloudprovider.GetProvider("", name, accessUrl, account, secret, provider); err != nil {
return nil, err
} else {
return provider.GetSubAccounts()
}
}
func (self *SCloudaccount) SaveSysInfo(info jsonutils.JSONObject) {
self.GetModelManager().TableSpec().Update(self, func() error {
self.Sysinfo = info
return nil
})
}
func (manager *SCloudaccountManager) FetchCloudaccountById(accountId string) *SCloudaccount {
providerObj, err := manager.FetchById(accountId)
if err != nil {
log.Errorf("%s", err)
return nil
}
return providerObj.(*SCloudaccount)
}
func (manager *SCloudaccountManager) FetchCloudaccountByIdOrName(accountId string) *SCloudaccount {
providerObj, err := manager.FetchByIdOrName(nil, accountId)
if err != nil {
if err != sql.ErrNoRows {
log.Errorf("%s", err)
}
return nil
}
return providerObj.(*SCloudaccount)
}
func (self *SCloudaccount) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict {
extra.Add(jsonutils.Marshal(self.GetCloudproviders()), "accounts")
return extra
}
func (self *SCloudaccount) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SEnabledStatusStandaloneResourceBase.GetCustomizeColumns(ctx, userCred, query)
return self.getMoreDetails(extra)
}
func (self *SCloudaccount) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
extra := self.SEnabledStatusStandaloneResourceBase.GetExtraDetails(ctx, userCred, query)
return self.getMoreDetails(extra)
}
func (manager *SCloudaccountManager) InitializeData() error {
cloudproviders := []SCloudprovider{}
q := CloudproviderManager.Query()
q = q.Filter(sqlchemy.OR(sqlchemy.IsEmpty(q.Field("cloudaccount_id")), sqlchemy.IsNull(q.Field("cloudaccount_id"))))
if err := db.FetchModelObjects(CloudproviderManager, q, &cloudproviders); err != nil {
return err
}
for i := 0; i < len(cloudproviders); i++ {
cloudprovider := cloudproviders[i]
Account, providerAccount, providerName := cloudprovider.Account, "", cloudprovider.Name
if cloudprovider.Provider == CLOUD_PROVIDER_AZURE {
if accountInfo := strings.Split(cloudprovider.Account, "/"); len(accountInfo) == 2 {
Account, providerAccount = accountInfo[0], accountInfo[1]
if len(cloudprovider.Description) > 0 {
providerName = cloudprovider.Description
}
} else {
log.Errorf("Error provider format %s", cloudprovider.Account)
continue
}
}
account := SCloudaccount{}
account.SetModelManager(CloudaccountManager)
if err := CloudaccountManager.Query().
Equals("access_url", cloudprovider.AccessUrl).
Equals("account", Account).
Equals("provider", cloudprovider.Provider).First(&account); err != nil {
account = SCloudaccount{
AccessUrl: cloudprovider.AccessUrl,
Account: Account,
LastSync: cloudprovider.LastSync,
Sysinfo: cloudprovider.Sysinfo,
Provider: cloudprovider.Provider,
}
if err := CloudaccountManager.TableSpec().Insert(&account); err != nil {
log.Errorf("Insert Account error: %v", err)
}
if _, err := CloudaccountManager.TableSpec().Update(&account, func() error {
account.Name = Account
account.Status = cloudprovider.Status
return nil
}); err != nil {
log.Errorf("Update Account %s error: %v", account.Id, err)
}
if secret, err := cloudprovider.getPassword(); err != nil {
log.Errorf("Get password from provider %s error %v", cloudprovider.Name, err)
} else if err := account.savePassword(secret); err != nil {
log.Errorf("Set password for account %s error %v", account.Name, err)
}
}
if _, err := CloudproviderManager.TableSpec().Update(&cloudprovider, func() error {
log.Errorf("update %s", cloudprovider.Name)
cloudprovider.CloudaccountId = account.Id
cloudprovider.Account = providerAccount
cloudprovider.Secret = ""
cloudprovider.Name = providerName
return nil
}); err != nil {
log.Errorf("Update provider %s error: %v", cloudprovider.Name, err)
}
}
return nil
}
func (self *SCloudaccount) GetBalance() (float64, error) {
driver, err := self.GetDriver()
if err != nil {
return 0.0, err
}
return driver.GetBalance()
}
func (self *SCloudaccount) AllowGetDetailsBalance(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return userCred.IsSystemAdmin()
}
func (self *SCloudaccount) GetDetailsBalance(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
balance, err := self.GetBalance()
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
ret := jsonutils.NewDict()
ret.Add(jsonutils.NewFloat(balance), "balance")
return ret, nil
}
+87 -127
View File
@@ -8,8 +8,11 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/pkg/util/timeutils"
"yunion.io/x/pkg/utils"
@@ -51,6 +54,10 @@ type SCloudprovider struct {
Account string `width:"128" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
Secret string `width:"256" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(256, charset='ascii'), nullable=False)
CloudaccountId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" key_index:"true"`
ProjectId string `name:"tenant_id" width:"128" charset:"ascii" nullable:"true" list:"admin"`
LastSync time.Time `get:"admin" list:"admin"` // = Column(DateTime, nullable=True)
Version string `width:"32" charset:"ascii" nullable:"true" list:"admin"` // Column(VARCHAR(32, charset='ascii'), nullable=True)
@@ -101,58 +108,7 @@ func (self *SCloudprovider) ValidateUpdateData(ctx context.Context, userCred mcc
}
func (self *SCloudproviderManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
// check provider
provider, _ := data.GetString("provider")
if !cloudprovider.IsSupported(provider) {
return nil, httperrors.NewInputParameterError("Unsupported provider %s", provider)
}
// check duplication
// url, account, provider must be unique
account, _ := data.GetString("account")
url, _ := data.GetString("access_url")
q := self.Query().Equals("provider", provider)
if len(account) > 0 {
q = q.Equals("account", account)
}
if len(url) > 0 {
q = q.Equals("access_url", url)
}
if q.Count() > 0 {
return nil, httperrors.NewConflictError("The account has been registered")
}
return self.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)
}
func (self *SCloudprovider) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data jsonutils.JSONObject) {
self.SEnabledStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerProjId, query, data)
self.savePassword(self.Secret)
if self.Enabled {
self.startSyncCloudProviderInfoTask(ctx, userCred, nil, "")
}
}
func (self *SCloudprovider) savePassword(secret string) error {
sec, err := utils.EncryptAESBase64(self.Id, secret)
if err != nil {
return err
}
/*log.Debugf("savePassword %s => %s", secret, sec)
newsec, err := utils.DescryptAESBase64(self.Id, sec)
if err != nil {
return err
}
if newsec != secret {
log.Errorf("Encrypt/Descrypt mismatch!!")
return fmt.Errorf("Encrypt/Descrypt mismatch!!")
}*/
_, err = self.GetModelManager().TableSpec().Update(self, func() error {
self.Secret = sec
return nil
})
return err
return nil, httperrors.NewUnsupportOperationError("Not support create cloudprovider, please considir create cloudaccount")
}
func (self *SCloudprovider) getPassword() (string, error) {
@@ -171,12 +127,37 @@ func (self *SCloudprovider) CanSync() bool {
}
}
func (self *SCloudprovider) SyncProject() (err error) {
projectId := ""
if len(self.ProjectId) == 0 && len(self.Name) > 0 {
if tenant, err := db.TenantCacheManager.FetchTenantByIdOrName(context.Background(), self.Name); err != nil {
s := auth.GetAdminSession(options.Options.Region, "")
if project, err := modules.Projects.Create(s, jsonutils.Marshal(map[string]string{"name": self.Name})); err != nil {
return err
} else if projectId, err = project.GetString("id"); err != nil {
return err
}
} else {
projectId = tenant.Id
}
}
if len(projectId) > 0 {
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
self.ProjectId = projectId
return nil
})
return err
}
return nil
}
type SSyncRange struct {
Force bool
FullSync bool
Region []string
Zone []string
Host []string
Force bool
FullSync bool
ProjectSync bool
Region []string
Zone []string
Host []string
}
func (sr *SSyncRange) NeedSyncInfo() bool {
@@ -276,65 +257,12 @@ func (self *SCloudprovider) PerformSync(ctx context.Context, userCred mcclient.T
return nil, httperrors.NewInputParameterError("invalid input %s", err)
}
if self.CanSync() || syncRange.Force {
err = self.startSyncCloudProviderInfoTask(ctx, userCred, &syncRange, "")
err = self.StartSyncCloudProviderInfoTask(ctx, userCred, &syncRange, "")
}
return nil, err
}
func (self *SCloudprovider) AllowPerformUpdateCredential(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return userCred.IsSystemAdmin()
}
func (self *SCloudprovider) PerformUpdateCredential(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if !self.Enabled {
return nil, httperrors.NewInvalidStatusError("Cloudprovider disabled")
}
var err error
changed := false
secret, _ := data.GetString("secret")
account, _ := data.GetString("account")
accessUrl, _ := data.GetString("access_url")
if len(secret) > 0 || len(account) > 0 || len(accessUrl) > 0 {
// check duplication
q := self.GetModelManager().Query()
q = q.Equals("access_url", accessUrl)
q = q.Equals("account", account)
q = q.NotEquals("id", self.Id)
if q.Count() > 0 {
return nil, httperrors.NewConflictError("Access url and account conflict")
}
}
if len(secret) > 0 {
err = self.savePassword(secret)
if err != nil {
return nil, err
}
changed = true
}
if (len(account) > 0 && account != self.Account) || (len(accessUrl) > 0 && accessUrl != self.AccessUrl) {
_, err = self.GetModelManager().TableSpec().Update(self, func() error {
if len(account) > 0 {
self.Account = account
}
if len(accessUrl) > 0 {
self.AccessUrl = accessUrl
}
return nil
})
if err != nil {
return nil, err
}
changed = true
}
if changed {
self.SetStatus(userCred, CLOUD_PROVIDER_INIT, "Change credential")
self.startSyncCloudProviderInfoTask(ctx, userCred, nil, "")
}
return nil, nil
}
func (self *SCloudprovider) startSyncCloudProviderInfoTask(ctx context.Context, userCred mcclient.TokenCredential, syncRange *SSyncRange, parentTaskId string) error {
func (self *SCloudprovider) StartSyncCloudProviderInfoTask(ctx context.Context, userCred mcclient.TokenCredential, syncRange *SSyncRange, parentTaskId string) error {
params := jsonutils.NewDict()
if syncRange != nil {
params.Add(jsonutils.Marshal(syncRange), "sync_range")
@@ -348,6 +276,26 @@ func (self *SCloudprovider) startSyncCloudProviderInfoTask(ctx context.Context,
return nil
}
func (self *SCloudprovider) AllowPerformChangeProject(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return userCred.IsSystemAdmin()
}
func (self *SCloudprovider) PerformChangeProject(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if project, err := data.GetString("project"); err != nil {
return nil, httperrors.NewInputParameterError("Missing project parameter")
} else if tenant, err := db.TenantCacheManager.FetchTenantByIdOrName(ctx, project); err != nil {
return nil, httperrors.NewNotFoundError("project %s not found", project)
} else if _, err := self.GetModelManager().TableSpec().Update(self, func() error {
self.ProjectId = tenant.Id
return nil
}); err != nil {
log.Errorf("Update cloudprovider error: %v", err)
return nil, err
} else {
return nil, self.StartSyncCloudProviderInfoTask(ctx, userCred, &SSyncRange{FullSync: true, ProjectSync: true}, "")
}
}
func (self *SCloudprovider) MarkStartSync(userCred mcclient.TokenCredential) {
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
self.LastSync = timeutils.UtcNow()
@@ -365,30 +313,42 @@ func (self *SCloudprovider) GetDriver() (cloudprovider.ICloudProvider, error) {
return nil, fmt.Errorf("Cloud provider is not enabled")
}
secret, err := self.getPassword()
account, err := self.getAccount()
if err != nil {
return nil, fmt.Errorf("Invalid password %s", err)
return nil, err
}
// log.Debugf("XXXXX secret: %s", secret)
return cloudprovider.GetProvider(self.Id, self.Name, self.AccessUrl, self.Account, secret, self.Provider)
return cloudprovider.GetProvider(self.Id, self.Name, account.AccessUrl, account.Account, account.Secret, self.Provider)
}
func (manager *SCloudproviderManager) AllowPerformGetSubAccounts(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return userCred.IsSystemAdmin()
type SAccount struct {
AccessUrl string
Account string
Secret string
}
func (manager *SCloudproviderManager) PerformGetSubAccounts(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
name, _ := data.GetString("name")
accessUrl, _ := data.GetString("access_url")
account, _ := data.GetString("account")
secret, _ := data.GetString("secret")
_provider, _ := data.GetString("provider")
if provider, err := cloudprovider.GetProvider("", name, accessUrl, account, secret, _provider); err != nil {
func (self *SCloudprovider) getCloudaccount() (*SCloudaccount, error) {
if cloudaccount := CloudaccountManager.FetchCloudaccountById(self.CloudaccountId); cloudaccount != nil {
return cloudaccount, nil
}
return nil, fmt.Errorf("Failed to find cloud account for cloud provider %s", self.Name)
}
func (self *SCloudprovider) getAccount() (*SAccount, error) {
if cloudaccount, err := self.getCloudaccount(); err != nil {
return nil, err
} else {
return provider.GetSubAccounts()
account := SAccount{AccessUrl: cloudaccount.AccessUrl, Account: cloudaccount.Account}
if passwd, err := cloudaccount.getPassword(); err != nil {
return nil, err
} else {
account.Secret = passwd
}
if len(self.Account) > 0 && self.Account != cloudaccount.Account {
account.Account = fmt.Sprintf("%s/%s", account.Account, self.Account)
}
return &account, nil
}
}
func (self *SCloudprovider) SaveSysInfo(info jsonutils.JSONObject) {
+14 -10
View File
@@ -651,7 +651,7 @@ func (manager *SDiskManager) getDisksByStorage(storage *SStorage) ([]SDisk, erro
return disks, nil
}
func (manager *SDiskManager) syncCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, vdisk cloudprovider.ICloudDisk) (*SDisk, error) {
func (manager *SDiskManager) syncCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, vdisk cloudprovider.ICloudDisk, projectId string, projectSync bool) (*SDisk, error) {
diskObj, err := manager.FetchByExternalId(vdisk.GetGlobalId())
if err != nil {
if err == sql.ErrNoRows {
@@ -662,13 +662,13 @@ func (manager *SDiskManager) syncCloudDisk(ctx context.Context, userCred mcclien
return nil, err
}
storage := storageObj.(*SStorage)
return manager.newFromCloudDisk(ctx, userCred, vdisk, storage)
return manager.newFromCloudDisk(ctx, userCred, vdisk, storage, projectId)
} else {
return nil, err
}
} else {
disk := diskObj.(*SDisk)
err = disk.syncWithCloudDisk(ctx, userCred, vdisk)
err = disk.syncWithCloudDisk(ctx, userCred, vdisk, projectId, projectSync)
if err != nil {
return nil, err
}
@@ -676,7 +676,7 @@ func (manager *SDiskManager) syncCloudDisk(ctx context.Context, userCred mcclien
}
}
func (manager *SDiskManager) SyncDisks(ctx context.Context, userCred mcclient.TokenCredential, storage *SStorage, disks []cloudprovider.ICloudDisk) ([]SDisk, []cloudprovider.ICloudDisk, compare.SyncResult) {
func (manager *SDiskManager) SyncDisks(ctx context.Context, userCred mcclient.TokenCredential, storage *SStorage, disks []cloudprovider.ICloudDisk, projectId string, projectSync bool) ([]SDisk, []cloudprovider.ICloudDisk, compare.SyncResult) {
localDisks := make([]SDisk, 0)
remoteDisks := make([]cloudprovider.ICloudDisk, 0)
syncResult := compare.SyncResult{}
@@ -708,7 +708,7 @@ func (manager *SDiskManager) SyncDisks(ctx context.Context, userCred mcclient.To
}
for i := 0; i < len(commondb); i += 1 {
err = commondb[i].syncWithCloudDisk(ctx, userCred, commonext[i])
err = commondb[i].syncWithCloudDisk(ctx, userCred, commonext[i], projectId, projectSync)
if err != nil {
syncResult.UpdateError(err)
} else {
@@ -719,7 +719,7 @@ func (manager *SDiskManager) SyncDisks(ctx context.Context, userCred mcclient.To
}
for i := 0; i < len(added); i += 1 {
new, err := manager.newFromCloudDisk(ctx, userCred, added[i], storage)
new, err := manager.newFromCloudDisk(ctx, userCred, added[i], storage, projectId)
if err != nil {
syncResult.AddError(err)
} else {
@@ -732,7 +732,7 @@ func (manager *SDiskManager) SyncDisks(ctx context.Context, userCred mcclient.To
return localDisks, remoteDisks, syncResult
}
func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, extDisk cloudprovider.ICloudDisk) error {
func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, extDisk cloudprovider.ICloudDisk, projectId string, projectSync bool) error {
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
extDisk.Refresh()
self.Name = extDisk.GetName()
@@ -751,7 +751,9 @@ func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.Toke
self.ExpiredAt = extDisk.GetExpiredAt()
self.ProjectId = userCred.GetProjectId()
if projectSync && len(projectId) > 0 {
self.ProjectId = projectId
}
return nil
})
if err != nil {
@@ -775,7 +777,7 @@ func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.Toke
return nil
}
func (manager *SDiskManager) newFromCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, extDisk cloudprovider.ICloudDisk, storage *SStorage) (*SDisk, error) {
func (manager *SDiskManager) newFromCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, extDisk cloudprovider.ICloudDisk, storage *SStorage, projectId string) (*SDisk, error) {
disk := SDisk{}
disk.SetModelManager(manager)
@@ -784,7 +786,9 @@ func (manager *SDiskManager) newFromCloudDisk(ctx context.Context, userCred mccl
disk.ExternalId = extDisk.GetGlobalId()
disk.StorageId = storage.Id
disk.ProjectId = userCred.GetProjectId()
if len(projectId) > 0 {
disk.ProjectId = projectId
}
disk.DiskFormat = extDisk.GetDiskFormat()
disk.DiskSize = extDisk.GetDiskSizeMB()
disk.AutoDelete = extDisk.GetIsAutoDelete()
+14 -8
View File
@@ -136,7 +136,7 @@ func (self *SElasticip) GetRegion() *SCloudregion {
return CloudregionManager.FetchRegionById(self.CloudregionId)
}
func (manager *SElasticipManager) SyncEips(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, eips []cloudprovider.ICloudEIP) compare.SyncResult {
func (manager *SElasticipManager) SyncEips(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, eips []cloudprovider.ICloudEIP, projectId string, projectSync bool) compare.SyncResult {
// localEips := make([]SElasticip, 0)
// remoteEips := make([]cloudprovider.ICloudEIP, 0)
syncResult := compare.SyncResult{}
@@ -167,7 +167,7 @@ func (manager *SElasticipManager) SyncEips(ctx context.Context, userCred mcclien
}
}
for i := 0; i < len(commondb); i += 1 {
err = commondb[i].SyncWithCloudEip(userCred, commonext[i])
err = commondb[i].SyncWithCloudEip(userCred, commonext[i], projectId, projectSync)
if err != nil {
syncResult.UpdateError(err)
} else {
@@ -175,7 +175,7 @@ func (manager *SElasticipManager) SyncEips(ctx context.Context, userCred mcclien
}
}
for i := 0; i < len(added); i += 1 {
_, err := manager.newFromCloudEip(userCred, added[i], region)
_, err := manager.newFromCloudEip(userCred, added[i], region, projectId)
if err != nil {
syncResult.AddError(err)
} else {
@@ -221,7 +221,7 @@ func (self *SElasticip) SyncInstanceWithCloudEip(ctx context.Context, userCred m
return nil
}
func (self *SElasticip) SyncWithCloudEip(userCred mcclient.TokenCredential, ext cloudprovider.ICloudEIP) error {
func (self *SElasticip) SyncWithCloudEip(userCred mcclient.TokenCredential, ext cloudprovider.ICloudEIP, projectId string, projectSync bool) error {
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
// self.Name = ext.GetName()
@@ -232,7 +232,10 @@ func (self *SElasticip) SyncWithCloudEip(userCred mcclient.TokenCredential, ext
self.ExternalId = ext.GetGlobalId()
// self.ManagerId = ext.GetManagerId()
self.IsEmulated = ext.IsEmulated()
// self.ProjectId = userCred.GetProjectId()
self.ProjectId = userCred.GetProjectId()
if projectSync && len(projectId) > 0 {
self.ProjectId = projectId
}
self.ChargeType = ext.GetInternetChargeType()
return nil
@@ -243,7 +246,7 @@ func (self *SElasticip) SyncWithCloudEip(userCred mcclient.TokenCredential, ext
return err
}
func (manager *SElasticipManager) newFromCloudEip(userCred mcclient.TokenCredential, extEip cloudprovider.ICloudEIP, region *SCloudregion) (*SElasticip, error) {
func (manager *SElasticipManager) newFromCloudEip(userCred mcclient.TokenCredential, extEip cloudprovider.ICloudEIP, region *SCloudregion, projectId string) (*SElasticip, error) {
eip := SElasticip{}
eip.SetModelManager(manager)
@@ -258,6 +261,9 @@ func (manager *SElasticipManager) newFromCloudEip(userCred mcclient.TokenCredent
eip.ChargeType = extEip.GetInternetChargeType()
eip.ProjectId = userCred.GetProjectId()
if len(projectId) > 0 {
eip.ProjectId = projectId
}
err := manager.TableSpec().Insert(&eip)
if err != nil {
@@ -344,7 +350,7 @@ func (self *SElasticip) AssociateVM(userCred mcclient.TokenCredential, vm *SGues
return nil
}
func (manager *SElasticipManager) getEipByExtEip(userCred mcclient.TokenCredential, extEip cloudprovider.ICloudEIP, region *SCloudregion) (*SElasticip, error) {
func (manager *SElasticipManager) getEipByExtEip(userCred mcclient.TokenCredential, extEip cloudprovider.ICloudEIP, region *SCloudregion, projectId string) (*SElasticip, error) {
eipObj, err := manager.FetchByExternalId(extEip.GetGlobalId())
if err == nil {
return eipObj.(*SElasticip), nil
@@ -354,7 +360,7 @@ func (manager *SElasticipManager) getEipByExtEip(userCred mcclient.TokenCredenti
return nil, err
}
return manager.newFromCloudEip(userCred, extEip, region)
return manager.newFromCloudEip(userCred, extEip, region, projectId)
}
func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
+17 -8
View File
@@ -1337,7 +1337,7 @@ func (self *SGuest) GetIsolatedDevices() []SIsolatedDevice {
return IsolatedDeviceManager.findAttachedDevicesOfGuest(self)
}
func (self *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, extVM cloudprovider.ICloudVM) error {
func (self *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, extVM cloudprovider.ICloudVM, projectId string, projectSync bool) error {
metaData := extVM.GetMetadata()
diff, err := GuestManager.TableSpec().Update(self, func() error {
extVM.Refresh()
@@ -1353,6 +1353,11 @@ func (self *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.Token
self.Machine = extVM.GetMachine()
self.HostId = host.Id
self.ProjectId = userCred.GetProjectId()
if projectSync && len(projectId) > 0 {
self.ProjectId = projectId
}
self.Hypervisor = extVM.GetHypervisor()
self.IsEmulated = extVM.IsEmulated()
@@ -1396,7 +1401,7 @@ func (self *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.Token
return nil
}
func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, extVM cloudprovider.ICloudVM) (*SGuest, error) {
func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, extVM cloudprovider.ICloudVM, projectId string) (*SGuest, error) {
guest := SGuest{}
guest.SetModelManager(manager)
@@ -1420,7 +1425,11 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
guest.ExpiredAt = extVM.GetExpiredAt()
guest.HostId = host.Id
guest.ProjectId = userCred.GetProjectId()
if len(projectId) > 0 {
guest.ProjectId = projectId
}
metaData := extVM.GetMetadata()
@@ -1893,7 +1902,7 @@ type sSyncDiskPair struct {
vdisk cloudprovider.ICloudDisk
}
func (self *SGuest) SyncVMDisks(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, vdisks []cloudprovider.ICloudDisk) compare.SyncResult {
func (self *SGuest) SyncVMDisks(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, vdisks []cloudprovider.ICloudDisk, projectId string, projectSync bool) compare.SyncResult {
result := compare.SyncResult{}
newdisks := make([]sSyncDiskPair, 0)
@@ -1901,7 +1910,7 @@ func (self *SGuest) SyncVMDisks(ctx context.Context, userCred mcclient.TokenCred
if len(vdisks[i].GetGlobalId()) == 0 {
continue
}
disk, err := DiskManager.syncCloudDisk(ctx, userCred, vdisks[i])
disk, err := DiskManager.syncCloudDisk(ctx, userCred, vdisks[i], projectId, projectSync)
if err != nil {
result.Error(err)
return result
@@ -4275,7 +4284,7 @@ func (self *SGuest) GetEip() (*SElasticip, error) {
return ElasticipManager.getEipForInstance("server", self.Id)
}
func (self *SGuest) SyncVMEip(ctx context.Context, userCred mcclient.TokenCredential, extEip cloudprovider.ICloudEIP) compare.SyncResult {
func (self *SGuest) SyncVMEip(ctx context.Context, userCred mcclient.TokenCredential, extEip cloudprovider.ICloudEIP, projectId string) compare.SyncResult {
result := compare.SyncResult{}
eip, err := self.GetEip()
@@ -4288,7 +4297,7 @@ func (self *SGuest) SyncVMEip(ctx context.Context, userCred mcclient.TokenCreden
// do nothing
} else if eip == nil && extEip != nil {
// add
neip, err := ElasticipManager.getEipByExtEip(userCred, extEip, self.getRegion())
neip, err := ElasticipManager.getEipByExtEip(userCred, extEip, self.getRegion(), projectId)
if err != nil {
result.AddError(err)
} else {
@@ -4317,7 +4326,7 @@ func (self *SGuest) SyncVMEip(ctx context.Context, userCred mcclient.TokenCreden
result.DeleteError(err)
} else {
result.Delete()
neip, err := ElasticipManager.getEipByExtEip(userCred, extEip, self.getRegion())
neip, err := ElasticipManager.getEipByExtEip(userCred, extEip, self.getRegion(), projectId)
if err != nil {
result.AddError(err)
} else {
@@ -4331,7 +4340,7 @@ func (self *SGuest) SyncVMEip(ctx context.Context, userCred mcclient.TokenCreden
}
} else {
// do nothing
err := eip.SyncWithCloudEip(userCred, extEip)
err := eip.SyncWithCloudEip(userCred, extEip, projectId, false)
if err != nil {
result.UpdateError(err)
} else {
+3 -3
View File
@@ -1222,7 +1222,7 @@ func (self *SHost) newCloudHostWire(ctx context.Context, userCred mcclient.Token
return err
}
func (self *SHost) SyncHostVMs(ctx context.Context, userCred mcclient.TokenCredential, vms []cloudprovider.ICloudVM) ([]SGuest, []cloudprovider.ICloudVM, compare.SyncResult) {
func (self *SHost) SyncHostVMs(ctx context.Context, userCred mcclient.TokenCredential, vms []cloudprovider.ICloudVM, projectId string, projectSync bool) ([]SGuest, []cloudprovider.ICloudVM, compare.SyncResult) {
localVMs := make([]SGuest, 0)
remoteVMs := make([]cloudprovider.ICloudVM, 0)
syncResult := compare.SyncResult{}
@@ -1250,7 +1250,7 @@ func (self *SHost) SyncHostVMs(ctx context.Context, userCred mcclient.TokenCrede
}
for i := 0; i < len(commondb); i += 1 {
err := commondb[i].syncWithCloudVM(ctx, userCred, self, commonext[i])
err := commondb[i].syncWithCloudVM(ctx, userCred, self, commonext[i], projectId, projectSync)
if err != nil {
syncResult.UpdateError(err)
} else {
@@ -1261,7 +1261,7 @@ func (self *SHost) SyncHostVMs(ctx context.Context, userCred mcclient.TokenCrede
}
for i := 0; i < len(added); i += 1 {
new, err := GuestManager.newCloudVM(ctx, userCred, self, added[i])
new, err := GuestManager.newCloudVM(ctx, userCred, self, added[i], projectId)
if err != nil {
syncResult.AddError(err)
} else {
+1
View File
@@ -8,6 +8,7 @@ import (
func InitDB() error {
for _, manager := range []db.IModelManager{
CloudproviderManager,
CloudaccountManager,
CloudregionManager,
ZoneManager,
VpcManager,
+11 -6
View File
@@ -413,7 +413,7 @@ func (manager *SNetworkManager) getNetworksByWire(wire *SWire) ([]SNetwork, erro
return nets, nil
}
func (manager *SNetworkManager) SyncNetworks(ctx context.Context, userCred mcclient.TokenCredential, wire *SWire, nets []cloudprovider.ICloudNetwork) ([]SNetwork, []cloudprovider.ICloudNetwork, compare.SyncResult) {
func (manager *SNetworkManager) SyncNetworks(ctx context.Context, userCred mcclient.TokenCredential, wire *SWire, nets []cloudprovider.ICloudNetwork, projectId string, projectSync bool) ([]SNetwork, []cloudprovider.ICloudNetwork, compare.SyncResult) {
localNets := make([]SNetwork, 0)
remoteNets := make([]cloudprovider.ICloudNetwork, 0)
syncResult := compare.SyncResult{}
@@ -455,7 +455,7 @@ func (manager *SNetworkManager) SyncNetworks(ctx context.Context, userCred mccli
}
}
for i := 0; i < len(commondb); i += 1 {
err = commondb[i].SyncWithCloudNetwork(userCred, commonext[i])
err = commondb[i].SyncWithCloudNetwork(userCred, commonext[i], projectId, projectSync)
if err != nil {
syncResult.UpdateError(err)
} else {
@@ -465,7 +465,7 @@ func (manager *SNetworkManager) SyncNetworks(ctx context.Context, userCred mccli
}
}
for i := 0; i < len(added); i += 1 {
new, err := manager.newFromCloudNetwork(userCred, added[i], wire)
new, err := manager.newFromCloudNetwork(userCred, added[i], wire, projectId)
if err != nil {
syncResult.AddError(err)
} else {
@@ -478,7 +478,7 @@ func (manager *SNetworkManager) SyncNetworks(ctx context.Context, userCred mccli
return localNets, remoteNets, syncResult
}
func (self *SNetwork) SyncWithCloudNetwork(userCred mcclient.TokenCredential, extNet cloudprovider.ICloudNetwork) error {
func (self *SNetwork) SyncWithCloudNetwork(userCred mcclient.TokenCredential, extNet cloudprovider.ICloudNetwork, projectId string, projectSync bool) error {
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
extNet.Refresh()
self.Name = extNet.GetName()
@@ -493,6 +493,9 @@ func (self *SNetwork) SyncWithCloudNetwork(userCred mcclient.TokenCredential, ex
self.AllocTimoutSeconds = extNet.GetAllocTimeoutSeconds()
self.ProjectId = userCred.GetProjectId()
if projectSync && len(projectId) > 0 {
self.ProjectId = projectId
}
return nil
})
if err != nil {
@@ -501,7 +504,7 @@ func (self *SNetwork) SyncWithCloudNetwork(userCred mcclient.TokenCredential, ex
return err
}
func (manager *SNetworkManager) newFromCloudNetwork(userCred mcclient.TokenCredential, extNet cloudprovider.ICloudNetwork, wire *SWire) (*SNetwork, error) {
func (manager *SNetworkManager) newFromCloudNetwork(userCred mcclient.TokenCredential, extNet cloudprovider.ICloudNetwork, wire *SWire, projectId string) (*SNetwork, error) {
net := SNetwork{}
net.SetModelManager(manager)
@@ -519,7 +522,9 @@ func (manager *SNetworkManager) newFromCloudNetwork(userCred mcclient.TokenCrede
net.AllocTimoutSeconds = extNet.GetAllocTimeoutSeconds()
net.ProjectId = userCred.GetProjectId()
if len(projectId) > 0 {
net.ProjectId = projectId
}
err := manager.TableSpec().Insert(&net)
if err != nil {
log.Errorf("newFromCloudZone fail %s", err)
+11 -5
View File
@@ -417,9 +417,12 @@ func totalSnapshotCount(projectId string) int {
}
// Only sync snapshot status
func (self *SSnapshot) SyncWithCloudSnapshot(userCred mcclient.TokenCredential, ext cloudprovider.ICloudSnapshot) error {
func (self *SSnapshot) SyncWithCloudSnapshot(userCred mcclient.TokenCredential, ext cloudprovider.ICloudSnapshot, projectId string, projectSync bool) error {
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
self.Status = ext.GetStatus()
if projectSync && len(projectId) > 0 {
self.ProjectId = projectId
}
return nil
})
if err != nil {
@@ -428,7 +431,7 @@ func (self *SSnapshot) SyncWithCloudSnapshot(userCred mcclient.TokenCredential,
return err
}
func (manager *SSnapshotManager) newFromCloudSnapshot(userCred mcclient.TokenCredential, extSnapshot cloudprovider.ICloudSnapshot, region *SCloudregion) (*SSnapshot, error) {
func (manager *SSnapshotManager) newFromCloudSnapshot(userCred mcclient.TokenCredential, extSnapshot cloudprovider.ICloudSnapshot, region *SCloudregion, projectId string) (*SSnapshot, error) {
snapshot := SSnapshot{}
snapshot.SetModelManager(manager)
@@ -449,6 +452,9 @@ func (manager *SSnapshotManager) newFromCloudSnapshot(userCred mcclient.TokenCre
snapshot.CloudregionId = region.Id
snapshot.ProjectId = userCred.GetProjectId()
if len(projectId) > 0 {
snapshot.ProjectId = projectId
}
err := manager.TableSpec().Insert(&snapshot)
if err != nil {
log.Errorf("newFromCloudEip fail %s", err)
@@ -470,7 +476,7 @@ func (manager *SSnapshotManager) getProviderSnapshotsByRegion(region *SCloudregi
return snapshots, nil
}
func (manager *SSnapshotManager) SyncSnapshots(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, snapshots []cloudprovider.ICloudSnapshot) compare.SyncResult {
func (manager *SSnapshotManager) SyncSnapshots(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, snapshots []cloudprovider.ICloudSnapshot, projectId string, projectSync bool) compare.SyncResult {
syncResult := compare.SyncResult{}
dbSnapshots, err := manager.getProviderSnapshotsByRegion(region, provider)
if err != nil {
@@ -496,7 +502,7 @@ func (manager *SSnapshotManager) SyncSnapshots(ctx context.Context, userCred mcc
}
}
for i := 0; i < len(commondb); i += 1 {
err = commondb[i].SyncWithCloudSnapshot(userCred, commonext[i])
err = commondb[i].SyncWithCloudSnapshot(userCred, commonext[i], projectId, projectSync)
if err != nil {
syncResult.UpdateError(err)
} else {
@@ -504,7 +510,7 @@ func (manager *SSnapshotManager) SyncSnapshots(ctx context.Context, userCred mcc
}
}
for i := 0; i < len(added); i += 1 {
_, err := manager.newFromCloudSnapshot(userCred, added[i], region)
_, err := manager.newFromCloudSnapshot(userCred, added[i], region, projectId)
if err != nil {
syncResult.AddError(err)
} else {
@@ -0,0 +1,85 @@
package tasks
import (
"context"
"yunion.io/x/jsonutils"
"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/compute/models"
)
type CloudAccountSyncInfoTask struct {
taskman.STask
}
func init() {
taskman.RegisterTask(CloudAccountSyncInfoTask{})
}
func (self *CloudAccountSyncInfoTask) OnInit(ctx context.Context, objs []db.IStandaloneModel, body jsonutils.JSONObject) {
cloudproviders := make([]*models.SCloudprovider, 0)
for _, obj := range objs {
cloudprovider := obj.(*models.SCloudprovider)
if cloudprovider.Enabled {
cloudproviders = append(cloudproviders, cloudprovider)
}
}
var account *models.SCloudaccount
if len(cloudproviders) > 0 {
if account = models.CloudaccountManager.FetchCloudaccountById(cloudproviders[0].CloudaccountId); account == nil {
account.SetStatus(self.UserCred, models.CLOUD_PROVIDER_CONNECTED, "")
self.SetStageComplete(ctx, nil)
return
}
} else {
account.SetStatus(self.UserCred, models.CLOUD_PROVIDER_CONNECTED, "")
self.SetStageComplete(ctx, nil)
return
}
if _, err := account.GetSubAccounts(); err != nil {
account.SetStatus(self.UserCred, models.CLOUD_PROVIDER_DISCONNECTED, "")
self.SetStageFailed(ctx, err.Error())
return
}
syncRange := models.SSyncRange{}
syncRangeJson, _ := self.Params.Get("sync_range")
if syncRangeJson != nil {
syncRangeJson.Unmarshal(&syncRange)
}
if len(syncRange.Host) == 0 && !syncRange.FullSync {
account.SetStatus(self.UserCred, models.CLOUD_PROVIDER_CONNECTED, "")
self.SetStageComplete(ctx, nil)
return
}
// do sync
self.SetStage("on_cloudaccount_sync_complete", nil)
self.SyncCloudaccount(ctx, account, cloudproviders, &syncRange)
}
func (self *CloudAccountSyncInfoTask) SyncCloudaccount(ctx context.Context, account *models.SCloudaccount, cloudproviders []*models.SCloudprovider, syncRange *models.SSyncRange) {
for _, cloudprovider := range cloudproviders {
self.SyncCloudprovider(ctx, cloudprovider, syncRange)
}
}
func (self *CloudAccountSyncInfoTask) SyncCloudprovider(ctx context.Context, cloudprovider *models.SCloudprovider, syncRange *models.SSyncRange) {
lockman.LockObject(ctx, cloudprovider)
defer lockman.ReleaseObject(ctx, cloudprovider)
cloudprovider.StartSyncCloudProviderInfoTask(ctx, self.UserCred, syncRange, self.GetId())
}
func (self *CloudAccountSyncInfoTask) OnCloudaccountSyncComplete(ctx context.Context, items []db.IStandaloneModel, data jsonutils.JSONObject) {
if len(items) > 0 {
cloudprovider := items[0].(*models.SCloudprovider)
if account := models.CloudaccountManager.FetchCloudaccountById(cloudprovider.CloudaccountId); account != nil {
account.SetStatus(self.UserCred, models.CLOUD_PROVIDER_CONNECTED, "")
}
}
self.SetStageComplete(ctx, nil)
}
@@ -108,11 +108,11 @@ func syncCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider,
if len(syncRange.Region) > 0 && !utils.IsInStringArray(localRegions[i].Id, syncRange.Region) {
continue
}
syncRegionEips(ctx, provider, task, &localRegions[i], remoteRegions[i])
syncRegionEips(ctx, provider, task, &localRegions[i], remoteRegions[i], syncRange)
localZones, remoteZones := syncRegionZones(ctx, provider, task, &localRegions[i], remoteRegions[i])
syncRegionVPCs(ctx, provider, task, &localRegions[i], remoteRegions[i])
syncRegionVPCs(ctx, provider, task, &localRegions[i], remoteRegions[i], syncRange)
if localZones != nil && remoteZones != nil {
for j := 0; j < len(localZones); j += 1 {
@@ -120,15 +120,15 @@ func syncCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider,
if len(syncRange.Zone) > 0 && !utils.IsInStringArray(localZones[j].Id, syncRange.Zone) {
continue
}
syncZoneStorages(ctx, provider, task, &localZones[j], remoteZones[j])
syncZoneStorages(ctx, provider, task, &localZones[j], remoteZones[j], syncRange)
syncZoneHosts(ctx, provider, task, &localZones[j], remoteZones[j], syncRange)
}
}
syncRegionSnapshots(ctx, provider, task, &localRegions[i], remoteRegions[i])
syncRegionSnapshots(ctx, provider, task, &localRegions[i], remoteRegions[i], syncRange)
}
}
func syncRegionSnapshots(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localRegion *models.SCloudregion, remoteRegion cloudprovider.ICloudRegion) {
func syncRegionSnapshots(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localRegion *models.SCloudregion, remoteRegion cloudprovider.ICloudRegion, syncRange *models.SSyncRange) {
snapshots, err := remoteRegion.GetISnapshots()
if err != nil {
msg := fmt.Sprintf("GetISnapshots for region %s failed %s", remoteRegion.GetName(), err)
@@ -137,7 +137,7 @@ func syncRegionSnapshots(ctx context.Context, provider *models.SCloudprovider, t
return
}
result := models.SnapshotManager.SyncSnapshots(ctx, task.GetUserCred(), provider, localRegion, snapshots)
result := models.SnapshotManager.SyncSnapshots(ctx, task.GetUserCred(), provider, localRegion, snapshots, provider.ProjectId, syncRange.ProjectSync)
msg := result.Result()
log.Infof("SyncSnapshots for region %s result: %s", localRegion.Name, msg)
if result.IsError() {
@@ -147,7 +147,7 @@ func syncRegionSnapshots(ctx context.Context, provider *models.SCloudprovider, t
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.GetUserCred())
}
func syncRegionEips(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localRegion *models.SCloudregion, remoteRegion cloudprovider.ICloudRegion) {
func syncRegionEips(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localRegion *models.SCloudregion, remoteRegion cloudprovider.ICloudRegion, syncRange *models.SSyncRange) {
eips, err := remoteRegion.GetIEips()
if err != nil {
msg := fmt.Sprintf("GetIEips for region %s failed %s", remoteRegion.GetName(), err)
@@ -156,7 +156,7 @@ func syncRegionEips(ctx context.Context, provider *models.SCloudprovider, task *
return
}
result := models.ElasticipManager.SyncEips(ctx, task.UserCred, provider, localRegion, eips)
result := models.ElasticipManager.SyncEips(ctx, task.UserCred, provider, localRegion, eips, provider.ProjectId, syncRange.ProjectSync)
msg := result.Result()
log.Infof("SyncEips for region %s result: %s", localRegion.Name, msg)
if result.IsError() {
@@ -187,7 +187,7 @@ func syncRegionZones(ctx context.Context, provider *models.SCloudprovider, task
return localZones, remoteZones
}
func syncRegionVPCs(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localRegion *models.SCloudregion, remoteRegion cloudprovider.ICloudRegion) {
func syncRegionVPCs(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localRegion *models.SCloudregion, remoteRegion cloudprovider.ICloudRegion, syncRange *models.SSyncRange) {
vpcs, err := remoteRegion.GetIVpcs()
if err != nil {
msg := fmt.Sprintf("GetVpcs for region %s failed %s", remoteRegion.GetName(), err)
@@ -207,7 +207,7 @@ func syncRegionVPCs(ctx context.Context, provider *models.SCloudprovider, task *
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.UserCred)
logclient.AddActionLog(provider, getAction(task.Params), notes, task.UserCred, true)
for j := 0; j < len(localVpcs); j += 1 {
syncVpcWires(ctx, provider, task, &localVpcs[j], remoteVpcs[j])
syncVpcWires(ctx, provider, task, &localVpcs[j], remoteVpcs[j], syncRange)
syncVpcSecGroup(ctx, provider, task, &localVpcs[j], remoteVpcs[j])
}
}
@@ -230,7 +230,7 @@ func syncVpcSecGroup(ctx context.Context, provider *models.SCloudprovider, task
}
}
func syncVpcWires(ctx context.Context, provider *models.SCloudprovider, task taskman.ITask, localVpc *models.SVpc, remoteVpc cloudprovider.ICloudVpc) {
func syncVpcWires(ctx context.Context, provider *models.SCloudprovider, task taskman.ITask, localVpc *models.SVpc, remoteVpc cloudprovider.ICloudVpc, syncRange *models.SSyncRange) {
wires, err := remoteVpc.GetIWires()
if err != nil {
msg := fmt.Sprintf("GetIWires for vpc %s failed %s", remoteVpc.GetId(), err)
@@ -249,11 +249,11 @@ func syncVpcWires(ctx context.Context, provider *models.SCloudprovider, task tas
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.GetUserCred())
logclient.AddActionLog(provider, getAction(task.GetParams()), notes, task.GetUserCred(), true)
for i := 0; i < len(localWires); i += 1 {
syncWireNetworks(ctx, provider, task, &localWires[i], remoteWires[i])
syncWireNetworks(ctx, provider, task, &localWires[i], remoteWires[i], syncRange)
}
}
func syncWireNetworks(ctx context.Context, provider *models.SCloudprovider, task taskman.ITask, localWire *models.SWire, remoteWire cloudprovider.ICloudWire) {
func syncWireNetworks(ctx context.Context, provider *models.SCloudprovider, task taskman.ITask, localWire *models.SWire, remoteWire cloudprovider.ICloudWire, syncRange *models.SSyncRange) {
nets, err := remoteWire.GetINetworks()
if err != nil {
msg := fmt.Sprintf("GetINetworks for wire %s failed %s", remoteWire.GetId(), err)
@@ -261,7 +261,7 @@ func syncWireNetworks(ctx context.Context, provider *models.SCloudprovider, task
logSyncFailed(provider, task, msg)
return
}
_, _, result := models.NetworkManager.SyncNetworks(ctx, task.GetUserCred(), localWire, nets)
_, _, result := models.NetworkManager.SyncNetworks(ctx, task.GetUserCred(), localWire, nets, provider.ProjectId, syncRange.ProjectSync)
msg := result.Result()
notes := fmt.Sprintf("SyncNetworks for wire %s result: %s", localWire.Name, msg)
log.Infof(notes)
@@ -273,7 +273,7 @@ func syncWireNetworks(ctx context.Context, provider *models.SCloudprovider, task
logclient.AddActionLog(provider, getAction(task.GetParams()), notes, task.GetUserCred(), true)
}
func syncZoneStorages(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localZone *models.SZone, remoteZone cloudprovider.ICloudZone) {
func syncZoneStorages(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localZone *models.SZone, remoteZone cloudprovider.ICloudZone, syncRange *models.SSyncRange) {
storages, err := remoteZone.GetIStorages()
if err != nil {
msg := fmt.Sprintf("GetIStorages for zone %s failed %s", remoteZone.GetName(), err)
@@ -294,7 +294,7 @@ func syncZoneStorages(ctx context.Context, provider *models.SCloudprovider, task
for i := 0; i < len(localStorages); i += 1 {
syncStorageCaches(ctx, provider, task, &localStorages[i], remoteStorages[i])
syncStorageDisks(ctx, provider, task, &localStorages[i], remoteStorages[i])
syncStorageDisks(ctx, provider, task, &localStorages[i], remoteStorages[i], syncRange)
}
}
@@ -315,7 +315,7 @@ func syncStorageCaches(ctx context.Context, provider *models.SCloudprovider, tas
}
}
func syncStorageDisks(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localStorage *models.SStorage, remoteStorage cloudprovider.ICloudStorage) {
func syncStorageDisks(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localStorage *models.SStorage, remoteStorage cloudprovider.ICloudStorage, syncRange *models.SSyncRange) {
disks, err := remoteStorage.GetIDisks()
if err != nil {
msg := fmt.Sprintf("GetIDisks for storage %s failed %s", remoteStorage.GetName(), err)
@@ -323,7 +323,7 @@ func syncStorageDisks(ctx context.Context, provider *models.SCloudprovider, task
logSyncFailed(provider, task, msg)
return
}
_, _, result := models.DiskManager.SyncDisks(ctx, task.UserCred, localStorage, disks)
_, _, result := models.DiskManager.SyncDisks(ctx, task.UserCred, localStorage, disks, provider.ProjectId, syncRange.ProjectSync)
msg := result.Result()
notes := fmt.Sprintf("SyncDisks for storage %s result: %s", localStorage.Name, msg)
log.Infof(notes)
@@ -359,7 +359,7 @@ func syncZoneHosts(ctx context.Context, provider *models.SCloudprovider, task *C
}
syncHostStorages(ctx, provider, task, &localHosts[i], remoteHosts[i])
syncHostWires(ctx, provider, task, &localHosts[i], remoteHosts[i])
syncHostVMs(ctx, provider, task, &localHosts[i], remoteHosts[i])
syncHostVMs(ctx, provider, task, &localHosts[i], remoteHosts[i], syncRange)
}
}
@@ -403,7 +403,7 @@ func syncHostWires(ctx context.Context, provider *models.SCloudprovider, task ta
logclient.AddActionLog(provider, getAction(task.GetParams()), notes, task.GetUserCred(), true)
}
func syncHostVMs(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localHost *models.SHost, remoteHost cloudprovider.ICloudHost) {
func syncHostVMs(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localHost *models.SHost, remoteHost cloudprovider.ICloudHost, syncRange *models.SSyncRange) {
vms, err := remoteHost.GetIVMs()
if err != nil {
msg := fmt.Sprintf("GetIVMs for host %s failed %s", remoteHost.GetName(), err)
@@ -411,7 +411,7 @@ func syncHostVMs(ctx context.Context, provider *models.SCloudprovider, task *Clo
logSyncFailed(provider, task, msg)
return
}
localVMs, remoteVMs, result := localHost.SyncHostVMs(ctx, task.UserCred, vms)
localVMs, remoteVMs, result := localHost.SyncHostVMs(ctx, task.UserCred, vms, provider.ProjectId, syncRange.ProjectSync)
msg := result.Result()
notes := fmt.Sprintf("SyncHostVMs for host %s result: %s", localHost.Name, msg)
log.Infof(notes)
@@ -423,7 +423,7 @@ func syncHostVMs(ctx context.Context, provider *models.SCloudprovider, task *Clo
logclient.AddActionLog(provider, getAction(task.Params), notes, task.UserCred, true)
for i := 0; i < len(localVMs); i += 1 {
syncVMNics(ctx, provider, task, localHost, &localVMs[i], remoteVMs[i])
syncVMDisks(ctx, provider, task, localHost, &localVMs[i], remoteVMs[i])
syncVMDisks(ctx, provider, task, localHost, &localVMs[i], remoteVMs[i], syncRange)
syncVMEip(ctx, provider, task, &localVMs[i], remoteVMs[i])
}
}
@@ -448,7 +448,7 @@ func syncVMNics(ctx context.Context, provider *models.SCloudprovider, task *Clou
logclient.AddActionLog(provider, getAction(task.Params), notes, task.UserCred, true)
}
func syncVMDisks(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, host *models.SHost, localVM *models.SGuest, remoteVM cloudprovider.ICloudVM) {
func syncVMDisks(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, host *models.SHost, localVM *models.SGuest, remoteVM cloudprovider.ICloudVM, syncRange *models.SSyncRange) {
disks, err := remoteVM.GetIDisks()
if err != nil {
msg := fmt.Sprintf("GetIDisks for VM %s failed %s", remoteVM.GetName(), err)
@@ -456,7 +456,7 @@ func syncVMDisks(ctx context.Context, provider *models.SCloudprovider, task *Clo
logSyncFailed(provider, task, msg)
return
}
result := localVM.SyncVMDisks(ctx, task.UserCred, host, disks)
result := localVM.SyncVMDisks(ctx, task.UserCred, host, disks, provider.ProjectId, syncRange.ProjectSync)
msg := result.Result()
notes := fmt.Sprintf("syncVMNics for VM %s result: %s", localVM.Name, msg)
log.Infof(notes)
@@ -476,7 +476,7 @@ func syncVMEip(ctx context.Context, provider *models.SCloudprovider, task *Cloud
logSyncFailed(provider, task, msg)
return
}
result := localVM.SyncVMEip(ctx, task.UserCred, eip)
result := localVM.SyncVMEip(ctx, task.UserCred, eip, provider.ProjectId)
msg := result.Result()
log.Infof("syncVMEip for VM %s result: %s", localVM.Name, msg)
if result.IsError() {
+1 -1
View File
@@ -39,7 +39,7 @@ func (self *EipAllocateTask) OnInit(ctx context.Context, obj db.IStandaloneModel
return
}
err = eip.SyncWithCloudEip(self.UserCred, extEip)
err = eip.SyncWithCloudEip(self.UserCred, extEip, "", false)
if err != nil {
msg := fmt.Sprintf("sync eip fail %s", err)
+1 -1
View File
@@ -38,7 +38,7 @@ func (self *EipSyncstatusTask) OnInit(ctx context.Context, obj db.IStandaloneMod
return
}
err = eip.SyncWithCloudEip(self.UserCred, extEip)
err = eip.SyncWithCloudEip(self.UserCred, extEip, "", false)
if err != nil {
msg := fmt.Sprintf("fail to sync eip status %s", err)
eip.SetStatus(self.UserCred, models.EIP_STATUS_UNKNOWN, msg)
+1 -1
View File
@@ -64,7 +64,7 @@ func (self *NetworkCreateTask) OnInit(ctx context.Context, obj db.IStandaloneMod
return
}
err = network.SyncWithCloudNetwork(self.UserCred, inet)
err = network.SyncWithCloudNetwork(self.UserCred, inet, "", false)
if err != nil {
self.taskFailed(ctx, network, "SyncWithCloudNetwork", err)
+1 -1
View File
@@ -57,7 +57,7 @@ func (self *VpcCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
}
provider := models.CloudproviderManager.FetchCloudproviderById(vpc.ManagerId)
syncVpcWires(ctx, provider, self, vpc, ivpc)
syncVpcWires(ctx, provider, self, vpc, ivpc, &models.SSyncRange{})
hosts := models.HostManager.GetHostsByManagerAndRegion(provider.Id, vpc.CloudregionId)
if hosts != nil {
+14
View File
@@ -0,0 +1,14 @@
package modules
var (
Cloudaccounts ResourceManager
)
func init() {
Cloudaccounts = NewComputeManager("cloudaccount", "cloudaccounts",
[]string{"ID", "Name", "Enabled", "Status", "Access_url", "Account",
"Last_sync", "Provider"},
[]string{})
registerCompute(&Cloudaccounts)
}
+11 -1
View File
@@ -122,7 +122,17 @@ func (self *SAliyunClient) GetRegions() []SRegion {
}
func (self *SAliyunClient) GetSubAccounts() (jsonutils.JSONObject, error) {
return nil, nil
if err := self.fetchRegions(); err != nil {
return nil, err
} else {
result := jsonutils.NewDict()
data := jsonutils.NewArray()
account := jsonutils.Marshal(map[string]string{"account": self.accessKey, "name": self.providerName})
data.Add(account)
result.Add(data, "data")
result.Add(jsonutils.NewInt(1), "total")
return result, nil
}
}
func (self *SAliyunClient) GetIRegions() []cloudprovider.ICloudRegion {
+2 -2
View File
@@ -163,9 +163,9 @@ func (self *SAzureClient) GetSubAccounts() (jsonutils.JSONObject, error) {
} else {
for _, value := range resp.Values() {
data := jsonutils.NewDict()
data.Add(jsonutils.NewString(*value.SubscriptionID), "subscriptionId")
data.Add(jsonutils.NewString(*value.SubscriptionID), "account")
data.Add(jsonutils.NewString(string(value.State)), "state")
data.Add(jsonutils.NewString(*value.DisplayName), "displayName")
data.Add(jsonutils.NewString(*value.DisplayName), "name")
accounts.Add(data)
}
result.Add(accounts, "data")
+14
View File
@@ -88,6 +88,20 @@ func (cli *SESXiClient) disconnect() error {
return nil
}
func (cli *SESXiClient) GetSubAccounts() (jsonutils.JSONObject, error) {
if err := cli.connect(); err != nil {
return nil, err
} else {
result := jsonutils.NewDict()
data := jsonutils.NewArray()
account := jsonutils.Marshal(map[string]string{"account": cli.account, "name": cli.providerName})
data.Add(account)
result.Add(data, "data")
result.Add(jsonutils.NewInt(1), "total")
return result, nil
}
}
func (cli *SESXiClient) About() jsonutils.JSONObject {
return jsonutils.Marshal(&cli.client.ServiceContent.About)
}
+1 -1
View File
@@ -88,7 +88,7 @@ func (self *SESXiProvider) GetSysInfo() (jsonutils.JSONObject, error) {
}
func (self *SESXiProvider) GetSubAccounts() (jsonutils.JSONObject, error) {
return nil, nil
return self.client.GetSubAccounts()
}
func (self *SESXiProvider) GetIRegions() []cloudprovider.ICloudRegion {