fix: recode cloud-account-create commands, easier to use

This commit is contained in:
Qiu Jian
2019-03-13 01:42:07 +08:00
parent b930257c6d
commit 300f4e5163
13 changed files with 301 additions and 83 deletions
+128 -40
View File
@@ -33,7 +33,6 @@ func init() {
})
type CloudaccountCreateOptions struct {
NAME string `help:"Name of cloud account"`
AccessKeyID string `help:"Aiyun|HuaWei|Aws access_key_id"`
AccessKeySecret string `help:"Aiyun|HuaWei|Aws access_key_secret"`
AppID string `help:"Qcloud appid"`
@@ -49,60 +48,85 @@ func init() {
ClientID string `help:"Azure client_id"`
ClientSecret string `help:"Azure clinet_secret"`
Environment string `help:"Azure|Huawei|Aws environment" choices:"AzureGermanCloud|AzureChinaCloud|AzureUSGovernmentCloud|AzurePublicCloud|InternationalCloud|ChinaCloud|"`
PROVIDER string `help:"Driver for cloud account" choices:"VMware|Aliyun|Azure|Qcloud|OpenStack|Huawei|Aws"`
Desc string `help:"Description"`
Enabled bool `help:"Enabled the account automatically"`
Import bool `help:"Import all sub account automatically"`
AutoSync bool `help:"Enabled the account automatically"`
AutoCreateProject bool `help:"Enable the account with same name project"`
Enabled bool `help:"Enabled the account automatically"`
Import bool `help:"Import all sub account automatically"`
AutoSync bool `help:"Enabled the 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.PROVIDER), "provider")
data := jsonutils.Marshal(args)
return fmt.Errorf("obsolete, please try cloud-account-create-xxx, where xxx is vmware, aliyun, azure, qcloud, aws, openstack, huawei etc.")
})
requireParamsMap := map[string][]string{
"VMware": {"username", "password", "host", "port"},
"Aliyun": {"access_key_id", "access_key_secret"},
"Azure": {"directory_id", "client_id", "client_secret", "environment"},
"Qcloud": {"app_id", "secret_id", "secret_key"},
"OpenStack": {"project_name", "username", "password", "auth_url", "endpoint_type"},
"Huawei": {"access_key_id", "access_key_secret", "environment"},
"Aws": {"access_key_id", "access_key_secret", "environment"},
R(&options.SVMwareCloudAccountCreateOptions{}, "cloud-account-create-vmware", "Create a VMware cloud account", func(s *mcclient.ClientSession, args *options.SVMwareCloudAccountCreateOptions) error {
params := jsonutils.Marshal(args)
params.(*jsonutils.JSONDict).Add(jsonutils.NewString("VMware"), "provider")
result, err := modules.Cloudaccounts.Create(s, params)
if err != nil {
return err
}
printObject(result)
return nil
})
requireParams, ok := requireParamsMap[args.PROVIDER]
if !ok {
return fmt.Errorf("Unsupport provider %s", args.PROVIDER)
R(&options.SAliyunCloudAccountCreateOptions{}, "cloud-account-create-aliyun", "Create an Aliyun cloud account", func(s *mcclient.ClientSession, args *options.SAliyunCloudAccountCreateOptions) error {
params := jsonutils.Marshal(args)
params.(*jsonutils.JSONDict).Add(jsonutils.NewString("Aliyun"), "provider")
result, err := modules.Cloudaccounts.Create(s, params)
if err != nil {
return err
}
printObject(result)
return nil
})
for _, key := range requireParams {
v, _ := data.GetString(key)
if len(v) == 0 {
return fmt.Errorf("Missing %s", key)
}
params.Add(jsonutils.NewString(v), key)
R(&options.SAzureCloudAccountCreateOptions{}, "cloud-account-create-azure", "Create an Azure cloud account", func(s *mcclient.ClientSession, args *options.SAzureCloudAccountCreateOptions) error {
params := jsonutils.Marshal(args)
params.(*jsonutils.JSONDict).Add(jsonutils.NewString("Azure"), "provider")
result, err := modules.Cloudaccounts.Create(s, params)
if err != nil {
return err
}
printObject(result)
return nil
})
if args.Enabled {
params.Add(jsonutils.JSONTrue, "enabled")
R(&options.SQcloudCloudAccountCreateOptions{}, "cloud-account-create-qcloud", "Create a Qcloud cloud account", func(s *mcclient.ClientSession, args *options.SQcloudCloudAccountCreateOptions) error {
params := jsonutils.Marshal(args)
params.(*jsonutils.JSONDict).Add(jsonutils.NewString("Qcloud"), "provider")
result, err := modules.Cloudaccounts.Create(s, params)
if err != nil {
return err
}
printObject(result)
return nil
})
if args.Import {
params.Add(jsonutils.JSONTrue, "import")
if args.AutoSync {
params.Add(jsonutils.JSONTrue, "auto_sync")
}
if args.AutoCreateProject {
params.Add(jsonutils.JSONTrue, "auto_create_project")
}
R(&options.SAWSCloudAccountCreateOptions{}, "cloud-account-create-aws", "Create an AWS cloud account", func(s *mcclient.ClientSession, args *options.SAWSCloudAccountCreateOptions) error {
params := jsonutils.Marshal(args)
params.(*jsonutils.JSONDict).Add(jsonutils.NewString("Aws"), "provider")
result, err := modules.Cloudaccounts.Create(s, params)
if err != nil {
return err
}
printObject(result)
return nil
})
if len(args.Desc) > 0 {
params.Add(jsonutils.NewString(args.Desc), "description")
R(&options.SOpenStackCloudAccountCreateOptions{}, "cloud-account-create-openstack", "Create an OpenStack cloud account", func(s *mcclient.ClientSession, args *options.SOpenStackCloudAccountCreateOptions) error {
params := jsonutils.Marshal(args)
params.(*jsonutils.JSONDict).Add(jsonutils.NewString("OpenStack"), "provider")
result, err := modules.Cloudaccounts.Create(s, params)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&options.SHuaweiCloudAccountCreateOptions{}, "cloud-account-create-huawei", "Create a Huawei cloud account", func(s *mcclient.ClientSession, args *options.SHuaweiCloudAccountCreateOptions) error {
params := jsonutils.Marshal(args)
params.(*jsonutils.JSONDict).Add(jsonutils.NewString("Huawei"), "provider")
result, err := modules.Cloudaccounts.Create(s, params)
if err != nil {
return err
@@ -233,6 +257,70 @@ func init() {
ClientSecret string `help:"Azure clinet_secret"`
}
R(&CloudaccountUpdateCredentialOptions{}, "cloud-account-update-credential", "Update credential of a cloud account", func(s *mcclient.ClientSession, args *CloudaccountUpdateCredentialOptions) error {
return fmt.Errorf("obsolete command, please try cloud-account-update-credential-xxx, where xxx is vmware, aliyun, azure, qcloud, aws, openstack, huawei, etc.")
})
R(&options.SVMwareCloudAccountUpdateCredentialOptions{}, "cloud-account-update-credential-vmware", "Update credential of a VMware cloud account", func(s *mcclient.ClientSession, args *options.SVMwareCloudAccountUpdateCredentialOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "update-credential", params)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&options.SAliyunCloudAccountUpdateCredentialOptions{}, "cloud-account-update-credential-aliyun", "Update credential of an Aliyun cloud account", func(s *mcclient.ClientSession, args *options.SAliyunCloudAccountUpdateCredentialOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "update-credential", params)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&options.SAzureCloudAccountUpdateCredentialOptions{}, "cloud-account-update-credential-azure", "Update credential of an Azure cloud account", func(s *mcclient.ClientSession, args *options.SAzureCloudAccountUpdateCredentialOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "update-credential", params)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&options.SQcloudCloudAccountUpdateCredentialOptions{}, "cloud-account-update-credential-qcloud", "Update credential of a Qcloud cloud account", func(s *mcclient.ClientSession, args *options.SQcloudCloudAccountUpdateCredentialOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "update-credential", params)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&options.SAWSCloudAccountUpdateCredentialOptions{}, "cloud-account-update-credential-aws", "Update credential of an AWS cloud account", func(s *mcclient.ClientSession, args *options.SAWSCloudAccountUpdateCredentialOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "update-credential", params)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&options.SOpenStackCloudAccountUpdateCredentialOptions{}, "cloud-account-update-credential-openstack", "Update credential of an OpenStack cloud account", func(s *mcclient.ClientSession, args *options.SOpenStackCloudAccountUpdateCredentialOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "update-credential", params)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&options.SHuaweiCloudAccountUpdateCredentialOptions{}, "cloud-account-update-credential-huawei", "Update credential of an Huawei cloud account", func(s *mcclient.ClientSession, args *options.SHuaweiCloudAccountUpdateCredentialOptions) error {
params := jsonutils.Marshal(args)
result, err := modules.Cloudaccounts.PerformAction(s, args.ID, "update-credential", params)
if err != nil {
+13 -20
View File
@@ -132,6 +132,13 @@ func (self *SCloudaccount) ValidateDeleteCondition(ctx context.Context) error {
return self.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx)
}
func (self *SCloudaccount) PreDelete(ctx context.Context, userCred mcclient.TokenCredential) {
cloudproviders := self.GetCloudproviders()
for i := 0; i < len(cloudproviders); i++ {
cloudproviders[i].Delete(ctx, userCred)
}
}
func (self *SCloudaccount) PerformEnable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
_, err := self.SEnabledStatusStandaloneResourceBase.PerformEnable(ctx, userCred, query, data)
if err != nil {
@@ -226,16 +233,9 @@ func (manager *SCloudaccountManager) ValidateCreateData(ctx context.Context, use
return manager.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)
}
func (self *SCloudaccount) PreDelete(ctx context.Context, userCred mcclient.TokenCredential) {
cloudproviders := self.GetCloudproviders()
for i := 0; i < len(cloudproviders); i++ {
cloudproviders[i].Delete(ctx, userCred)
}
}
func (self *SCloudaccount) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
self.Enabled = true
self.EnableAutoSync = false
// self.EnableAutoSync = false
return self.SEnabledStatusStandaloneResourceBase.CustomizeCreate(ctx, userCred, ownerProjId, query, data)
}
@@ -243,7 +243,9 @@ func (self *SCloudaccount) PostCreate(ctx context.Context, userCred mcclient.Tok
self.SEnabledStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerProjId, query, data)
self.savePassword(self.Secret)
self.StartSyncCloudProviderInfoTask(ctx, userCred, nil, "")
if !self.EnableAutoSync {
self.StartSyncCloudProviderInfoTask(ctx, userCred, &SSyncRange{}, "")
}
}
func (self *SCloudaccount) savePassword(secret string) error {
@@ -1013,15 +1015,6 @@ func (manager *SCloudaccountManager) AutoSyncCloudaccountTask(ctx context.Contex
}
q := manager.Query()
/*
q = q.Filter(
sqlchemy.OR(
sqlchemy.NotEquals(q.Field("status"), CLOUD_PROVIDER_DISCONNECTED),
sqlchemy.LT(q.Field("error_count"), options.Options.MaxCloudAccountErrorCount),
),
)
*/
// q = q.Equals("sync_status", CLOUD_PROVIDER_SYNC_STATUS_IDLE)
accounts := make([]SCloudaccount, 0)
err := db.FetchModelObjects(manager, q, &accounts)
@@ -1051,7 +1044,7 @@ func (account *SCloudaccount) probeAccountStatus(ctx context.Context, userCred m
return nil, err
}
balance, err := manager.GetBalance()
if err != nil {
if err != nil && err != cloudprovider.ErrNotSupported {
log.Errorf("manager.GetBalance fail %s", err)
return nil, err
}
@@ -1129,7 +1122,7 @@ func (account *SCloudaccount) SubmitSyncAccountTask(ctx context.Context, userCre
if waitChan != nil {
waitChan <- err
} else {
if err == nil && autoSync && account.EnableAutoSync {
if err == nil && autoSync && account.Enabled && account.EnableAutoSync {
syncRange := SSyncRange{FullSync: true}
providers := account.GetEnabledCloudproviders()
for i := range providers {
+4 -1
View File
@@ -7,6 +7,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"database/sql"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
@@ -143,7 +144,9 @@ func (manager *SCloudproviderregionManager) FetchByIds(providerId string, region
}
err = q.First(obj)
if err != nil {
log.Errorf("q.First fail %s", err)
if err != sql.ErrNoRows {
log.Errorf("q.First fail %s", err)
}
return nil
}
return obj.(*SCloudproviderregion)
+3 -3
View File
@@ -519,7 +519,7 @@ func syncVMEip(ctx context.Context, userCred mcclient.TokenCredential, provider
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, userCred)
}
func syncRegionSkusFromCloud(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localZone *SZone, remoteRegion cloudprovider.ICloudRegion, remoteZone cloudprovider.ICloudZone) {
func syncZoneSkusFromCloud(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localZone *SZone, remoteRegion cloudprovider.ICloudRegion, remoteZone cloudprovider.ICloudZone) {
skus, err := remoteRegion.GetSkus(remoteZone.GetId())
if err != nil {
msg := fmt.Sprintf("GetSkus for zone %s failed %v", localZone.Name, err)
@@ -527,7 +527,7 @@ func syncRegionSkusFromCloud(ctx context.Context, userCred mcclient.TokenCredent
return
}
result := ServerSkuManager.SyncCloudSkusByRegion(ctx, userCred, provider, localZone, skus)
result := ServerSkuManager.SyncCloudSkusByZone(ctx, userCred, provider, localZone, skus)
syncResults.Add(ServerSkuManager, result)
@@ -763,7 +763,7 @@ func syncPublicCloudProviderInfo(
}
if driver.GetFactory().NeedSyncSkuFromCloud() {
syncRegionSkusFromCloud(ctx, userCred, syncResults, provider, &localZones[j], remoteRegion, remoteZones[j])
syncZoneSkusFromCloud(ctx, userCred, syncResults, provider, &localZones[j], remoteRegion, remoteZones[j])
}
}
+1 -1
View File
@@ -799,7 +799,7 @@ func (manager *SServerSkuManager) PendingDeleteInvalidSku() error {
return nil
}
func (manager *SServerSkuManager) SyncCloudSkusByRegion(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, zone *SZone, skus []cloudprovider.ICloudSku) compare.SyncResult {
func (manager *SServerSkuManager) SyncCloudSkusByZone(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, zone *SZone, skus []cloudprovider.ICloudSku) compare.SyncResult {
lockman.LockClass(ctx, manager, manager.GetOwnerId(userCred))
defer lockman.ReleaseClass(ctx, manager, manager.GetOwnerId(userCred))
+145
View File
@@ -0,0 +1,145 @@
package options
type SUserPasswordCredential struct {
Username string `help:"Username" positional:"true"`
Password string `help:"Password" positional:"true"`
}
type SVMwareCredentialWithEnvironment struct {
SUserPasswordCredential
Host string `help:"VMware VCenter/ESXi host" positional:"true"`
Port string `help:"VMware VCenter/ESXi host port" default:"443"`
}
type SAzureCredential struct {
ClientID string `help:"Azure client_id" positional:"true"`
ClientSecret string `help:"Azure clinet_secret" positional:"true"`
}
type SAzureCredentialWithEnvironment struct {
DirectoryID string `help:"Azure directory_id" positional:"true"`
SAzureCredential
Environment string `help:"Cloud environment" choices:"AzureGermanCloud|AzureChinaCloud|AzurePublicCloud" default:"AzureChinaCloud"`
}
type SQcloudCredential struct {
AppID string `help:"Qcloud appid" positional:"true"`
SecretID string `help:"Qcloud secret_id" positional:"true"`
SecretKey string `help:"Qcloud secret_key" positional:"true"`
}
type SOpenStackCredential struct {
ProjectName string `help:"OpenStack project_name" positional:"true"`
SUserPasswordCredential
EndpointType string `help:"OpenStack endpoint type" choices:"internal|public|admin"`
}
type SOpenStackCredentialWithAuthURL struct {
SOpenStackCredential
AuthURL string `help:"OpenStack auth_url" positional:"true" json:"auth_url"`
}
type SAccessKeyCredential struct {
AccessKeyID string `help:"Access_key_id" positional:"true"`
AccessKeySecret string `help:"Access_key_secret" positional:"true"`
}
type SAccessKeyCredentialWithEnvironment struct {
SAccessKeyCredential
Environment string `help:"Cloud environment" choices:"InternationalCloud|ChinaCloud" default:"ChinaCloud"`
}
/// create options
type SCloudAccountCreateBaseOptions struct {
Name string `help:"Name of cloud account" positional:"true"`
// PROVIDER string `help:"Driver for cloud account" choices:"VMware|Aliyun|Azure|Qcloud|OpenStack|Huawei|Aws"`
Desc string `help:"Description" token:"desc" json:"description"`
AutoCreateProject bool `help:"Enable the account with same name project"`
EnableAutoSync bool `help:"Enable automatically synchronize resources of this account"`
SyncIntervalSeconds int `help:"Interval to synchronize if auto sync is enable" metavar:"SECONDS"`
}
type SVMwareCloudAccountCreateOptions struct {
SCloudAccountCreateBaseOptions
SVMwareCredentialWithEnvironment
}
type SAliyunCloudAccountCreateOptions struct {
SCloudAccountCreateBaseOptions
SAccessKeyCredential
}
type SAzureCloudAccountCreateOptions struct {
SCloudAccountCreateBaseOptions
SAzureCredentialWithEnvironment
}
type SQcloudCloudAccountCreateOptions struct {
SCloudAccountCreateBaseOptions
SQcloudCredential
}
type SAWSCloudAccountCreateOptions struct {
SCloudAccountCreateBaseOptions
SAccessKeyCredentialWithEnvironment
}
type SOpenStackCloudAccountCreateOptions struct {
SCloudAccountCreateBaseOptions
SOpenStackCredentialWithAuthURL
}
type SHuaweiCloudAccountCreateOptions struct {
SCloudAccountCreateBaseOptions
SAccessKeyCredentialWithEnvironment
}
// update credential options
type SCloudAccountUpdateCredentialBaseOptions struct {
ID string `help:"ID or Name of cloud account" json:"-"`
}
type SVMwareCloudAccountUpdateCredentialOptions struct {
SCloudAccountUpdateCredentialBaseOptions
SUserPasswordCredential
}
type SAliyunCloudAccountUpdateCredentialOptions struct {
SCloudAccountUpdateCredentialBaseOptions
SAccessKeyCredential
}
type SAzureCloudAccountUpdateCredentialOptions struct {
SCloudAccountUpdateCredentialBaseOptions
SAzureCredential
}
type SQcloudCloudAccountUpdateCredentialOptions struct {
SCloudAccountUpdateCredentialBaseOptions
SQcloudCredential
}
type SAWSCloudAccountUpdateCredentialOptions struct {
SCloudAccountUpdateCredentialBaseOptions
SAccessKeyCredential
}
type SOpenStackCloudAccountUpdateCredentialOptions struct {
SCloudAccountUpdateCredentialBaseOptions
SOpenStackCredential
}
type SHuaweiCloudAccountUpdateCredentialOptions struct {
SCloudAccountUpdateCredentialBaseOptions
SAccessKeyCredential
}
+1 -1
View File
@@ -202,7 +202,7 @@ type SAccountBalance struct {
func (self *SAwsClient) QueryAccountBalance() (*SAccountBalance, error) {
// todo: aws 貌似没有余额?
panic("implement me")
return nil, cloudprovider.ErrNotSupported
}
func (self *SAwsClient) GetIProjects() ([]cloudprovider.ICloudProject, error) {
+1 -5
View File
@@ -122,11 +122,7 @@ func (self *SAwsProvider) GetIRegionById(id string) (cloudprovider.ICloudRegion,
}
func (self *SAwsProvider) GetBalance() (float64, error) {
balance, err := self.client.QueryAccountBalance()
if err != nil {
return 0.0, err
}
return balance.AvailableAmount, nil
return 0.0, cloudprovider.ErrNotSupported
}
func (self *SAwsProvider) GetIProjects() ([]cloudprovider.ICloudProject, error) {
+1 -1
View File
@@ -766,7 +766,7 @@ type SAccountBalance struct {
}
func (self *SAzureClient) QueryAccountBalance() (*SAccountBalance, error) {
return nil, cloudprovider.ErrNotImplemented
return nil, cloudprovider.ErrNotSupported
}
func getResourceGroup(id string) string {
+1 -5
View File
@@ -128,11 +128,7 @@ func (self *SAzureProvider) GetIRegionById(id string) (cloudprovider.ICloudRegio
}
func (self *SAzureProvider) GetBalance() (float64, error) {
balance, err := self.client.QueryAccountBalance()
if err != nil {
return 0.0, err
}
return balance.AvailableAmount, nil
return 0.0, cloudprovider.ErrNotSupported
}
func (self *SAzureProvider) GetIProjects() ([]cloudprovider.ICloudProject, error) {
+1 -1
View File
@@ -156,7 +156,7 @@ func (self *SESXiProvider) GetIRegionById(id string) (cloudprovider.ICloudRegion
}
func (self *SESXiProvider) GetBalance() (float64, error) {
return 0.0, nil
return 0.0, cloudprovider.ErrNotSupported
}
func (self *SESXiProvider) GetOnPremiseIRegion() (cloudprovider.ICloudRegion, error) {
+1 -4
View File
@@ -6,7 +6,6 @@ import (
"strconv"
"strings"
"yunion.io/x/log"
"yunion.io/x/pkg/util/netutils"
)
@@ -36,14 +35,12 @@ func ParseMac(macStr string) (SMacAddr, error) {
func (mac SMacAddr) Add(step int) SMacAddr {
mac2 := SMacAddr{}
leftOver := step
for i := 5; i >= 0; i -= 1 { // skip first 2 vendor bytes
for i := 5; i >= 0; i -= 1 {
newByte := int(mac[i]) + leftOver
res := 0
if newByte < 0 {
log.Debugf("%d %d", mac[i], newByte)
res = ((-newByte) / 0x100) + 1
newByte = newByte + res*0x100
log.Debugf("%d %d", newByte, res)
}
mac2[i] = byte(newByte % 0x100)
leftOver = newByte/0x100 - res
+1 -1
View File
@@ -169,7 +169,7 @@ func (self *SOpenStackProvider) GetIRegionById(extId string) (cloudprovider.IClo
}
func (self *SOpenStackProvider) GetBalance() (float64, error) {
return 0.0, nil
return 0.0, cloudprovider.ErrNotSupported
}
func (self *SOpenStackProvider) GetIProjects() ([]cloudprovider.ICloudProject, error) {