Merge pull request #5590 from ioito/feature/qx-public-cloud-quota

fix: 支持同步云平台配额信息
This commit is contained in:
Zexi Li
2020-03-30 20:02:54 +08:00
committed by GitHub
29 changed files with 1448 additions and 102 deletions
+60
View File
@@ -0,0 +1,60 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/jsonutils"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/mcclient/options"
)
func init() {
type CloudproviderQuotaListOptions struct {
options.BaseListOptions
Cloudregion string `help:"ID or Name of Cloudregion"`
QuotaType string `help:"Quota type"`
QuotaRange string `help:"Quota range" choices:"cloudregion|cloudprovider"`
}
R(&CloudproviderQuotaListOptions{}, "cloud-provider-quota-list", "List cloudprovider quota", func(s *mcclient.ClientSession, args *CloudproviderQuotaListOptions) error {
params, err := args.Params()
if err != nil {
return err
}
if len(args.QuotaType) > 0 {
params.Add(jsonutils.NewString(args.QuotaType), "quota_type")
}
if len(args.QuotaRange) > 0 {
params.Add(jsonutils.NewString(args.QuotaRange), "quota_range")
}
if len(args.Cloudregion) > 0 {
params.Add(jsonutils.NewString(args.Cloudregion), "cloudregion")
}
result, err := modules.CloudproviderQuotas.List(s, params)
if err != nil {
return err
}
printList(result, modules.CloudproviderQuotas.GetColumns(s))
return nil
})
}
+36
View File
@@ -0,0 +1,36 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package compute
import "yunion.io/x/onecloud/pkg/apis"
const (
CLOUD_PROVIDER_QUOTA_RANGE_CLOUDREGION = "cloudregion"
CLOUD_PROVIDER_QUOTA_RANGE_CLOUDPROVIDER = "cloudprovider"
)
type CloudproviderQuotaListInput struct {
apis.StandaloneResourceListInput
apis.ExternalizedResourceBaseListInput
ManagedResourceListInput
RegionalFilterListInput
// 配额类型
QuotaType string `json:"quota_type"`
// 配额范围
QuotaRange string `json:"quota_range"`
}
+5
View File
@@ -202,6 +202,7 @@ type ICloudProvider interface {
GetStorageClasses(regionId string) []string
GetCapabilities() []string
GetICloudQuotas() ([]ICloudQuota, error)
}
func IsSupportProject(prod ICloudProvider) bool {
@@ -301,6 +302,10 @@ func (self *SBaseProvider) GetOnPremiseIRegion() (ICloudRegion, error) {
return nil, ErrNotImplemented
}
func (self *SBaseProvider) GetICloudQuotas() ([]ICloudQuota, error) {
return nil, ErrNotImplemented
}
func (self *SBaseProvider) GetCloudRegionExternalIdPrefix() string {
return self.factory.GetId()
}
+10
View File
@@ -139,6 +139,8 @@ type ICloudRegion interface {
GetICloudEvents(start time.Time, end time.Time, withReadEvent bool) ([]ICloudEvent, error) //获取公有云操作日志接口
GetCapabilities() []string
GetICloudQuotas() ([]ICloudQuota, error)
}
type ICloudZone interface {
@@ -940,3 +942,11 @@ type ICloudEvent interface {
GetCreatedAt() time.Time
}
type ICloudQuota interface {
GetGlobalId() string
GetDesc() string
GetQuotaType() string
GetMaxQuotaCount() int
GetCurrentQuotaUsedCount() int
}
+252
View File
@@ -0,0 +1,252 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package models
import (
"context"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SCloudproviderQuotaManager struct {
db.SStandaloneResourceBaseManager
db.SExternalizedResourceBaseManager
SManagedResourceBaseManager
SCloudregionResourceBaseManager
}
var CloudproviderQuotaManager *SCloudproviderQuotaManager
func init() {
CloudproviderQuotaManager = &SCloudproviderQuotaManager{
SStandaloneResourceBaseManager: db.NewStandaloneResourceBaseManager(
SCloudproviderQuota{},
"cloudprovider_quotas_tbl",
"cloudproviderquota",
"cloudproviderquotas",
),
}
CloudproviderQuotaManager.SetVirtualObject(CloudproviderQuotaManager)
}
type SCloudproviderQuota struct {
db.SStandaloneResourceBase
db.SExternalizedResourceBase
SManagedResourceBase
SCloudregionResourceBase
// 配额范围
// cloudregion: 区域级别
// cloudprovider: 云订阅级别
QuotaRange string `width:"32" charset:"ascii" list:"user"`
// 已使用的配额
// -1代表未从云平台拿到已使用配额信息
UsedCount int `nullable:"false" default:"0" list:"user"`
// 最大配额限制
MaxCount int `nullable:"false" default:"0" list:"user"`
// 配额类型
QuotaType string `width:"32" charset:"ascii" list:"user"`
}
func (manager *SCloudproviderQuotaManager) GetContextManagers() [][]db.IModelManager {
return [][]db.IModelManager{
{CloudproviderManager},
}
}
func (man *SCloudproviderQuotaManager) ListItemFilter(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.CloudproviderQuotaListInput,
) (*sqlchemy.SQuery, error) {
var err error
q, err = man.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StandaloneResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SStandaloneResourceBaseManager.ListItemFilter")
}
q, err = man.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
if err != nil {
return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
}
q, err = man.SManagedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ManagedResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemFilter")
}
q, err = man.SCloudregionResourceBaseManager.ListItemFilter(ctx, q, userCred, query.RegionalFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemFilter")
}
if len(query.QuotaType) > 0 {
q = q.Equals("quota_type", query.QuotaType)
}
if len(query.QuotaRange) > 0 {
q = q.Equals("quota_range", query.QuotaRange)
}
return q, nil
}
func (man *SCloudproviderQuotaManager) OrderByExtraFields(
ctx context.Context,
q *sqlchemy.SQuery,
userCred mcclient.TokenCredential,
query api.CloudproviderQuotaListInput,
) (*sqlchemy.SQuery, error) {
q, err := man.SStandaloneResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StandaloneResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SStandaloneResourceBaseManager.OrderByExtraFields")
}
q, err = man.SCloudregionResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.RegionalFilterListInput)
if err != nil {
return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.OrderByExtraFields")
}
q, err = man.SManagedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ManagedResourceListInput)
if err != nil {
return nil, errors.Wrap(err, "SManagedResourceBaseManager.OrderByExtraFields")
}
return q, nil
}
func (man *SCloudproviderQuotaManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
q, err := man.SStandaloneResourceBaseManager.QueryDistinctExtraField(q, field)
if err == nil {
return q, nil
}
q, err = man.SCloudregionResourceBaseManager.QueryDistinctExtraField(q, field)
if err == nil {
return q, nil
}
q, err = man.SManagedResourceBaseManager.QueryDistinctExtraField(q, field)
if err == nil {
return q, nil
}
return q, httperrors.ErrNotFound
}
func (manager *SCloudproviderQuotaManager) GetQuotas(provider *SCloudprovider, region *SCloudregion, quotaRange string) ([]SCloudproviderQuota, error) {
q := manager.Query()
if provider != nil {
q = q.Equals("manager_id", provider.Id)
}
if region != nil {
q = q.Equals("cloudregion_id", region.Id)
}
if len(quotaRange) > 0 {
q = q.Equals("quota_range", quotaRange)
}
quotas := []SCloudproviderQuota{}
err := db.FetchModelObjects(manager, q, &quotas)
if err != nil {
return nil, errors.Wrap(err, "db.FetchModelObjects")
}
return quotas, nil
}
func (manager *SCloudproviderQuotaManager) SyncQuotas(ctx context.Context, userCred mcclient.TokenCredential, syncOwnerId mcclient.IIdentityProvider, provider *SCloudprovider, region *SCloudregion, quotaRange string, iQuotas []cloudprovider.ICloudQuota) compare.SyncResult {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, provider.GetOwnerId()))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, provider.GetOwnerId()))
result := compare.SyncResult{}
dbQuotas, err := manager.GetQuotas(provider, region, quotaRange)
if err != nil {
result.Error(err)
return result
}
removed := make([]SCloudproviderQuota, 0)
commondb := make([]SCloudproviderQuota, 0)
commonext := make([]cloudprovider.ICloudQuota, 0)
added := make([]cloudprovider.ICloudQuota, 0)
err = compare.CompareSets(dbQuotas, iQuotas, &removed, &commondb, &commonext, &added)
if err != nil {
result.Error(err)
return result
}
for i := 0; i < len(removed); i++ {
err := removed[i].Delete(ctx, userCred)
if err != nil {
result.DeleteError(err)
} else {
result.Delete()
}
}
for i := 0; i < len(commondb); i++ {
err := commondb[i].SyncWithCloudQuota(ctx, userCred, commonext[i])
if err != nil {
result.UpdateError(err)
continue
}
result.Update()
}
for i := 0; i < len(added); i++ {
err = manager.newFromCloudQuota(ctx, userCred, provider, region, quotaRange, added[i])
if err != nil {
result.AddError(err)
continue
}
result.Add()
}
return result
}
func (self *SCloudproviderQuota) SyncWithCloudQuota(ctx context.Context, userCred mcclient.TokenCredential, iQuota cloudprovider.ICloudQuota) error {
_, err := db.UpdateWithLock(ctx, self, func() error {
self.UsedCount = iQuota.GetCurrentQuotaUsedCount()
self.MaxCount = iQuota.GetMaxQuotaCount()
return nil
})
return err
}
func (manager *SCloudproviderQuotaManager) newFromCloudQuota(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, quotaRange string, iQuota cloudprovider.ICloudQuota) error {
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, userCred))
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, userCred))
quota := SCloudproviderQuota{}
quota.SetModelManager(manager, &quota)
quota.Name = iQuota.GetQuotaType()
quota.Description = iQuota.GetDesc()
quota.ExternalId = iQuota.GetGlobalId()
quota.ManagerId = provider.Id
quota.QuotaType = iQuota.GetQuotaType()
quota.QuotaRange = quotaRange
quota.UsedCount = iQuota.GetCurrentQuotaUsedCount()
quota.MaxCount = iQuota.GetMaxQuotaCount()
if region != nil {
quota.CloudregionId = region.Id
}
return manager.TableSpec().Insert(&quota)
}
+1
View File
@@ -1287,6 +1287,7 @@ func (self *SCloudprovider) RealDelete(ctx context.Context, userCred mcclient.To
CloudproviderRegionManager,
ExternalProjectManager,
CloudregionManager,
CloudproviderQuotaManager,
} {
err = manager.purgeAll(ctx, userCred, self.Id)
if err != nil {
+20
View File
@@ -87,6 +87,24 @@ func isInCache(pairs []sStoragecacheSyncPair, localCacheId string) bool {
return false
}
func syncRegionQuotas(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, driver cloudprovider.ICloudProvider, provider *SCloudprovider, localRegion *SCloudregion, remoteRegion cloudprovider.ICloudRegion) error {
quotas, err := remoteRegion.GetICloudQuotas()
if err != nil {
msg := fmt.Sprintf("GetICloudQuotas for region %s failed %s", remoteRegion.GetName(), err)
log.Errorf(msg)
return err
}
result := CloudproviderQuotaManager.SyncQuotas(ctx, userCred, provider.GetOwnerId(), provider, localRegion, api.CLOUD_PROVIDER_QUOTA_RANGE_CLOUDREGION, quotas)
syncResults.Add(CloudproviderQuotaManager, result)
msg := result.Result()
notes := fmt.Sprintf("SyncQuotas for region %s result: %s", localRegion.Name, msg)
log.Infof(notes)
if result.IsError() {
return fmt.Errorf(msg)
}
return nil
}
func syncRegionZones(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet, provider *SCloudprovider, localRegion *SCloudregion, remoteRegion cloudprovider.ICloudRegion) ([]SZone, []cloudprovider.ICloudZone, error) {
zones, err := remoteRegion.GetIZones()
if err != nil {
@@ -1013,6 +1031,8 @@ func syncPublicCloudProviderInfo(
syncProjects(ctx, userCred, syncResults, driver, provider)
}
syncRegionQuotas(ctx, userCred, syncResults, driver, provider, localRegion, remoteRegion)
localZones, remoteZones, _ := syncRegionZones(ctx, userCred, syncResults, provider, localRegion, remoteRegion)
if !driver.GetFactory().NeedSyncSkuFromCloud() {
+27
View File
@@ -1630,3 +1630,30 @@ func (manager *SSecurityGroupCacheManager) purgeAll(ctx context.Context, userCre
}
return nil
}
func (quota *SCloudproviderQuota) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
lockman.LockObject(ctx, quota)
defer lockman.ReleaseObject(ctx, quota)
err := quota.ValidateDeleteCondition(ctx)
if err != nil {
return err
}
return quota.Delete(ctx, userCred)
}
func (manager *SCloudproviderQuotaManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error {
quotas := []SCloudproviderQuota{}
err := fetchByManagerId(manager, providerId, &quotas)
if err != nil {
return err
}
for i := range quotas {
err := quotas[i].purge(ctx, userCred)
if err != nil {
return err
}
}
return nil
}
+1
View File
@@ -161,6 +161,7 @@ func InitHandlers(app *appsrv.Application) {
models.GuestTemplateManager,
models.ServiceCatalogManager,
models.CloudproviderQuotaManager,
} {
db.RegisterModelManager(manager)
handler := db.NewModelHandler(manager)
@@ -16,12 +16,17 @@ package tasks
import (
"context"
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/appsrv"
"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/compute/models"
"yunion.io/x/onecloud/pkg/util/logclient"
)
@@ -59,18 +64,47 @@ func taskFail(ctx context.Context, task *CloudProviderSyncInfoTask, provider *mo
task.SetStageFailed(ctx, reason)
}
func (self *CloudProviderSyncInfoTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
provider := obj.(*models.SCloudprovider)
db.OpsLog.LogEvent(provider, db.ACT_SYNCING_HOST, "", self.UserCred)
func (self *CloudProviderSyncInfoTask) GetSyncRange() models.SSyncRange {
syncRange := models.SSyncRange{}
syncRangeJson, _ := self.Params.Get("sync_range")
if syncRangeJson != nil {
syncRangeJson.Unmarshal(&syncRange)
}
syncRange.Normalize()
return syncRange
}
func (self *CloudProviderSyncInfoTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
provider := obj.(*models.SCloudprovider)
self.SetStage("OnSyncCloudProviderQuotaInfoComplete", nil)
taskman.LocalTaskRun(self, func() (jsonutils.JSONObject, error) {
p, err := provider.GetProvider()
if err != nil {
return nil, errors.Wrap(err, "GetProvider")
}
quotas, err := p.GetICloudQuotas()
if err != nil {
if errors.Cause(err) != cloudprovider.ErrNotImplemented {
return nil, errors.Wrap(err, "GetICloudQuotas")
}
return nil, nil
}
result := models.CloudproviderQuotaManager.SyncQuotas(ctx, self.GetUserCred(), provider.GetOwnerId(), provider, nil, api.CLOUD_PROVIDER_QUOTA_RANGE_CLOUDPROVIDER, quotas)
msg := result.Result()
notes := fmt.Sprintf("SyncQuotas for provider %s result: %s", provider.Name, msg)
log.Infof(notes)
return nil, nil
})
}
func (self *CloudProviderSyncInfoTask) OnSyncCloudProviderQuotaInfoComplete(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
provider := obj.(*models.SCloudprovider)
syncRange := self.GetSyncRange()
db.OpsLog.LogEvent(provider, db.ACT_SYNCING_HOST, "", self.UserCred)
self.SetStage("OnSyncCloudProviderInfoComplete", nil)
taskman.LocalTaskRun(self, func() (jsonutils.JSONObject, error) {
@@ -79,6 +113,11 @@ func (self *CloudProviderSyncInfoTask) OnInit(ctx context.Context, obj db.IStand
})
}
func (self *CloudProviderSyncInfoTask) OnSyncCloudProviderQuotaInfoCompleteFailed(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
log.Errorf("faild to sync provider quotas %s", body.String())
self.OnSyncCloudProviderQuotaInfoComplete(ctx, obj, body)
}
func (self *CloudProviderSyncInfoTask) OnSyncCloudProviderInfoComplete(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
provider := obj.(*models.SCloudprovider)
// provider.MarkEndSync(self.UserCred)
@@ -87,86 +126,3 @@ func (self *CloudProviderSyncInfoTask) OnSyncCloudProviderInfoComplete(ctx conte
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, "", self.UserCred)
logclient.AddActionLogWithStartable(self, provider, getAction(self.Params), body, self.UserCred, true)
}
/*func logSyncFailed(provider *models.SCloudprovider, task taskman.ITask, reason string) {
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, reason, task.GetUserCred())
logclient.AddActionLogWithStartable(task, provider, getAction(task.GetParams()), reason, task.GetUserCred(), false)
}
func syncCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, driver cloudprovider.ICloudProvider, syncRange *models.SSyncRange) {
notes := fmt.Sprintf("Start sync host info ...")
log.Infof(notes)
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_START, "", task.UserCred)
if driver.GetFactory().IsOnPremise() {
syncOnPremiseCloudProviderInfo(ctx, provider, task, driver, syncRange)
} else {
syncOutOfPremiseCloudProviderInfo(ctx, provider, task, driver, syncRange)
}
}
func syncOnPremiseCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, driver cloudprovider.ICloudProvider, syncRange *models.SSyncRange) {
cpr := models.CloudproviderRegionManager.FetchByIdsOrCreate(provider.Id, models.DEFAULT_REGION_ID)
cpr.DoSync(ctx, task.UserCred, syncRange)
}
func syncOutOfPremiseCloudProviderInfo(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, driver cloudprovider.ICloudProvider, syncRange *models.SSyncRange) {
regions := driver.GetIRegions()
externalIdPrefix := driver.GetCloudRegionExternalIdPrefix()
localRegions, _, cloudProviderRegions, result := models.CloudregionManager.SyncRegions(ctx, task.UserCred, provider, externalIdPrefix, regions)
msg := result.Result()
log.Infof("SyncRegion result: %s", msg)
if result.IsError() {
logSyncFailed(provider, task, msg)
return
}
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.UserCred)
// logclient.AddActionLog(provider, getAction(task.Params), "", task.UserCred, true)
for i := 0; i < len(localRegions); i += 1 {
if len(syncRange.Region) > 0 && !utils.IsInStringArray(localRegions[i].Id, syncRange.Region) {
continue
}
cloudProviderRegions[i].DoSync(ctx, task.UserCred, syncRange)
}
}
func syncVMDisks(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, driver cloudprovider.ICloudProvider, 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)
log.Errorf(msg)
logSyncFailed(provider, task, msg)
return
}
result := localVM.SyncVMDisks(ctx, task.UserCred, driver, host, disks, provider.ProjectId, syncRange.ProjectSync)
msg := result.Result()
notes := fmt.Sprintf("syncVMDisks for VM %s result: %s", localVM.Name, msg)
log.Infof(notes)
if result.IsError() {
logSyncFailed(provider, task, msg)
return
}
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.UserCred)
// logclient.AddActionLog(provider, getAction(task.Params), notes, task.UserCred, true)
}
func syncVMEip(ctx context.Context, provider *models.SCloudprovider, task *CloudProviderSyncInfoTask, localVM *models.SGuest, remoteVM cloudprovider.ICloudVM) {
eip, err := remoteVM.GetIEIP()
if err != nil {
msg := fmt.Sprintf("GetIEIP for VM %s failed %s", remoteVM.GetName(), err)
log.Errorf(msg)
logSyncFailed(provider, task, msg)
return
}
result := localVM.SyncVMEip(ctx, task.UserCred, provider, eip, provider.ProjectId)
msg := result.Result()
log.Infof("syncVMEip for VM %s result: %s", localVM.Name, msg)
if result.IsError() {
logSyncFailed(provider, task, msg)
return
}
db.OpsLog.LogEvent(provider, db.ACT_SYNC_HOST_COMPLETE, msg, task.UserCred)
}*/
@@ -0,0 +1,33 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package modules
import "yunion.io/x/onecloud/pkg/mcclient/modulebase"
type CloudproviderQuotasManager struct {
modulebase.ResourceManager
}
var (
CloudproviderQuotas CloudproviderQuotasManager
)
func init() {
CloudproviderQuotas = CloudproviderQuotasManager{NewComputeManager("cloudproviderquota", "cloudproviderquotas",
[]string{"Id", "Name", "Quota_Range", "Quota_Type", "Max_Count", "Used_Count"},
[]string{})}
registerCompute(&CloudproviderQuotas)
}
+136
View File
@@ -0,0 +1,136 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package aliyun
import (
"fmt"
"strconv"
"strings"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type ValueItem struct {
Value string
DiskCategory string
}
type AttributeValues struct {
ValueItem []ValueItem
}
type SAccountAttributeItem struct {
AttributeValues AttributeValues
AttributeName string
}
type SQuota struct {
Name string
UsedCount int
MaxCount int
}
func (q *SQuota) GetGlobalId() string {
return q.Name
}
func (q *SQuota) GetDesc() string {
return q.Name
}
func (q *SQuota) GetQuotaType() string {
return q.Name
}
func (q *SQuota) GetMaxQuotaCount() int {
return q.MaxCount
}
func (q *SQuota) GetCurrentQuotaUsedCount() int {
return q.UsedCount
}
func (region *SRegion) GetAccountAttributes() ([]SAccountAttributeItem, error) {
params := map[string]string{
"RegionId": region.RegionId,
}
resp, err := region.ecsRequest("DescribeAccountAttributes", params)
if err != nil {
return nil, errors.Wrap(err, "ecsRequest")
}
quotas := []SAccountAttributeItem{}
err = resp.Unmarshal(&quotas, "AccountAttributeItems", "AccountAttributeItem")
if err != nil {
return nil, errors.Wrap(err, "resp.Unmarshal")
}
return quotas, nil
}
func (region *SRegion) GetQuotas() ([]SQuota, error) {
attrs, err := region.GetAccountAttributes()
if err != nil {
return nil, errors.Wrap(err, "GetAccountAttributes")
}
quotas := map[string]SQuota{}
for _, attr := range attrs {
for _, item := range attr.AttributeValues.ValueItem {
value, err := strconv.ParseInt(item.Value, 10, 64)
if err != nil {
continue
}
used := false
name := attr.AttributeName
if strings.HasPrefix(name, "used-") {
used = true
name = strings.TrimPrefix(name, "used-")
}
if len(item.DiskCategory) > 0 {
name = fmt.Sprintf("%s/%s", name, item.DiskCategory)
}
if _, ok := quotas[name]; !ok {
quotas[name] = SQuota{
Name: name,
UsedCount: -1,
}
}
quota := quotas[name]
if used {
quota.UsedCount = int(value)
} else {
quota.MaxCount = int(value)
}
quotas[name] = quota
}
}
ret := []SQuota{}
for _, quota := range quotas {
ret = append(ret, quota)
}
return ret, nil
}
func (region *SRegion) GetICloudQuotas() ([]cloudprovider.ICloudQuota, error) {
quotas, err := region.GetQuotas()
if err != nil {
return nil, errors.Wrap(err, "GetQuotas")
}
ret := []cloudprovider.ICloudQuota{}
for i := range quotas {
ret = append(ret, &quotas[i])
}
return ret, nil
}
+33
View File
@@ -0,0 +1,33 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/aliyun"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type QuotaListOptions struct {
}
shellutils.R(&QuotaListOptions{}, "quota-list", "List quota", func(cli *aliyun.SRegion, args *QuotaListOptions) error {
quotas, err := cli.GetQuotas()
if err != nil {
return err
}
printList(quotas, 0, 0, 0, nil)
return nil
})
}
+1 -1
View File
@@ -21,7 +21,7 @@ import (
func init() {
type RouteTableListOptions struct {
VpcId string `vpc id`
VpcId string `help:"vpc id"`
}
shellutils.R(&RouteTableListOptions{}, "routetable-list", "List route tables", func(cli *aws.SRegion, args *RouteTableListOptions) error {
routetables, err := cli.GetRouteTables(args.VpcId, false)
+35
View File
@@ -0,0 +1,35 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/azure"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type UsageListOptions struct {
TYPE string `choices:"Microsoft.Network|Microsoft.Compute|Microsoft.Storage"`
}
shellutils.R(&UsageListOptions{}, "usage-list", "List usage", func(cli *azure.SRegion, args *UsageListOptions) error {
usage, err := cli.GetUsage(args.TYPE)
if err != nil {
return err
}
printList(usage, 0, 0, 0, []string{})
return nil
})
}
+81
View File
@@ -0,0 +1,81 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package azure
import (
"fmt"
"strings"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type UsageName struct {
Value string
LocalizedValue string
}
// {"value":[{"unit":"Count","currentValue":0,"limit":250,"name":{"value":"StorageAccounts","localizedValue":"Storage Accounts"}}]}
type SUsage struct {
Unit string
CurrentValue int
Limit int
Name UsageName
}
func (u *SUsage) GetGlobalId() string {
return strings.ToLower(u.Name.Value)
}
func (u *SUsage) GetQuotaType() string {
return u.Name.Value
}
func (u *SUsage) GetDesc() string {
return u.Name.LocalizedValue
}
func (u *SUsage) GetMaxQuotaCount() int {
return u.Limit
}
func (u *SUsage) GetCurrentQuotaUsedCount() int {
return u.CurrentValue
}
func (region *SRegion) GetUsage(resourceType string) ([]SUsage, error) {
usage := []SUsage{}
resource := fmt.Sprintf("%s/locations/%s/usages", resourceType, region.Name)
err := region.client.ListAll(resource, &usage)
if err != nil {
return nil, errors.Wrapf(err, "ListAll(%s)", resource)
}
return usage, nil
}
func (region *SRegion) GetICloudQuotas() ([]cloudprovider.ICloudQuota, error) {
ret := []cloudprovider.ICloudQuota{}
for _, resourceType := range []string{"Microsoft.Network", "Microsoft.Storage", "Microsoft.Compute", "Microsoft.Storage"} {
usages, err := region.GetUsage(resourceType)
if err != nil {
return nil, errors.Wrap(err, "GetUsage")
}
for i := range usages {
ret = append(ret, &usages[i])
}
}
return ret, nil
}
+60
View File
@@ -0,0 +1,60 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google
import (
"strings"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SQuota struct {
Metric string
Limit int
Usage int
Owner string
}
func (q *SQuota) GetGlobalId() string {
return strings.ToLower(q.Metric)
}
func (q *SQuota) GetName() string {
return q.Metric
}
func (q *SQuota) GetDesc() string {
return q.Metric
}
func (q *SQuota) GetQuotaType() string {
return q.Metric
}
func (q *SQuota) GetMaxQuotaCount() int {
return q.Limit
}
func (q *SQuota) GetCurrentQuotaUsedCount() int {
return q.Usage
}
func (region *SRegion) GetICloudQuotas() ([]cloudprovider.ICloudQuota, error) {
ret := []cloudprovider.ICloudQuota{}
for i := range region.Quotas {
ret = append(ret, &region.Quotas[i])
}
return ret, nil
}
+1
View File
@@ -35,6 +35,7 @@ type SRegion struct {
client *SGoogleClient
capabilities []string
Quotas []SQuota
Description string
ID string
+2
View File
@@ -81,6 +81,7 @@ type Client struct {
DBInstanceJob *modules.SDBInstanceJobManager
Traces *modules.STraceManager
CloudEye *modules.SCloudEyeManager
Quotas *modules.SQuotaManager
}
func (self *Client) SetHttpClient(httpClient *http.Client) {
@@ -210,6 +211,7 @@ func (self *Client) initManagers() {
self.DBInstanceJob = modules.NewDBInstanceJobManager(self.regionId, self.projectId, self.signer, self.debug)
self.Traces = modules.NewTraceManager(self.regionId, self.projectId, self.signer, self.debug)
self.CloudEye = modules.NewCloudEyeManager(self.regionId, self.projectId, self.signer, self.debug)
self.Quotas = modules.NewQuotaManager(self.regionId, self.projectId, self.signer, self.debug)
}
self.init = true
@@ -0,0 +1,37 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package modules
import (
"yunion.io/x/onecloud/pkg/multicloud/huawei/client/auth"
)
type SQuotaManager struct {
SResourceManager
}
func NewQuotaManager(regionId string, projectId string, signer auth.Signer, debug bool) *SQuotaManager {
return &SQuotaManager{SResourceManager: SResourceManager{
SBaseManager: NewBaseManager(signer, debug),
ServiceName: ServiceNameEVS,
Region: regionId,
ProjectId: projectId,
version: "v1",
Keyword: "quotas",
KeywordPlural: "quotas",
ResourceKeyword: "quotas",
}}
}
+80
View File
@@ -0,0 +1,80 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package huawei
import (
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SQuota struct {
Min int
Quota int
Type string
Used int
}
func (q *SQuota) GetGlobalId() string {
return q.Type
}
func (q *SQuota) GetQuotaType() string {
return q.Type
}
func (q *SQuota) GetName() string {
return q.Type
}
func (q *SQuota) GetDesc() string {
return ""
}
func (q *SQuota) GetMaxQuotaCount() int {
return q.Quota
}
func (q *SQuota) GetCurrentQuotaUsedCount() int {
return q.Used
}
func (self *SRegion) GetQuotas() ([]SQuota, error) {
quotas := []SQuota{}
params := map[string]string{}
result, err := self.ecsClient.Quotas.Get("", params)
if err != nil {
return nil, errors.Wrap(err, "Quotas.List")
}
err = result.Unmarshal(&quotas, "resources")
if err != nil {
return nil, errors.Wrap(err, "result.Unmarshal")
}
return quotas, nil
}
func (region *SRegion) GetICloudQuotas() ([]cloudprovider.ICloudQuota, error) {
quotas, err := region.GetQuotas()
if err != nil {
return nil, errors.Wrap(err, "GetQuotas")
}
ret := []cloudprovider.ICloudQuota{}
for i := range quotas {
ret = append(ret, &quotas[i])
}
return ret, nil
}
+34
View File
@@ -0,0 +1,34 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/huawei"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type QuotaListOptions struct {
}
shellutils.R(&QuotaListOptions{}, "quota-list", "List Quotas", func(cli *huawei.SRegion, args *QuotaListOptions) error {
quotas, err := cli.GetQuotas()
if err != nil {
return err
}
printList(quotas, 0, 0, 0, nil)
return nil
})
}
+106 -13
View File
@@ -15,28 +15,66 @@
package openstack
import (
"yunion.io/x/jsonutils"
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/util/version"
)
type SQuota struct {
FixedIps int
Floatingips int
Networks int
Port int
RbacPolicy int
Router int
SecurityGroups int
SecurityGroupRules int
type QuotaDetail struct {
Reserved int
Limit int
InUse int
}
func (region *SRegion) GetQuota() (*SQuota, error) {
_, resp, err := region.Get("compute", "/os-quota-sets/"+region.client.tokenCredential.GetTenantId(), "", nil)
type QuotaSet struct {
InjectedFileContentBytes QuotaDetail
MetadataItems QuotaDetail
ServerGroupMembers QuotaDetail
ServerGroups QuotaDetail
Ram QuotaDetail
FloatingIps QuotaDetail
KeyPairs QuotaDetail
Id string
Instances QuotaDetail
SecurityGroupRules QuotaDetail
InjectedFiles QuotaDetail
Cores QuotaDetail
FixedIps QuotaDetail
InjectedFilePathBytes QuotaDetail
SecurityGroups QuotaDetail
}
type SQuota struct {
Cores int
Instances int
KeyPairs int
FixedIps int
MetadataItems int
Ram int
ServerGroups int
ServerGroupMembers int
InjectedFileContentBytes int
InjectedFilePathBytes int
InjectedFiles int
Floatingips int
Networks int
Port int
RbacPolicy int
Router int
SecurityGroups int
SecurityGroupRules int
}
func (region *SRegion) GetQuota() (*QuotaSet, error) {
_, resp, err := region.Get("compute", fmt.Sprintf("/os-quota-sets/%s/detail", region.client.tokenCredential.GetTenantId()), "", nil)
if err != nil {
return nil, err
}
quota := &SQuota{}
quota := &QuotaSet{}
return quota, resp.Unmarshal(quota, "quota_set")
}
@@ -74,3 +112,58 @@ func (region *SRegion) SetQuota(quota *SQuota) error {
_, _, err := region.Update("compute", "/os-quota-sets/"+region.client.tokenCredential.GetTenantId(), maxVersion, jsonutils.Marshal(params))
return err
}
type IQuota struct {
Name string
Limit int
InUse int
}
func (iq *IQuota) GetGlobalId() string {
return iq.Name
}
func (iq *IQuota) GetName() string {
return iq.Name
}
func (iq *IQuota) GetDesc() string {
return ""
}
func (iq *IQuota) GetQuotaType() string {
return iq.Name
}
func (iq *IQuota) GetMaxQuotaCount() int {
return iq.Limit
}
func (iq *IQuota) GetCurrentQuotaUsedCount() int {
return iq.InUse
}
func (region *SRegion) GetICloudQuotas() ([]cloudprovider.ICloudQuota, error) {
quota, err := region.GetQuota()
if err != nil {
return nil, errors.Wrap(err, "GetQuota")
}
ret := []cloudprovider.ICloudQuota{}
ret = append(ret, &IQuota{Name: "injected_file_content_bytes", Limit: quota.InjectedFileContentBytes.Limit, InUse: quota.InjectedFileContentBytes.InUse})
ret = append(ret, &IQuota{Name: "metadata_items", Limit: quota.MetadataItems.Limit, InUse: quota.MetadataItems.InUse})
ret = append(ret, &IQuota{Name: "server_group_members", Limit: quota.ServerGroupMembers.Limit, InUse: quota.ServerGroupMembers.InUse})
ret = append(ret, &IQuota{Name: "server_groups", Limit: quota.ServerGroups.Limit, InUse: quota.ServerGroups.InUse})
ret = append(ret, &IQuota{Name: "ram", Limit: quota.Ram.Limit, InUse: quota.Ram.InUse})
ret = append(ret, &IQuota{Name: "floating_ips", Limit: quota.FloatingIps.Limit, InUse: quota.FloatingIps.InUse})
ret = append(ret, &IQuota{Name: "key_pairs", Limit: quota.KeyPairs.Limit, InUse: quota.KeyPairs.InUse})
ret = append(ret, &IQuota{Name: "instances", Limit: quota.Instances.Limit, InUse: quota.Instances.InUse})
ret = append(ret, &IQuota{Name: "security_group_rules", Limit: quota.SecurityGroupRules.Limit, InUse: quota.SecurityGroupRules.InUse})
ret = append(ret, &IQuota{Name: "injected_files", Limit: quota.InjectedFiles.Limit, InUse: quota.InjectedFiles.InUse})
ret = append(ret, &IQuota{Name: "cores", Limit: quota.Cores.Limit, InUse: quota.Cores.InUse})
ret = append(ret, &IQuota{Name: "fixed_ips", Limit: quota.FixedIps.Limit, InUse: quota.FixedIps.InUse})
ret = append(ret, &IQuota{Name: "injected_file_path_bytes", Limit: quota.InjectedFilePathBytes.Limit, InUse: quota.InjectedFilePathBytes.InUse})
ret = append(ret, &IQuota{Name: "security_groups", Limit: quota.SecurityGroups.Limit, InUse: quota.SecurityGroups.InUse})
return ret, nil
}
+131
View File
@@ -0,0 +1,131 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package qcloud
import (
"strings"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type ImageQuota struct {
region *SRegion
ImageNumQuota int
}
func (iq *ImageQuota) GetGlobalId() string {
return "ImageNumQuota"
}
func (iq *ImageQuota) GetName() string {
return "ImageNumQuota"
}
func (iq *ImageQuota) GetDesc() string {
return ""
}
func (iq *ImageQuota) GetQuotaType() string {
return "ImageNumQuota"
}
func (iq *ImageQuota) GetMaxQuotaCount() int {
return iq.ImageNumQuota
}
func (iq *ImageQuota) GetCurrentQuotaUsedCount() int {
_, count, err := iq.region.GetImages("", "PRIVATE_IMAGE", nil, "", 0, iq.ImageNumQuota)
if err != nil {
log.Errorf("get private image error: %v", err)
return -1
}
return count
}
func (region *SRegion) GetImageQuota() (*ImageQuota, error) {
params := map[string]string{}
resp, err := region.cvmRequest("DescribeImageQuota", params, true)
if err != nil {
return nil, errors.Wrap(err, "DescribeImageQuota")
}
imageQuota := &ImageQuota{region: region}
return imageQuota, resp.Unmarshal(imageQuota)
}
type QuotaSet struct {
QuotaId string
QuotaCurrent int
QuotaLimit int
}
func (qs *QuotaSet) GetGlobalId() string {
return strings.ToLower(qs.QuotaId)
}
func (qs *QuotaSet) GetName() string {
return qs.QuotaId
}
func (qs *QuotaSet) GetDesc() string {
return ""
}
func (qs *QuotaSet) GetQuotaType() string {
return qs.QuotaId
}
func (qs *QuotaSet) GetMaxQuotaCount() int {
return qs.QuotaLimit
}
func (qs *QuotaSet) GetCurrentQuotaUsedCount() int {
return qs.QuotaCurrent
}
func (region *SRegion) GetQuota(action string) ([]QuotaSet, error) {
params := map[string]string{}
resp, err := region.vpcRequest("DescribeAddressQuota", params)
if err != nil {
return nil, errors.Wrap(err, "DescribeAddressQuota")
}
quotas := []QuotaSet{}
err = resp.Unmarshal(&quotas, "QuotaSet")
if err != nil {
return nil, errors.Wrap(err, "resp.Unmarshal")
}
return quotas, nil
}
func (region *SRegion) GetICloudQuotas() ([]cloudprovider.ICloudQuota, error) {
ret := []cloudprovider.ICloudQuota{}
imageQ, err := region.GetImageQuota()
if err != nil {
return nil, errors.Wrap(err, "GetImageQuota")
}
ret = append(ret, imageQ)
for _, action := range []string{"DescribeAddressQuota", "DescribeBandwidthPackageQuota"} {
quotas, err := region.GetQuota(action)
if err != nil {
return nil, errors.Wrapf(err, "GetQuota(%s)", action)
}
for i := range quotas {
ret = append(ret, &quotas[i])
}
}
return ret, nil
}
+47
View File
@@ -0,0 +1,47 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/qcloud"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type ImageQuotaShowOptions struct {
}
shellutils.R(&ImageQuotaShowOptions{}, "image-quota", "Show image quota", func(cli *qcloud.SRegion, args *ImageQuotaShowOptions) error {
quota, err := cli.GetImageQuota()
if err != nil {
return err
}
printObject(quota)
return nil
})
type QuotaListOptions struct {
ACTION string `choices:"DescribeAddressQuota|DescribeBandwidthPackageQuota"`
}
shellutils.R(&QuotaListOptions{}, "quota-list", "List quotas", func(cli *qcloud.SRegion, args *QuotaListOptions) error {
quotas, err := cli.GetQuota(args.ACTION)
if err != nil {
return err
}
printList(quotas, 0, 0, 0, nil)
return nil
})
}
+4
View File
@@ -138,3 +138,7 @@ func (self *SRegion) GetIElasticcacheById(id string) (cloudprovider.ICloudElasti
func (self *SRegion) GetICloudEvents(start time.Time, end time.Time, withReadEvent bool) ([]cloudprovider.ICloudEvent, error) {
return nil, fmt.Errorf("Not Implemented GetICloudEvnets")
}
func (self *SRegion) GetICloudQuotas() ([]cloudprovider.ICloudQuota, error) {
return nil, fmt.Errorf("Not Implemented GetICloudQuotas")
}
+104
View File
@@ -0,0 +1,104 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package zstack
import (
"net/url"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
/*
"uuid":"132e0ad32b2242c4a648440be917ec4a",
"name":"pci.num",
"identityUuid":"2dce5dc485554d21a3796500c1db007a",
"identityType":"AccountVO",
"value":0,
"lastOpDate":"Dec 28, 2019 2:26:03 PM",
"createDate":"Dec 28, 2019 2:26:03 PM"
*/
type SQuota struct {
Uuid string
Name string
IdentityUuid string
IdentityType string
Value int
}
func (q *SQuota) GetGlobalId() string {
return q.Uuid
}
func (q *SQuota) GetName() string {
return q.Name
}
func (q *SQuota) GetDesc() string {
return ""
}
func (q *SQuota) GetQuotaType() string {
return q.Name
}
func (q *SQuota) GetMaxQuotaCount() int {
return q.Value
}
func (q *SQuota) GetCurrentQuotaUsedCount() int {
return -1
}
func (region *SRegion) GetQuotas() ([]SQuota, error) {
quotas := []SQuota{}
params := url.Values{}
err := region.client.listAll("accounts/quotas", params, &quotas)
if err != nil {
return nil, err
}
return quotas, nil
}
type SUserAccount struct {
Uuid string
}
func (region *SRegion) GetUserAccount(name string) ([]SUserAccount, error) {
users := []SUserAccount{}
params := url.Values{}
if len(name) > 0 {
params.Add("q", "name="+name)
}
err := region.client.listAll("accounts/users", params, &users)
if err != nil {
return nil, errors.Wrap(err, "users.list")
}
return users, nil
}
func (region *SRegion) GetICloudQuotas() ([]cloudprovider.ICloudQuota, error) {
quotas, err := region.GetQuotas()
if err != nil {
return nil, errors.Wrap(err, "GetQuotas")
}
ret := []cloudprovider.ICloudQuota{}
for i := range quotas {
ret = append(ret, &quotas[i])
}
return ret, nil
}
+33
View File
@@ -0,0 +1,33 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/zstack"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type QuotaListOptions struct {
}
shellutils.R(&QuotaListOptions{}, "quota-list", "List quotas", func(cli *zstack.SRegion, args *QuotaListOptions) error {
quotas, err := cli.GetQuotas()
if err != nil {
return err
}
printList(quotas, 0, 0, 0, nil)
return nil
})
}
+34
View File
@@ -0,0 +1,34 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/onecloud/pkg/multicloud/zstack"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type UserListOptions struct {
Name string
}
shellutils.R(&UserListOptions{}, "user-list", "List users", func(cli *zstack.SRegion, args *UserListOptions) error {
users, err := cli.GetUserAccount(args.Name)
if err != nil {
return err
}
printList(users, 0, 0, 0, nil)
return nil
})
}