From 1bc8e3845234affb44e85d079045f651b6a22fae Mon Sep 17 00:00:00 2001 From: Qu Xuan Date: Wed, 9 Jun 2021 18:16:38 +0800 Subject: [PATCH] fix(region): support cloudprovider bind project mapping --- cmd/climc/shell/compute/cloudproviders.go | 255 ++---------------- cmd/climc/shell/helper.go | 8 +- pkg/apis/compute/cloudprovider.go | 2 + pkg/compute/models/cloudaccounts.go | 2 +- pkg/compute/models/cloudproviders.go | 117 ++++++-- pkg/compute/models/cloudsync.go | 21 +- pkg/compute/models/project_mappings.go | 17 ++ pkg/compute/policy/resources.go | 1 + .../options/compute/cloudproviders.go | 145 ++++++++++ 9 files changed, 293 insertions(+), 275 deletions(-) create mode 100644 pkg/mcclient/options/compute/cloudproviders.go diff --git a/cmd/climc/shell/compute/cloudproviders.go b/cmd/climc/shell/compute/cloudproviders.go index f7778c183a..1bace8365b 100644 --- a/cmd/climc/shell/compute/cloudproviders.go +++ b/cmd/climc/shell/compute/cloudproviders.go @@ -18,251 +18,38 @@ import ( "fmt" "yunion.io/x/jsonutils" + "yunion.io/x/log" - "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/cmd/climc/shell" "yunion.io/x/onecloud/pkg/mcclient/modules" "yunion.io/x/onecloud/pkg/mcclient/options" + "yunion.io/x/onecloud/pkg/mcclient/options/compute" ) func init() { + cmd := shell.NewResourceCmd(&modules.Cloudproviders).WithKeyword("cloud-provider") + cmd.List(&compute.CloudproviderListOptions{}) + cmd.Update(&compute.CloudproviderUpdateOptions{}) + cmd.Show(&options.BaseIdOptions{}) + cmd.Delete(&options.BaseIdOptions{}) + cmd.Perform("change-project", &compute.CloudproviderChangeProjectOptions{}) + cmd.Perform("enable", &options.BaseIdOptions{}) + cmd.Perform("disable", &options.BaseIdOptions{}) + cmd.Perform("sync", &compute.CloudproviderSyncOptions{}) + cmd.Perform("project-mapping", &compute.ClouproviderProjectMappingOptions{}) - type CloudproviderListOptions struct { - options.BaseListOptions - - Usable bool `help:"Vpc & Network usable"` - - HasObjectStorage bool `help:"filter cloudproviders that has object storage"` - NoObjectStorage bool `help:"filter cloudproviders that has no object storage"` - Capability []string `help:"capability filter" choices:"project|compute|network|loadbalancer|objectstore|rds|cache|event"` - Cloudregion string `help:"filter cloudproviders by cloudregion"` - - HostSchedtagId string `help:"filter by host schedtag"` - } - R(&CloudproviderListOptions{}, "cloud-provider-list", "List cloud providers", func(s *mcclient.ClientSession, args *CloudproviderListOptions) error { - var params *jsonutils.JSONDict - { - var err error - params, err = args.BaseListOptions.Params() - if err != nil { - return err - } - - if args.Usable { - params.Add(jsonutils.NewBool(true), "usable") - } - - if args.HasObjectStorage { - params.Add(jsonutils.JSONTrue, "has_object_storage") - } else if args.NoObjectStorage { - params.Add(jsonutils.JSONFalse, "has_object_storage") - } - - if len(args.Capability) > 0 { - params.Add(jsonutils.NewStringArray(args.Capability), "capability") - } - - if len(args.Cloudregion) > 0 { - params.Add(jsonutils.NewString(args.Cloudregion), "cloudregion") - } - - if len(args.HostSchedtagId) > 0 { - params.Add(jsonutils.NewString(args.HostSchedtagId), "host_schedtag_id") - } - } - result, err := modules.Cloudproviders.List(s, params) - if err != nil { - return err - } - printList(result, modules.Cloudproviders.GetColumns(s)) - return nil - }) - - type CloudproviderUpdateOptions struct { - ID string `help:"ID or Name of cloud provider"` - Name string `help:"New name to update"` - AccessUrl string `help:"New access url"` - Desc string `help:"Description"` - } - R(&CloudproviderUpdateOptions{}, "cloud-provider-update", "Update a cloud provider", func(s *mcclient.ClientSession, args *CloudproviderUpdateOptions) 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.Cloudproviders.Update(s, args.ID, params) - if err != nil { - return err - } - printObject(result) - 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"` - } - R(&CloudproviderShowOptions{}, "cloud-provider-show", "Get details of a cloud provider", func(s *mcclient.ClientSession, args *CloudproviderShowOptions) error { - result, err := modules.Cloudproviders.Get(s, args.ID, nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - - R(&CloudproviderShowOptions{}, "cloud-provider-delete", "Delete a cloud provider", func(s *mcclient.ClientSession, args *CloudproviderShowOptions) error { - result, err := modules.Cloudproviders.Delete(s, args.ID, nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - - R(&CloudproviderShowOptions{}, "cloud-provider-enable", "Enable cloud provider", func(s *mcclient.ClientSession, args *CloudproviderShowOptions) error { - result, err := modules.Cloudproviders.PerformAction(s, args.ID, "enable", nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - - R(&CloudproviderShowOptions{}, "cloud-provider-disable", "Disable cloud provider", func(s *mcclient.ClientSession, args *CloudproviderShowOptions) error { - result, err := modules.Cloudproviders.PerformAction(s, args.ID, "disable", nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - - R(&CloudproviderShowOptions{}, "cloud-provider-balance", "Get balance", func(s *mcclient.ClientSession, args *CloudproviderShowOptions) error { - result, err := modules.Cloudproviders.GetSpecific(s, args.ID, "balance", nil) - if err != nil { - return err - } - printObject(result) - return nil - }) - - type CloudproviderUpdateCredentialOptions struct { - ID string `help:"ID or Name of cloud provider"` - ACCOUNT string `help:"new account"` - SECRET string `help:"new secret"` - } - R(&CloudproviderUpdateCredentialOptions{}, "cloud-provider-update-credential", "Update credential of a cloud provider", func(s *mcclient.ClientSession, args *CloudproviderUpdateCredentialOptions) error { - params := jsonutils.NewDict() - params.Add(jsonutils.NewString(args.ACCOUNT), "account") - params.Add(jsonutils.NewString(args.SECRET), "secret") - - result, err := modules.Cloudproviders.PerformAction(s, args.ID, "update-credential", params) - if err != nil { - return err - } - printObject(result) - return nil - }) - - type CloudproviderSyncOptions struct { - ID string `help:"ID or Name of cloud provider"` - Force bool `help:"Force sync no matter what"` - FullSync bool `help:"Synchronize everything"` - ProjectSync bool `help:"Auto sync project info"` - Region []string `help:"region to sync"` - Zone []string `help:"region to sync"` - Host []string `help:"region to sync"` - } - R(&CloudproviderSyncOptions{}, "cloud-provider-sync", "Sync of a cloud provider account", func(s *mcclient.ClientSession, args *CloudproviderSyncOptions) error { - params := jsonutils.NewDict() - if args.Force { - params.Add(jsonutils.JSONTrue, "force") - } - if args.FullSync { - params.Add(jsonutils.JSONTrue, "full_sync") - } - if args.ProjectSync { - params.Add(jsonutils.JSONTrue, "project_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.Cloudproviders.PerformAction(s, args.ID, "sync", params) - if err != nil { - return err - } - printObject(result) - return nil - }) - - type CloudproviderClientRCOptions struct { - ID string `help:"ID or name of cloud provider"` - } - R(&CloudproviderClientRCOptions{}, "cloud-provider-clirc", "Get client RC file of the cloud provider", func(s *mcclient.ClientSession, args *CloudproviderClientRCOptions) error { - result, err := modules.Cloudproviders.GetSpecific(s, args.ID, "clirc", nil) - if err != nil { - return err - } + cmd.GetWithCustomShow("clirc", func(result jsonutils.JSONObject) { rc := make(map[string]string) - err = result.Unmarshal(&rc) + err := result.Unmarshal(&rc) if err != nil { - return err + log.Errorf("error: %v", err) + return } for k, v := range rc { fmt.Printf(`export %s="%s"`+"\n", k, v) } - return nil - }) - - type CloudproviderStorageClassesOptions struct { - ID string `help:"ID or Name of cloud provider" json:"-"` - Cloudregion string `help:"cloud region name or Id"` - } - R(&CloudproviderStorageClassesOptions{}, "cloud-provider-storage-classes", "Get list of supported storage classes of a cloud provider", func(s *mcclient.ClientSession, args *CloudproviderStorageClassesOptions) error { - params, err := options.StructToParams(args) - if err != nil { - return err - } - result, err := modules.Cloudproviders.GetSpecific(s, args.ID, "storage-classes", params) - if err != nil { - return err - } - printObject(result) - return nil - }) - - R(&CloudproviderShowOptions{}, "cloud-provider-change-owner-candidate-domains", "Show candiate domains of a cloud provider changing owner", func(s *mcclient.ClientSession, args *CloudproviderShowOptions) error { - result, err := modules.Cloudproviders.GetSpecific(s, args.ID, "change-owner-candidate-domains", nil) - if err != nil { - return err - } - printObject(result) - return nil - }) + }, &options.BaseIdOptions{}) + cmd.Get("storage-classes", &compute.CloudproviderStorageClassesOptions{}) + cmd.Get("change-owner-candidate-domains", &options.BaseIdOptions{}) + cmd.Get("balance", &options.BaseIdOptions{}) } diff --git a/cmd/climc/shell/helper.go b/cmd/climc/shell/helper.go index fd33a3f9cf..a66d0b0a94 100644 --- a/cmd/climc/shell/helper.go +++ b/cmd/climc/shell/helper.go @@ -421,7 +421,7 @@ type IGetOpt interface { IOpt } -func (cmd ResourceCmd) Get(specific string, args IGetOpt) { +func (cmd ResourceCmd) GetWithCustomShow(specific string, show func(data jsonutils.JSONObject), args IGetOpt) { man := cmd.manager callback := func(s *mcclient.ClientSession, args IGetOpt) error { params, err := args.Params() @@ -432,12 +432,16 @@ func (cmd ResourceCmd) Get(specific string, args IGetOpt) { if err != nil { return err } - printObject(ret) + show(ret) return nil } cmd.RunWithDesc(specific, fmt.Sprintf("Get %s of a %s", specific, man.GetKeyword()), args, callback) } +func (cmd ResourceCmd) Get(specific string, args IGetOpt) { + cmd.GetWithCustomShow(specific, printObject, args) +} + type IUpdateOpt interface { IOpt IIdOpt diff --git a/pkg/apis/compute/cloudprovider.go b/pkg/apis/compute/cloudprovider.go index 77e5d2a625..a137ff67a4 100644 --- a/pkg/apis/compute/cloudprovider.go +++ b/pkg/apis/compute/cloudprovider.go @@ -137,6 +137,8 @@ type CloudproviderDetails struct { // 子订阅品牌信息 Brand string `json:"brand"` + + ProjectMappingResourceInfo } // 云订阅输入参数 diff --git a/pkg/compute/models/cloudaccounts.go b/pkg/compute/models/cloudaccounts.go index 6953cccb7d..fb606c96ef 100644 --- a/pkg/compute/models/cloudaccounts.go +++ b/pkg/compute/models/cloudaccounts.go @@ -2885,5 +2885,5 @@ func (self *SCloudaccount) PerformProjectMapping(ctx context.Context, userCred m if err != nil { return nil, err } - return nil, refreshMapping() + return nil, refreshPmCaches() } diff --git a/pkg/compute/models/cloudproviders.go b/pkg/compute/models/cloudproviders.go index 60d32c92ff..41f55dcbae 100644 --- a/pkg/compute/models/cloudproviders.go +++ b/pkg/compute/models/cloudproviders.go @@ -37,6 +37,7 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" "yunion.io/x/onecloud/pkg/cloudcommon/db/proxy" "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" + "yunion.io/x/onecloud/pkg/cloudcommon/validators" "yunion.io/x/onecloud/pkg/cloudprovider" "yunion.io/x/onecloud/pkg/compute/options" "yunion.io/x/onecloud/pkg/httperrors" @@ -52,6 +53,7 @@ type SCloudproviderManager struct { db.SEnabledStatusStandaloneResourceBaseManager db.SProjectizedResourceBaseManager + SProjectMappingResourceBaseManager SSyncableBaseResourceManager } @@ -108,49 +110,61 @@ type SCloudprovider struct { // 云账号的平台信息 Provider string `width:"64" charset:"ascii" list:"domain" create:"domain_required"` + + SProjectMappingResourceBase } -type providerMapping struct { - Id string - CloudaccountId string - ProjectMappingId string +type pmCache struct { + Id string + CloudaccountId string + AccountProjectMappingId string + ManagerProjectMappingId string } -var providerProjectMapping map[string]*providerMapping = map[string]*providerMapping{} +func (self *pmCache) GetProjectMapping() (*SProjectMapping, error) { + if len(self.ManagerProjectMappingId) > 0 { + return GetRuleMapping(self.ManagerProjectMappingId) + } + if len(self.AccountProjectMappingId) > 0 { + return GetRuleMapping(self.AccountProjectMappingId) + } + return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty project mapping id") +} -func refreshMapping() error { - q := CloudproviderManager.Query("cloudaccount_id", "id") +var pmCaches map[string]*pmCache = map[string]*pmCache{} + +func refreshPmCaches() error { + q := CloudproviderManager.Query().SubQuery() + providers := q.Query(q.Field("cloudaccount_id"), q.Field("id"), q.Field("project_mapping_id").Label("manager_project_mapping_id")) sq := CloudaccountManager.Query().SubQuery() - q = q.LeftJoin(sq, sqlchemy.Equals(q.Field("cloudaccount_id"), sq.Field("id"))).AppendField(sq.Field("project_mapping_id")) - pms := []providerMapping{} - err := q.All(&pms) + mq := providers.LeftJoin(sq, sqlchemy.Equals(q.Field("cloudaccount_id"), sq.Field("id"))).AppendField(sq.Field("project_mapping_id").Label("account_project_mapping_id")) + caches := []pmCache{} + err := mq.All(&caches) if err != nil { return errors.Wrapf(err, "q.All") } - for i := range pms { - providerProjectMapping[pms[i].Id] = &pms[i] + for i := range caches { + pmCaches[caches[i].Id] = &caches[i] } return nil } -func (self *providerMapping) GetCloudaccount() (*SCloudaccount, error) { - account, err := CloudaccountManager.FetchById(self.CloudaccountId) +func (self *SCloudprovider) GetProjectMapping() (*SProjectMapping, error) { + cache, err := func() (*pmCache, error) { + mp, ok := pmCaches[self.Id] + if ok { + return mp, nil + } + err := refreshPmCaches() + if err != nil { + return nil, errors.Wrapf(err, "refreshPmCaches") + } + return pmCaches[self.Id], nil + }() if err != nil { - return nil, errors.Wrapf(err, "FetchById(%s)", self.CloudaccountId) + return nil, errors.Wrapf(err, "get project mapping cache") } - return account.(*SCloudaccount), nil -} - -func GetProviderMapping(id string) (*providerMapping, error) { - mp, ok := providerProjectMapping[id] - if ok { - return mp, nil - } - err := refreshMapping() - if err != nil { - return nil, err - } - return providerProjectMapping[id], nil + return cache.GetProjectMapping() } func (self *SCloudprovider) ValidateDeleteCondition(ctx context.Context) error { @@ -976,6 +990,7 @@ func (manager *SCloudproviderManager) FetchCustomizeColumns( stdRows := manager.SEnabledStatusStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList) projRows := manager.SProjectizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList) + pmRows := manager.SProjectMappingResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList) accountIds := make([]string, len(objs)) for i := range rows { provider := objs[i].(*SCloudprovider) @@ -985,6 +1000,7 @@ func (manager *SCloudproviderManager) FetchCustomizeColumns( ProjectizedResourceInfo: projRows[i], SCloudproviderUsage: provider.getUsage(), SyncStatus2: provider.getSyncStatus2(), + ProjectMappingResourceInfo: pmRows[i], } capabilities, _ := CloudproviderCapabilityManager.getCapabilities(provider.Id) if len(capabilities) > 0 { @@ -1885,3 +1901,48 @@ func (self *SCloudprovider) SyncCallSyncCloudproviderInterVpcNetwork(ctx context } } } + +func (manager *SCloudproviderManager) ListItemExportKeys(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, keys stringutils2.SSortedStrings) (*sqlchemy.SQuery, error) { + q, err := manager.SEnabledStatusStandaloneResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys) + if err != nil { + return nil, errors.Wrap(err, "SEnabledStatusStandaloneResourceBaseManager.ListItemExportKeys") + } + q, err = manager.SProjectizedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys) + if err != nil { + return nil, errors.Wrapf(err, "SProjectizedResourceBaseManager.ListItemExportKeys") + } + q, err = manager.SProjectMappingResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys) + if err != nil { + return nil, errors.Wrapf(err, "SProjectMappingResourceBaseManager.ListItemExportKeys") + } + return q, nil +} + +func (self *SCloudprovider) AllowPerformProjectMapping(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool { + return db.IsAdminAllowPerform(userCred, self, "project-mapping") +} + +// 绑定同步策略 +func (self *SCloudprovider) PerformProjectMapping(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.CloudaccountProjectMappingInput) (jsonutils.JSONObject, error) { + if len(input.ProjectMappingId) > 0 { + _, err := validators.ValidateModel(userCred, ProjectMappingManager, &input.ProjectMappingId) + if err != nil { + return nil, err + } + if len(self.ProjectMappingId) > 0 && self.ProjectMappingId != input.ProjectMappingId { + return nil, httperrors.NewInputParameterError("cloudprovider %s has aleady bind project mapping %s", self.Name, self.ProjectMappingId) + } + } + // no changes + if self.ProjectMappingId == input.ProjectMappingId { + return nil, nil + } + _, err := db.Update(self, func() error { + self.ProjectMappingId = input.ProjectMappingId + return nil + }) + if err != nil { + return nil, err + } + return nil, refreshPmCaches() +} diff --git a/pkg/compute/models/cloudsync.go b/pkg/compute/models/cloudsync.go index ec6c0afd31..65f936a87b 100644 --- a/pkg/compute/models/cloudsync.go +++ b/pkg/compute/models/cloudsync.go @@ -1400,20 +1400,21 @@ func (manager *SCloudproviderregionManager) initAllRecords() { func SyncCloudProject(userCred mcclient.TokenCredential, model db.IVirtualModel, syncOwnerId mcclient.IIdentityProvider, extModel cloudprovider.IVirtualResource, managerId string) { newOwnerId, err := func() (mcclient.IIdentityProvider, error) { - pm, err := GetProviderMapping(managerId) + _manager, err := CloudproviderManager.FetchById(managerId) if err != nil { - return nil, errors.Wrapf(err, "GetProviderMapping") + return nil, errors.Wrapf(err, "CloudproviderManager.FetchById(%s)", managerId) } - if len(pm.ProjectMappingId) == 0 { - return nil, nil - } - account, err := pm.GetCloudaccount() + manager := _manager.(*SCloudprovider) + rm, err := manager.GetProjectMapping() if err != nil { - return nil, errors.Wrapf(err, "GetCloudaccount") + if errors.Cause(err) == cloudprovider.ErrNotFound { + return nil, nil + } + return nil, errors.Wrapf(err, "GetProjectMapping") } - rm, err := GetRuleMapping(pm.ProjectMappingId) - if err != nil { - return nil, errors.Wrapf(err, "GetRuleMapping") + account := manager.GetCloudaccount() + if account == nil { + return nil, fmt.Errorf("can not find manager %s account", manager.Name) } if rm != nil && rm.Enabled.Bool() { extTags, err := extModel.GetTags() diff --git a/pkg/compute/models/project_mappings.go b/pkg/compute/models/project_mappings.go index bac6322180..b5f15a305e 100644 --- a/pkg/compute/models/project_mappings.go +++ b/pkg/compute/models/project_mappings.go @@ -236,6 +236,16 @@ func (self *SProjectMapping) GetCloudaccounts() ([]SCloudaccount, error) { return accounts, nil } +func (self *SProjectMapping) GetCloudproviders() ([]SCloudprovider, error) { + q := CloudproviderManager.Query().Equals("project_mapping_id", self.Id) + ret := []SCloudprovider{} + err := db.FetchModelObjects(CloudproviderManager, q, &ret) + if err != nil { + return nil, err + } + return ret, nil +} + func (self *SProjectMapping) Delete(ctx context.Context, userCred mcclient.TokenCredential) error { delete(projectRuleMapping, self.Id) return self.SEnabledStatusInfrasResourceBase.Delete(ctx, userCred) @@ -249,6 +259,13 @@ func (self *SProjectMapping) ValidateDeleteCondition(ctx context.Context) error if len(accounts) > 0 { return httperrors.NewNotEmptyError("project mapping has associate %d accounts", len(accounts)) } + providers, err := self.GetCloudproviders() + if err != nil { + return errors.Wrapf(err, "GetCloudproviders") + } + if len(providers) > 0 { + return httperrors.NewNotEmptyError("project mapping has associate %d cloudproviders", len(providers)) + } return self.SEnabledStatusInfrasResourceBase.ValidateDeleteCondition(ctx) } diff --git a/pkg/compute/policy/resources.go b/pkg/compute/policy/resources.go index 6d8b87fc3a..e0305fde95 100644 --- a/pkg/compute/policy/resources.go +++ b/pkg/compute/policy/resources.go @@ -57,6 +57,7 @@ var ( "natdentries", "policy_assignments", "proxysettings", + "project_mappings", } computeUserResources = []string{ "keypairs", diff --git a/pkg/mcclient/options/compute/cloudproviders.go b/pkg/mcclient/options/compute/cloudproviders.go new file mode 100644 index 0000000000..33d960e3e6 --- /dev/null +++ b/pkg/mcclient/options/compute/cloudproviders.go @@ -0,0 +1,145 @@ +// 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/jsonutils" + + "yunion.io/x/onecloud/pkg/mcclient/options" +) + +type CloudproviderListOptions struct { + options.BaseListOptions + + Usable bool `help:"Vpc & Network usable"` + + HasObjectStorage bool `help:"filter cloudproviders that has object storage"` + NoObjectStorage bool `help:"filter cloudproviders that has no object storage"` + Capability []string `help:"capability filter" choices:"project|compute|network|loadbalancer|objectstore|rds|cache|event"` + Cloudregion string `help:"filter cloudproviders by cloudregion"` + + HostSchedtagId string `help:"filter by host schedtag"` +} + +func (opts *CloudproviderListOptions) Params() (jsonutils.JSONObject, error) { + params, err := opts.BaseListOptions.Params() + if err != nil { + return nil, err + } + + if opts.Usable { + params.Add(jsonutils.NewBool(true), "usable") + } + + if opts.HasObjectStorage { + params.Add(jsonutils.JSONTrue, "has_object_storage") + } else if opts.NoObjectStorage { + params.Add(jsonutils.JSONFalse, "has_object_storage") + } + + if len(opts.Capability) > 0 { + params.Add(jsonutils.NewStringArray(opts.Capability), "capability") + } + + if len(opts.Cloudregion) > 0 { + params.Add(jsonutils.NewString(opts.Cloudregion), "cloudregion") + } + + if len(opts.HostSchedtagId) > 0 { + params.Add(jsonutils.NewString(opts.HostSchedtagId), "host_schedtag_id") + } + return params, nil +} + +type CloudproviderUpdateOptions struct { + options.BaseIdOptions + Name string `help:"New name to update"` + AccessUrl string `help:"New access url"` + Desc string `help:"Description"` +} + +func (opts *CloudproviderUpdateOptions) Params() (jsonutils.JSONObject, error) { + params := jsonutils.NewDict() + if len(opts.Name) > 0 { + params.Add(jsonutils.NewString(opts.Name), "name") + } + if len(opts.AccessUrl) > 0 { + params.Add(jsonutils.NewString(opts.AccessUrl), "access_url") + } + if len(opts.Desc) > 0 { + params.Add(jsonutils.NewString(opts.Desc), "description") + } + return params, nil +} + +type CloudproviderChangeProjectOptions struct { + options.BaseIdOptions + TENANT string `help:"ID or Name of tenant"` +} + +func (opts *CloudproviderChangeProjectOptions) Params() (jsonutils.JSONObject, error) { + return jsonutils.Marshal(map[string]string{"project": opts.TENANT}), nil +} + +type CloudproviderSyncOptions struct { + options.BaseIdOptions + Force bool `help:"Force sync no matter what"` + FullSync bool `help:"Synchronize everything"` + ProjectSync bool `help:"Auto sync project info"` + Region []string `help:"region to sync"` + Zone []string `help:"region to sync"` + Host []string `help:"region to sync"` +} + +func (opts *CloudproviderSyncOptions) Params() (jsonutils.JSONObject, error) { + params := jsonutils.NewDict() + if opts.Force { + params.Add(jsonutils.JSONTrue, "force") + } + if opts.FullSync { + params.Add(jsonutils.JSONTrue, "full_sync") + } + if opts.ProjectSync { + params.Add(jsonutils.JSONTrue, "project_sync") + } + if len(opts.Region) > 0 { + params.Add(jsonutils.NewStringArray(opts.Region), "region") + } + if len(opts.Zone) > 0 { + params.Add(jsonutils.NewStringArray(opts.Zone), "zone") + } + if len(opts.Host) > 0 { + params.Add(jsonutils.NewStringArray(opts.Host), "host") + } + return params, nil +} + +type CloudproviderStorageClassesOptions struct { + options.BaseIdOptions + Cloudregion string `help:"cloud region name or Id"` +} + +func (opts *CloudproviderStorageClassesOptions) Params() (jsonutils.JSONObject, error) { + return options.StructToParams(opts) +} + +type ClouproviderProjectMappingOptions struct { + options.BaseIdOptions + ProjectMappingId string `json:"project_mapping_id" help:"project mapping id"` +} + +func (opts *ClouproviderProjectMappingOptions) Params() (jsonutils.JSONObject, error) { + return jsonutils.Marshal(map[string]string{"project_mapping_id": opts.ProjectMappingId}), nil +}