diff --git a/cmd/climc/shell/compute/dbinstances.go b/cmd/climc/shell/compute/dbinstances.go index 835fbaff77..453324d19d 100644 --- a/cmd/climc/shell/compute/dbinstances.go +++ b/cmd/climc/shell/compute/dbinstances.go @@ -20,6 +20,7 @@ import ( "yunion.io/x/jsonutils" + computeapi "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/mcclient/modulebase" "yunion.io/x/onecloud/pkg/mcclient/modules" @@ -371,4 +372,47 @@ func init() { return nil }) + R(&options.ResourceMetadataOptions{}, "dbinstance-add-tag", "Set tag of a dbinstance", func(s *mcclient.ClientSession, opts *options.ResourceMetadataOptions) error { + params, err := opts.Params() + if err != nil { + return err + } + result, err := modules.DBInstance.PerformAction(s, opts.ID, "user-metadata", params) + if err != nil { + return err + } + printObject(result) + return nil + }) + + R(&options.ResourceMetadataOptions{}, "dbinstance-set-tag", "Set tag of a dbinstance", func(s *mcclient.ClientSession, opts *options.ResourceMetadataOptions) error { + params, err := opts.Params() + if err != nil { + return err + } + result, err := modules.DBInstance.PerformAction(s, opts.ID, "set-user-metadata", params) + if err != nil { + return err + } + printObject(result) + return nil + }) + + type DBInstanceRemoteUpdateOptions struct { + ID string `json:"-"` + computeapi.DBInstanceRemoteUpdateInput + } + + R(&DBInstanceRemoteUpdateOptions{}, "dbinstance-remote-update", "Change owner porject of a dbinstance", func(s *mcclient.ClientSession, opts *DBInstanceRemoteUpdateOptions) error { + params, err := options.StructToParams(opts) + if err != nil { + return err + } + result, err := modules.DBInstance.PerformAction(s, opts.ID, "remote-update", params) + if err != nil { + return err + } + printObject(result) + return nil + }) } diff --git a/cmd/climc/shell/compute/elasticcache.go b/cmd/climc/shell/compute/elasticcache.go index c1945639af..25a2eb0669 100644 --- a/cmd/climc/shell/compute/elasticcache.go +++ b/cmd/climc/shell/compute/elasticcache.go @@ -393,4 +393,44 @@ func init() { printList(result, nil) return nil }) + + R(&options.ResourceMetadataOptions{}, "elastic-cache-add-tag", "Set tag of a server", func(s *mcclient.ClientSession, opts *options.ResourceMetadataOptions) error { + params, err := opts.Params() + if err != nil { + return err + } + result, err := modules.ElasticCache.PerformAction(s, opts.ID, "user-metadata", params) + if err != nil { + return err + } + printObject(result) + return nil + }) + + R(&options.ResourceMetadataOptions{}, "elastic-cache-set-tag", "Set tag of a server", func(s *mcclient.ClientSession, opts *options.ResourceMetadataOptions) error { + params, err := opts.Params() + if err != nil { + return err + } + result, err := modules.ElasticCache.PerformAction(s, opts.ID, "set-user-metadata", params) + if err != nil { + return err + } + printObject(result) + return nil + }) + + R(&options.ElasticCacheRemoteUpdateOptions{}, "elastic-cache-remote-update", "Restore elastisc cache backup", func(s *mcclient.ClientSession, opts *options.ElasticCacheRemoteUpdateOptions) error { + params, err := options.StructToParams(opts) + if err != nil { + return err + } + result, err := modules.ElasticCache.PerformAction(s, opts.ID, "remote-update", params) + if err != nil { + return err + } + + printObject(result) + return nil + }) } diff --git a/cmd/climc/shell/compute/loadbalancers.go b/cmd/climc/shell/compute/loadbalancers.go index 478fd09cef..6ec2bfe22e 100644 --- a/cmd/climc/shell/compute/loadbalancers.go +++ b/cmd/climc/shell/compute/loadbalancers.go @@ -108,4 +108,43 @@ func init() { return nil }) + R(&options.ResourceMetadataOptions{}, "lb-add-tag", "Set tag of a lb", func(s *mcclient.ClientSession, opts *options.ResourceMetadataOptions) error { + params, err := opts.Params() + if err != nil { + return err + } + result, err := modules.Loadbalancers.PerformAction(s, opts.ID, "user-metadata", params) + if err != nil { + return err + } + printObject(result) + return nil + }) + + R(&options.ResourceMetadataOptions{}, "lb-set-tag", "Set tag of a lb", func(s *mcclient.ClientSession, opts *options.ResourceMetadataOptions) error { + params, err := opts.Params() + if err != nil { + return err + } + result, err := modules.Loadbalancers.PerformAction(s, opts.ID, "set-user-metadata", params) + if err != nil { + return err + } + printObject(result) + return nil + }) + + R(&options.LoadbalancerRemoteUpdateOptions{}, "lb-remote-update", "Change lb status", func(s *mcclient.ClientSession, opts *options.ServerRemoteUpdateOptions) error { + params, err := options.StructToParams(opts) + if err != nil { + return err + } + lb, err := modules.Loadbalancers.PerformAction(s, opts.ID, "remote-update", params) + if err != nil { + return err + } + printObject(lb) + return nil + }) + } diff --git a/pkg/apis/compute/dbinstance.go b/pkg/apis/compute/dbinstance.go index c911051048..c28597c668 100644 --- a/pkg/apis/compute/dbinstance.go +++ b/pkg/apis/compute/dbinstance.go @@ -346,3 +346,8 @@ type DBInstanceNetworkListInput struct { apis.VirtualJointResourceBaseListInput DBInstanceFilterListInput } + +type DBInstanceRemoteUpdateInput struct { + // 是否覆盖替换所有标签 + ReplaceTags *bool `json:"replace_tags" help:"replace all remote tags"` +} diff --git a/pkg/apis/compute/elasticcache.go b/pkg/apis/compute/elasticcache.go index 953ea14c78..9070b4da21 100644 --- a/pkg/apis/compute/elasticcache.go +++ b/pkg/apis/compute/elasticcache.go @@ -94,3 +94,8 @@ type ElasticcacheParameterDetails struct { type ElasticcacheSyncstatusInput struct { } + +type ElasticcacheRemoteUpdateInput struct { + // 是否覆盖替换所有标签 + ReplaceTags *bool `json:"replace_tags" help:"replace all remote tags"` +} diff --git a/pkg/apis/compute/loadbalancer.go b/pkg/apis/compute/loadbalancer.go index bd82da1911..406534da29 100644 --- a/pkg/apis/compute/loadbalancer.go +++ b/pkg/apis/compute/loadbalancer.go @@ -269,3 +269,8 @@ type LoadbalancerCreateInput struct { CloudproviderResourceInput // Manager string `json:"manager"` } + +type LoadbalancerRemoteUpdateInput struct { + // 是否覆盖替换所有标签 + ReplaceTags *bool `json:"replace_tags" help:"replace all remote tags"` +} diff --git a/pkg/cloudprovider/loadbalancer.go b/pkg/cloudprovider/loadbalancer.go index 3740477d70..b0f87d8099 100644 --- a/pkg/cloudprovider/loadbalancer.go +++ b/pkg/cloudprovider/loadbalancer.go @@ -30,4 +30,5 @@ type SLoadbalancer struct { EgressMbps int billingCycle *billing.SBillingCycle ProjectId string + Tags map[string]string } diff --git a/pkg/cloudprovider/resources.go b/pkg/cloudprovider/resources.go index 368f4f2737..43a5193612 100644 --- a/pkg/cloudprovider/resources.go +++ b/pkg/cloudprovider/resources.go @@ -530,6 +530,8 @@ type ICloudLoadbalancer interface { CreateILoadBalancerListener(ctx context.Context, listener *SLoadbalancerListener) (ICloudLoadbalancerListener, error) GetILoadBalancerListenerById(listenerId string) (ICloudLoadbalancerListener, error) + + SetMetadata(tags map[string]string, replace bool) error } type ICloudLoadbalancerListener interface { @@ -802,6 +804,8 @@ type ICloudDBInstance interface { RecoveryFromBackup(conf *SDBInstanceRecoveryConfig) error Delete() error + + SetMetadata(tags map[string]string, replace bool) error } type ICloudDBInstanceParameter interface { @@ -906,6 +910,8 @@ type ICloudElasticcache interface { UpdateAuthMode(noPasswordAccess bool) error UpdateInstanceParameters(config jsonutils.JSONObject) error UpdateBackupPolicy(config SCloudElasticCacheBackupPolicyUpdateInput) error + + SetMetadata(tags map[string]string, replace bool) error } type ICloudElasticcacheAccount interface { diff --git a/pkg/compute/models/dbinstances.go b/pkg/compute/models/dbinstances.go index 99e57cc474..ee55238488 100644 --- a/pkg/compute/models/dbinstances.go +++ b/pkg/compute/models/dbinstances.go @@ -464,6 +464,7 @@ func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred } func (self *SDBInstance) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) { + self.SVirtualResourceBase.PostCreate(ctx, userCred, ownerId, query, data) pendingUsage := SRegionQuota{Loadbalancer: 1} pendingUsage.SetKeys(self.GetQuotaKeys()) err := quotas.CancelPendingUsage(ctx, userCred, &pendingUsage, &pendingUsage, true) @@ -1875,3 +1876,39 @@ func (self *SDBInstance) CancelExpireTime(ctx context.Context, userCred mcclient db.OpsLog.LogEvent(self, db.ACT_RENEW, "dbinstance cancel expire time", userCred) return nil } + +func (self *SDBInstance) AllowPerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { + return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "remote-update") +} + +func (self *SDBInstance) PerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.DBInstanceRemoteUpdateInput) (jsonutils.JSONObject, error) { + err := self.StartRemoteUpdateTask(ctx, userCred, (input.ReplaceTags != nil && *input.ReplaceTags), "") + if err != nil { + return nil, errors.Wrap(err, "StartRemoteUpdateTask") + } + return nil, nil +} + +func (self *SDBInstance) StartRemoteUpdateTask(ctx context.Context, userCred mcclient.TokenCredential, replaceTags bool, parentTaskId string) error { + data := jsonutils.NewDict() + if replaceTags { + data.Add(jsonutils.JSONTrue, "replace_tags") + } + if task, err := taskman.TaskManager.NewTask(ctx, "DBInstanceRemoteUpdateTask", self, userCred, data, parentTaskId, "", nil); err != nil { + log.Errorln(err) + return errors.Wrap(err, "Start ElasticcacheRemoteUpdateTask") + } else { + task.ScheduleRun(nil) + } + return nil +} + +func (self *SDBInstance) OnMetadataUpdated(ctx context.Context, userCred mcclient.TokenCredential) { + if len(self.ExternalId) == 0 { + return + } + err := self.StartRemoteUpdateTask(ctx, userCred, false, "") + if err != nil { + log.Errorf("StartRemoteUpdateTask fail: %s", err) + } +} diff --git a/pkg/compute/models/elasticcache_instances.go b/pkg/compute/models/elasticcache_instances.go index 615248eec4..6ab14ee8e8 100644 --- a/pkg/compute/models/elasticcache_instances.go +++ b/pkg/compute/models/elasticcache_instances.go @@ -1713,3 +1713,39 @@ func (self *SElasticcache) CancelExpireTime(ctx context.Context, userCred mcclie db.OpsLog.LogEvent(self, db.ACT_RENEW, "elasticcache cancel expire time", userCred) return nil } + +func (self *SElasticcache) AllowPerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { + return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "remote-update") +} + +func (self *SElasticcache) PerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ElasticcacheRemoteUpdateInput) (jsonutils.JSONObject, error) { + err := self.StartRemoteUpdateTask(ctx, userCred, (input.ReplaceTags != nil && *input.ReplaceTags), "") + if err != nil { + return nil, errors.Wrap(err, "StartRemoteUpdateTask") + } + return nil, nil +} + +func (self *SElasticcache) StartRemoteUpdateTask(ctx context.Context, userCred mcclient.TokenCredential, replaceTags bool, parentTaskId string) error { + data := jsonutils.NewDict() + if replaceTags { + data.Add(jsonutils.JSONTrue, "replace_tags") + } + if task, err := taskman.TaskManager.NewTask(ctx, "ElasticcacheRemoteUpdateTask", self, userCred, data, parentTaskId, "", nil); err != nil { + log.Errorln(err) + return errors.Wrap(err, "Start ElasticcacheRemoteUpdateTask") + } else { + task.ScheduleRun(nil) + } + return nil +} + +func (self *SElasticcache) OnMetadataUpdated(ctx context.Context, userCred mcclient.TokenCredential) { + if len(self.ExternalId) == 0 { + return + } + err := self.StartRemoteUpdateTask(ctx, userCred, false, "") + if err != nil { + log.Errorf("StartRemoteUpdateTask fail: %s", err) + } +} diff --git a/pkg/compute/models/loadbalancers.go b/pkg/compute/models/loadbalancers.go index d749c8a79e..22ad7ed97d 100644 --- a/pkg/compute/models/loadbalancers.go +++ b/pkg/compute/models/loadbalancers.go @@ -454,6 +454,7 @@ func (lb *SLoadbalancer) GetCreateLoadbalancerParams(iRegion cloudprovider.IClou ChargeType: lb.ChargeType, LoadbalancerSpec: lb.LoadbalancerSpec, } + params.Tags, _ = lb.GetAllUserMetadata() if len(lb.ZoneId) > 0 { zone := lb.GetZone() @@ -1221,3 +1222,39 @@ func (manager *SLoadbalancerManager) ListItemExportKeys(ctx context.Context, func (self *SLoadbalancer) GetChangeOwnerCandidateDomainIds() []string { return self.SManagedResourceBase.GetChangeOwnerCandidateDomainIds() } + +func (self *SLoadbalancer) AllowPerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { + return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "remote-update") +} + +func (self *SLoadbalancer) PerformRemoteUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.LoadbalancerRemoteUpdateInput) (jsonutils.JSONObject, error) { + err := self.StartRemoteUpdateTask(ctx, userCred, (input.ReplaceTags != nil && *input.ReplaceTags), "") + if err != nil { + return nil, errors.Wrap(err, "StartRemoteUpdateTask") + } + return nil, nil +} + +func (guest *SLoadbalancer) StartRemoteUpdateTask(ctx context.Context, userCred mcclient.TokenCredential, replaceTags bool, parentTaskId string) error { + data := jsonutils.NewDict() + if replaceTags { + data.Add(jsonutils.JSONTrue, "replace_tags") + } + if task, err := taskman.TaskManager.NewTask(ctx, "LoadbalancerRemoteUpdateTask", guest, userCred, data, parentTaskId, "", nil); err != nil { + log.Errorln(err) + return errors.Wrap(err, "Start LoadbalancerRemoteUpdateTask") + } else { + task.ScheduleRun(nil) + } + return nil +} + +func (guest *SLoadbalancer) OnMetadataUpdated(ctx context.Context, userCred mcclient.TokenCredential) { + if len(guest.ExternalId) == 0 { + return + } + err := guest.StartRemoteUpdateTask(ctx, userCred, false, "") + if err != nil { + log.Errorf("StartRemoteUpdateTask fail: %s", err) + } +} diff --git a/pkg/compute/models/regiondrivers.go b/pkg/compute/models/regiondrivers.go index fba1d7486e..61f609de71 100644 --- a/pkg/compute/models/regiondrivers.go +++ b/pkg/compute/models/regiondrivers.go @@ -46,6 +46,7 @@ type IRegionDriver interface { RequestStartLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *SLoadbalancer, task taskman.ITask) error RequestStopLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *SLoadbalancer, task taskman.ITask) error RequestSyncstatusLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *SLoadbalancer, task taskman.ITask) error + RequestRemoteUpdateLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *SLoadbalancer, replaceTags bool, task taskman.ITask) error ValidateCreateLoadbalancerAclData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) RequestCreateLoadbalancerAcl(ctx context.Context, userCred mcclient.TokenCredential, lbacl *SCachedLoadbalancerAcl, task taskman.ITask) error @@ -167,6 +168,8 @@ type IDBInstanceDriver interface { IsDBInstanceNeedSecgroup() bool ValidateDBInstanceRecovery(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, backup *SDBInstanceBackup, input api.SDBInstanceRecoveryConfigInput) error + + RequestRemoteUpdateDBInstance(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, replaceTags bool, task taskman.ITask) error } type IElasticcacheDriver interface { @@ -198,6 +201,8 @@ type IElasticcacheDriver interface { RequestElasticcacheUpdateBackupPolicy(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error RequestSyncElasticcacheStatus(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, task taskman.ITask) error + + RequestRemoteUpdateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *SElasticcache, replaceTags bool, task taskman.ITask) error } type IElasticcacheAccount interface { diff --git a/pkg/compute/regiondrivers/base.go b/pkg/compute/regiondrivers/base.go index ae4969cb35..970e4f168d 100644 --- a/pkg/compute/regiondrivers/base.go +++ b/pkg/compute/regiondrivers/base.go @@ -52,6 +52,11 @@ func (self *SBaseRegionDriver) RequestSyncstatusLoadbalancer(ctx context.Context return fmt.Errorf("Not Implement RequestSyncstatusLoadbalancer") } +func (self *SBaseRegionDriver) RequestRemoteUpdateLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, replaceTags bool, task taskman.ITask) error { + // nil ops + return nil +} + func (self *SBaseRegionDriver) RequestDeleteLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, task taskman.ITask) error { return fmt.Errorf("Not Implement RequestDeleteLoadbalancer") } @@ -346,6 +351,11 @@ func (self *SBaseRegionDriver) ValidateDBInstanceRecovery(ctx context.Context, u return errors.Wrap(cloudprovider.ErrNotImplemented, "ValidateDBInstanceRecovery") } +func (self *SBaseRegionDriver) RequestRemoteUpdateDBInstance(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, replaceTags bool, task taskman.ITask) error { + // nil ops + return nil +} + func (self *SBaseRegionDriver) IsSupportedDBInstance() bool { return false } @@ -378,6 +388,11 @@ func (self *SBaseRegionDriver) RequestSyncElasticcacheStatus(ctx context.Context return fmt.Errorf("Not Implement RequestSyncElasticcacheStatus") } +func (self *SBaseRegionDriver) RequestRemoteUpdateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, replaceTags bool, task taskman.ITask) error { + // nil ops + return nil +} + func (self *SBaseRegionDriver) IsDBInstanceNeedSecgroup() bool { return false } diff --git a/pkg/compute/regiondrivers/managedvirtual.go b/pkg/compute/regiondrivers/managedvirtual.go index c2a7675125..1c4f804327 100644 --- a/pkg/compute/regiondrivers/managedvirtual.go +++ b/pkg/compute/regiondrivers/managedvirtual.go @@ -265,6 +265,36 @@ func (self *SManagedVirtualizationRegionDriver) RequestSyncstatusLoadbalancer(ct return nil } +func (self *SManagedVirtualizationRegionDriver) RequestRemoteUpdateLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, replaceTags bool, task taskman.ITask) error { + taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { + iRegion, err := lb.GetIRegion() + if err != nil { + return nil, err + } + iLoadbalancer, err := iRegion.GetILoadBalancerById(lb.ExternalId) + if err != nil { + return nil, err + } + tags, err := lb.GetAllUserMetadata() + if err != nil { + log.Errorf("GetAllUserMetadata fail %s", err) + } else { + err := iLoadbalancer.SetMetadata(tags, replaceTags) + if err != nil { + return nil, errors.Wrap(err, "iLoadbalancer.SetMetadata") + } + // sync back cloud metadata + err = models.SyncVirtualResourceMetadata(ctx, userCred, lb, iLoadbalancer) + if err != nil { + return nil, errors.Wrap(err, "syncVirtualResourceMetadata") + } + } + return nil, nil + }) + // nil ops + return nil +} + func (self *SManagedVirtualizationRegionDriver) RequestDeleteLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { if jsonutils.QueryBoolean(task.GetParams(), "purge", false) { @@ -2367,6 +2397,32 @@ func (self *SManagedVirtualizationRegionDriver) ValidateResetDBInstancePassword( return nil } +func (self *SManagedVirtualizationRegionDriver) RequestRemoteUpdateDBInstance(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, replaceTags bool, task taskman.ITask) error { + taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { + iRds, err := instance.GetIDBInstance() + if err != nil { + return nil, errors.Wrap(err, "instance.GetIDBInstance") + } + tags, err := instance.GetAllUserMetadata() + if err != nil { + log.Errorf("GetAllUserMetadata fail %s", err) + } else { + err := iRds.SetMetadata(tags, replaceTags) + if err != nil { + return nil, errors.Wrap(err, "iRds.SetMetadata") + } + // sync back cloud metadata + err = models.SyncVirtualResourceMetadata(ctx, userCred, instance, iRds) + if err != nil { + return nil, errors.Wrap(err, "syncVirtualResourceMetadata") + } + } + return nil, nil + }) + // nil ops + return nil +} + func (self *SManagedVirtualizationRegionDriver) RequestCreateElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential, eb *models.SElasticcacheBackup, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { _ec, err := db.FetchById(models.ElasticcacheManager, eb.ElasticcacheId) @@ -2736,3 +2792,31 @@ func (self *SManagedVirtualizationRegionDriver) RequestSyncElasticcacheStatus(ct }) return nil } + +func (self *SManagedVirtualizationRegionDriver) RequestRemoteUpdateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, replaceTags bool, task taskman.ITask) error { + taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { + iRegion, err := elasticcache.GetIRegion() + if err != nil { + return nil, errors.Wrap(err, "elasticcache.GetIRegion") + } + + iElasticcache, err := iRegion.GetIElasticcacheById(elasticcache.ExternalId) + tags, err := elasticcache.GetAllUserMetadata() + if err != nil { + log.Errorf("GetAllUserMetadata fail %s", err) + } else { + err := iElasticcache.SetMetadata(tags, replaceTags) + if err != nil { + return nil, errors.Wrap(err, "iElasticcache.SetMetadata") + } + // sync back cloud metadata + err = models.SyncVirtualResourceMetadata(ctx, userCred, elasticcache, iElasticcache) + if err != nil { + return nil, errors.Wrap(err, "syncVirtualResourceMetadata") + } + } + return nil, nil + }) + // nil ops + return nil +} diff --git a/pkg/compute/tasks/dbinstance_remote_update_task.go b/pkg/compute/tasks/dbinstance_remote_update_task.go new file mode 100644 index 0000000000..28f1f7efa6 --- /dev/null +++ b/pkg/compute/tasks/dbinstance_remote_update_task.go @@ -0,0 +1,56 @@ +// 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 tasks + +import ( + "context" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudcommon/db" + "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" + "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient" + "yunion.io/x/onecloud/pkg/compute/models" + "yunion.io/x/onecloud/pkg/util/logclient" +) + +type DBInstanceRemoteUpdateTask struct { + SGuestBaseTask +} + +func init() { + taskman.RegisterTask(DBInstanceRemoteUpdateTask{}) +} + +func (self *DBInstanceRemoteUpdateTask) taskFail(ctx context.Context, lb *models.SDBInstance, reason jsonutils.JSONObject) { + logclient.AddActionLogWithStartable(self, lb, logclient.ACT_ENABLE, reason, self.UserCred, false) + notifyclient.NotifySystemErrorWithCtx(ctx, lb.Id, lb.Name, api.LB_STATUS_DISABLED, reason.String()) + self.SetStageFailed(ctx, reason) +} + +func (self *DBInstanceRemoteUpdateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { + instance := obj.(*models.SDBInstance) + self.SetStage("OnRemoteUpdateComplete", nil) + replaceTags := jsonutils.QueryBoolean(self.Params, "replace_tags", false) + + if err := instance.GetRegion().GetDriver().RequestRemoteUpdateDBInstance(ctx, self.GetUserCred(), instance, replaceTags, self); err != nil { + self.taskFail(ctx, instance, jsonutils.Marshal(err)) + } +} + +func (self *DBInstanceRemoteUpdateTask) OnRemoteUpdateComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { + self.SetStageComplete(ctx, nil) +} diff --git a/pkg/compute/tasks/elasticcache_remote_update_task.go b/pkg/compute/tasks/elasticcache_remote_update_task.go new file mode 100644 index 0000000000..f9fc4f6921 --- /dev/null +++ b/pkg/compute/tasks/elasticcache_remote_update_task.go @@ -0,0 +1,62 @@ +// 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 tasks + +import ( + "context" + "fmt" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudcommon/db" + "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" + "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient" + "yunion.io/x/onecloud/pkg/compute/models" + "yunion.io/x/onecloud/pkg/util/logclient" +) + +type ElasticcacheRemoteUpdateTask struct { + SGuestBaseTask +} + +func init() { + taskman.RegisterTask(ElasticcacheRemoteUpdateTask{}) +} + +func (self *ElasticcacheRemoteUpdateTask) taskFail(ctx context.Context, elasticcache *models.SElasticcache, reason jsonutils.JSONObject) { + logclient.AddActionLogWithStartable(self, elasticcache, logclient.ACT_ENABLE, reason, self.UserCred, false) + notifyclient.NotifySystemErrorWithCtx(ctx, elasticcache.Id, elasticcache.Name, api.LB_STATUS_DISABLED, reason.String()) + self.SetStageFailed(ctx, reason) +} + +func (self *ElasticcacheRemoteUpdateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { + ec := obj.(*models.SElasticcache) + region := ec.GetRegion() + if region == nil { + self.taskFail(ctx, ec, jsonutils.NewString(fmt.Sprintf("failed to find region for elastic cache %s", ec.GetName()))) + return + } + self.SetStage("OnRemoteUpdateComplete", nil) + replaceTags := jsonutils.QueryBoolean(self.Params, "replace_tags", false) + + if err := region.GetDriver().RequestRemoteUpdateElasticcache(ctx, self.GetUserCred(), ec, replaceTags, self); err != nil { + self.taskFail(ctx, ec, jsonutils.Marshal(err)) + } +} + +func (self *ElasticcacheRemoteUpdateTask) OnRemoteUpdateComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { + self.SetStageComplete(ctx, nil) +} diff --git a/pkg/compute/tasks/loadbalancer_remote_update_task.go b/pkg/compute/tasks/loadbalancer_remote_update_task.go new file mode 100644 index 0000000000..bac29970d8 --- /dev/null +++ b/pkg/compute/tasks/loadbalancer_remote_update_task.go @@ -0,0 +1,62 @@ +// 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 tasks + +import ( + "context" + "fmt" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudcommon/db" + "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" + "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient" + "yunion.io/x/onecloud/pkg/compute/models" + "yunion.io/x/onecloud/pkg/util/logclient" +) + +type LoadbalancerRemoteUpdateTask struct { + SGuestBaseTask +} + +func init() { + taskman.RegisterTask(LoadbalancerRemoteUpdateTask{}) +} + +func (self *LoadbalancerRemoteUpdateTask) taskFail(ctx context.Context, lb *models.SLoadbalancer, reason jsonutils.JSONObject) { + logclient.AddActionLogWithStartable(self, lb, logclient.ACT_ENABLE, reason, self.UserCred, false) + notifyclient.NotifySystemErrorWithCtx(ctx, lb.Id, lb.Name, api.LB_STATUS_DISABLED, reason.String()) + self.SetStageFailed(ctx, reason) +} + +func (self *LoadbalancerRemoteUpdateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { + lb := obj.(*models.SLoadbalancer) + region := lb.GetRegion() + if region == nil { + self.taskFail(ctx, lb, jsonutils.NewString(fmt.Sprintf("failed to find region for lb %s", lb.Name))) + return + } + self.SetStage("OnRemoteUpdateComplete", nil) + replaceTags := jsonutils.QueryBoolean(self.Params, "replace_tags", false) + + if err := region.GetDriver().RequestRemoteUpdateLoadbalancer(ctx, self.GetUserCred(), lb, replaceTags, self); err != nil { + self.taskFail(ctx, lb, jsonutils.Marshal(err)) + } +} + +func (self *LoadbalancerRemoteUpdateTask) OnRemoteUpdateComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) { + self.SetStageComplete(ctx, nil) +} diff --git a/pkg/mcclient/options/elasticcache.go b/pkg/mcclient/options/elasticcache.go index 481039f3c4..901acc640e 100644 --- a/pkg/mcclient/options/elasticcache.go +++ b/pkg/mcclient/options/elasticcache.go @@ -14,6 +14,8 @@ package options +import computeapi "yunion.io/x/onecloud/pkg/apis/compute" + type ElasticCacheCreateOptions struct { NAME string Manager string @@ -63,3 +65,8 @@ type ElasticCacheParameterUpdateOptions struct { type ElasticCacheIdOptions struct { ID string } + +type ElasticCacheRemoteUpdateOptions struct { + ID string `json:"-"` + computeapi.ElasticcacheRemoteUpdateInput +} diff --git a/pkg/mcclient/options/loadbalancers.go b/pkg/mcclient/options/loadbalancers.go index 1bbbcfcc76..164fdf2e2b 100644 --- a/pkg/mcclient/options/loadbalancers.go +++ b/pkg/mcclient/options/loadbalancers.go @@ -14,6 +14,10 @@ package options +import ( + computeapi "yunion.io/x/onecloud/pkg/apis/compute" +) + type LoadbalancerCreateOptions struct { NAME string Network string @@ -26,6 +30,7 @@ type LoadbalancerCreateOptions struct { Zone1 string `json:"zone_1" help:"slave zone 1"` Cluster string `json:"cluster_id"` Manager string + Meta map[string]string `json:"__meta__"` } type LoadbalancerGetOptions struct { @@ -72,3 +77,8 @@ type LoadbalancerActionSyncStatusOptions struct { type LoadbalancerIdOptions struct { ID string `json:"-"` } + +type LoadbalancerRemoteUpdateOptions struct { + ID string `json:"-"` + computeapi.LoadbalancerRemoteUpdateInput +} diff --git a/pkg/multicloud/aliyun/dbinstance.go b/pkg/multicloud/aliyun/dbinstance.go index ca49a430e7..23e6c05579 100644 --- a/pkg/multicloud/aliyun/dbinstance.go +++ b/pkg/multicloud/aliyun/dbinstance.go @@ -775,3 +775,21 @@ func (region *SRegion) RenewDBInstance(instanceId string, bc billing.SBillingCyc _, err := region.rdsRequest("RenewInstance", params) return err } + +func (rds *SDBInstance) GetMetadata() *jsonutils.JSONDict { + data := jsonutils.NewDict() + tags, err := rds.region.ListResourceTags("rds", "INSTANCE", []string{rds.GetId()}) + if err != nil { + log.Errorf(`[err:%s]rds.region.FetchResourceTags("slb", "instance", []string{rds.GetId()})`, err.Error()) + return nil + } + if _, ok := tags[rds.GetId()]; !ok { + return nil + } + data.Update(jsonutils.Marshal(tags[rds.GetId()])) + return data +} + +func (rds *SDBInstance) SetMetadata(tags map[string]string, replace bool) error { + return rds.region.SetResourceTags("rds", "INSTANCE", []string{rds.GetId()}, tags, replace) +} diff --git a/pkg/multicloud/aliyun/elasticcache_instance.go b/pkg/multicloud/aliyun/elasticcache_instance.go index cc183303ad..f72b3d7e62 100644 --- a/pkg/multicloud/aliyun/elasticcache_instance.go +++ b/pkg/multicloud/aliyun/elasticcache_instance.go @@ -911,3 +911,21 @@ func (self *SElasticcache) GetICloudElasticcacheBackup(backupId string) (cloudpr return nil, cloudprovider.ErrNotFound } + +func (instance *SElasticcache) GetMetadata() *jsonutils.JSONDict { + data := jsonutils.NewDict() + tags, err := instance.region.ListResourceTags("kvs", "INSTANCE", []string{instance.GetId()}) + if err != nil { + log.Errorf(`[err:%s]instance.region.FetchResourceTags("kvs", "instance", []string{instance.GetId()})`, err.Error()) + return nil + } + if _, ok := tags[instance.GetId()]; !ok { + return nil + } + data.Update(jsonutils.Marshal(tags[instance.GetId()])) + return data +} + +func (instance *SElasticcache) SetMetadata(tags map[string]string, replace bool) error { + return instance.region.SetResourceTags("kvs", "INSTANCE", []string{instance.GetId()}, tags, replace) +} diff --git a/pkg/multicloud/aliyun/instance.go b/pkg/multicloud/aliyun/instance.go index f5f91bcd8d..58506d12ea 100644 --- a/pkg/multicloud/aliyun/instance.go +++ b/pkg/multicloud/aliyun/instance.go @@ -1077,5 +1077,5 @@ func (self *SInstance) SetAutoRenew(autoRenew bool) error { } func (self *SInstance) SetMetadata(tags map[string]string, replace bool) error { - return self.host.zone.region.SetResourceTags("instance", []string{self.InstanceId}, tags, replace) + return self.host.zone.region.SetResourceTags("ecs", "instance", []string{self.InstanceId}, tags, replace) } diff --git a/pkg/multicloud/aliyun/loadbalancer.go b/pkg/multicloud/aliyun/loadbalancer.go index ca641ec053..3484ebb51d 100644 --- a/pkg/multicloud/aliyun/loadbalancer.go +++ b/pkg/multicloud/aliyun/loadbalancer.go @@ -103,7 +103,17 @@ func (lb *SLoadbalancer) GetStatus() string { } func (lb *SLoadbalancer) GetMetadata() *jsonutils.JSONDict { - return nil + data := jsonutils.NewDict() + tags, err := lb.region.ListResourceTags("slb", "instance", []string{lb.GetId()}) + if err != nil { + log.Errorf(`[err:%s]lb.region.FetchResourceTags("slb", "instance", []string{lb.GetId()})`, err.Error()) + return nil + } + if _, ok := tags[lb.GetId()]; !ok { + return nil + } + data.Update(jsonutils.Marshal(tags[lb.GetId()])) + return data } func (lb *SLoadbalancer) GetAddress() string { @@ -396,3 +406,7 @@ func (lb *SLoadbalancer) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoad func (lb *SLoadbalancer) GetProjectId() string { return lb.ResourceGroupId } + +func (lb *SLoadbalancer) SetMetadata(tags map[string]string, replace bool) error { + return lb.region.SetResourceTags("slb", "instance", []string{lb.LoadBalancerId}, tags, replace) +} diff --git a/pkg/multicloud/aliyun/region.go b/pkg/multicloud/aliyun/region.go index d5f2bca868..b87e052605 100644 --- a/pkg/multicloud/aliyun/region.go +++ b/pkg/multicloud/aliyun/region.go @@ -140,6 +140,21 @@ func (self *SRegion) kvsRequest(action string, params map[string]string) (jsonut return jsonRequest(client, "r-kvstore.aliyuncs.com", ALIYUN_API_VERSION_KVS, action, params, self.client.debug) } +func (self *SRegion) tagRequest(serviceType string, action string, params map[string]string) (jsonutils.JSONObject, error) { + switch serviceType { + case "ecs": + return self.ecsRequest(action, params) + case "rds": + return self.rdsRequest(action, params) + case "slb": + return self.lbRequest(action, params) + case "kvs": + return self.kvsRequest(action, params) + default: + return nil, errors.Wrapf(errors.ErrNotSupported, "not support %service tag", serviceType) + } +} + type LBRegion struct { RegionEndpoint string RegionId string diff --git a/pkg/multicloud/aliyun/resource_tags.go b/pkg/multicloud/aliyun/resource_tags.go index 8155385f69..8d41998243 100644 --- a/pkg/multicloud/aliyun/resource_tags.go +++ b/pkg/multicloud/aliyun/resource_tags.go @@ -30,7 +30,7 @@ type STagResource struct { TagKey string `json:"TagKey"` } -func (self *SRegion) rawListTagResources(resourceType string, resIds []string, token string) ([]STagResource, string, error) { +func (self *SRegion) rawListTagResources(serviceType string, resourceType string, resIds []string, token string) ([]STagResource, string, error) { if len(resIds) > 50 { return nil, "", errors.Wrap(cloudprovider.ErrNotSupported, "resource count exceed 50 for one request") } @@ -42,9 +42,9 @@ func (self *SRegion) rawListTagResources(resourceType string, resIds []string, t if len(token) != 0 { params["NextToken"] = token } - ret, err := self.ecsRequest("ListTagResources", params) + ret, err := self.tagRequest(serviceType, "ListTagResources", params) if err != nil { - return nil, "", errors.Wrapf(err, `self.ecsRequest("ListTagResources", %s)`, jsonutils.Marshal(params).String()) + return nil, "", errors.Wrapf(err, `self.tagRequest(%s,"ListTagResources", %s)`, serviceType, jsonutils.Marshal(params).String()) } tagResources := []STagResource{} err = ret.Unmarshal(&tagResources, "TagResources", "TagResource") @@ -85,14 +85,14 @@ func splitTags(tags map[string]string, stride int) []map[string]string { return tagsGroups } -func (self *SRegion) ListResourceTags(resourceType string, resIds []string) (map[string]*map[string]string, error) { +func (self *SRegion) ListResourceTags(serviceType string, resourceType string, resIds []string) (map[string]*map[string]string, error) { tags := make(map[string]*map[string]string) tagReources := []STagResource{} nextToken := "" resIdsGroups := splitStringSlice(resIds, 50) for i := range resIdsGroups { for { - _tagResource, nextToken, err := self.rawListTagResources(resourceType, resIdsGroups[i], nextToken) + _tagResource, nextToken, err := self.rawListTagResources(serviceType, resourceType, resIdsGroups[i], nextToken) if err != nil { return nil, errors.Wrapf(err, "self.rawListTagResources(%s,%s,%s)", resourceType, resIds, nextToken) } @@ -117,7 +117,7 @@ func (self *SRegion) ListResourceTags(resourceType string, resIds []string) (map return tags, nil } -func (self *SRegion) rawTagResources(resourceType string, resIds []string, tags map[string]string) error { +func (self *SRegion) rawTagResources(serviceType string, resourceType string, resIds []string, tags map[string]string) error { if len(resIds) > 50 { return errors.Wrap(cloudprovider.ErrNotSupported, "resource count exceed 50 for one request") } @@ -135,14 +135,14 @@ func (self *SRegion) rawTagResources(resourceType string, resIds []string, tags params[fmt.Sprintf("Tag.%d.Value", i+1)] = v i++ } - _, err := self.ecsRequest("TagResources", params) + _, err := self.tagRequest(serviceType, "TagResources", params) if err != nil { - return errors.Wrapf(err, `self.ecsRequest("TagResources", %s)`, jsonutils.Marshal(params).String()) + return errors.Wrapf(err, `self.tagRequest(%s,"TagResources", %s)`, serviceType, jsonutils.Marshal(params).String()) } return nil } -func (self *SRegion) TagResources(resourceType string, resIds []string, tags map[string]string) error { +func (self *SRegion) TagResources(serviceType string, resourceType string, resIds []string, tags map[string]string) error { if len(resIds) == 0 || len(tags) == 0 { return nil } @@ -150,7 +150,7 @@ func (self *SRegion) TagResources(resourceType string, resIds []string, tags map tagsGroups := splitTags(tags, 20) for i := range resIdsGroups { for j := range tagsGroups { - err := self.rawTagResources(resourceType, resIdsGroups[i], tagsGroups[j]) + err := self.rawTagResources(serviceType, resourceType, resIdsGroups[i], tagsGroups[j]) if err != nil { return errors.Wrapf(err, "self.rawTagResources(resourceType, resIdsGroups[i], tagsGroups[i])") } @@ -159,7 +159,7 @@ func (self *SRegion) TagResources(resourceType string, resIds []string, tags map return nil } -func (self *SRegion) rawUntagResources(resourceType string, resIds []string, tags []string) error { +func (self *SRegion) rawUntagResources(serviceType string, resourceType string, resIds []string, tags []string) error { if len(resIds) > 50 { return errors.Wrap(cloudprovider.ErrNotSupported, "resource count exceed 50 for one request") } @@ -174,14 +174,14 @@ func (self *SRegion) rawUntagResources(resourceType string, resIds []string, tag for i := range tags { params[fmt.Sprintf("TagKey.%d", i+1)] = tags[i] } - _, err := self.ecsRequest("UntagResources", params) + _, err := self.tagRequest(serviceType, "UntagResources", params) if err != nil { - return errors.Wrapf(err, `self.ecsRequest("UntagResources", %s)`, jsonutils.Marshal(params).String()) + return errors.Wrapf(err, `self.tagRequest(%s,"UntagResources", %s)`, serviceType, jsonutils.Marshal(params).String()) } return nil } -func (self *SRegion) UntagResources(resourceType string, resIds []string, tags []string) error { +func (self *SRegion) UntagResources(serviceType string, resourceType string, resIds []string, tags []string) error { if len(resIds) == 0 || len(tags) == 0 { return nil } @@ -189,7 +189,7 @@ func (self *SRegion) UntagResources(resourceType string, resIds []string, tags [ tagsGroups := splitStringSlice(tags, 20) for i := range resIdsGroups { for j := range tagsGroups { - err := self.rawUntagResources(resourceType, resIdsGroups[i], tagsGroups[j]) + err := self.rawUntagResources(serviceType, resourceType, resIdsGroups[i], tagsGroups[j]) if err != nil { return errors.Wrapf(err, "self.rawTagResources(resourceType, resIdsGroups[i], tagsGroups[i])") } @@ -198,15 +198,15 @@ func (self *SRegion) UntagResources(resourceType string, resIds []string, tags [ return nil } -func (self *SRegion) SetResourceTags(resourceType string, resIds []string, tags map[string]string, replace bool) error { - oldTags, err := self.ListResourceTags(resourceType, resIds) +func (self *SRegion) SetResourceTags(serviceType string, resourceType string, resIds []string, tags map[string]string, replace bool) error { + oldTags, err := self.ListResourceTags(serviceType, resourceType, resIds) if err != nil { return errors.Wrapf(err, "self.ListResourceTags(%s,%s)", resourceType, resIds) } for i := range resIds { _, ok := oldTags[resIds[i]] if !ok { - err := self.TagResources(resourceType, []string{resIds[i]}, tags) + err := self.TagResources(serviceType, resourceType, []string{resIds[i]}, tags) if err != nil { return errors.Wrap(err, "self.TagResources(resourceType, []string{resIds[i]}, tags)") } @@ -230,11 +230,11 @@ func (self *SRegion) SetResourceTags(resourceType string, resIds []string, tags } } } - err := self.UntagResources(resourceType, []string{resIds[i]}, delTags) + err := self.UntagResources(serviceType, resourceType, []string{resIds[i]}, delTags) if err != nil { return errors.Wrap(err, "self.UntagResources(resourceType, []string{resIds[i]}, delTags)") } - err = self.TagResources(resourceType, []string{resIds[i]}, addTags) + err = self.TagResources(serviceType, resourceType, []string{resIds[i]}, addTags) if err != nil { return errors.Wrap(err, "self.TagResources(resourceType, []string{resIds[i]}, addTags)") } diff --git a/pkg/multicloud/aliyun/shell/resource_tag.go b/pkg/multicloud/aliyun/shell/resource_tag.go index 950ec8cc07..a816a97909 100644 --- a/pkg/multicloud/aliyun/shell/resource_tag.go +++ b/pkg/multicloud/aliyun/shell/resource_tag.go @@ -24,11 +24,12 @@ import ( func init() { type TagGetOptions struct { + SERVICE string `help:"service, eg. ecs"` RESTYPE string `help:"resource type, eg. instance"` ID []string `help:"resource Id, eg. ins-123xxx"` } shellutils.R(&TagGetOptions{}, "tag-show", "show tag of a specific resource", func(cli *aliyun.SRegion, args *TagGetOptions) error { - tags, err := cli.ListResourceTags(args.RESTYPE, args.ID) + tags, err := cli.ListResourceTags(args.SERVICE, args.RESTYPE, args.ID) if err != nil { return err } @@ -49,7 +50,7 @@ func init() { parts := strings.Split(t, ":") tags[parts[0]] = parts[1] } - err := cli.SetResourceTags(args.RESTYPE, args.ID, tags, args.Replace) + err := cli.SetResourceTags(args.SERVICE, args.RESTYPE, args.ID, tags, args.Replace) if err != nil { return err } diff --git a/pkg/multicloud/aws/loadbalancer.go b/pkg/multicloud/aws/loadbalancer.go index 45c193ec39..386669a085 100644 --- a/pkg/multicloud/aws/loadbalancer.go +++ b/pkg/multicloud/aws/loadbalancer.go @@ -454,3 +454,7 @@ func (self *SRegion) CreateElbBackendgroup(group *cloudprovider.SLoadbalancerBac return nil, fmt.Errorf("CreateElbBackendgroup error: %#v", backendgroups) } + +func (self *SElb) SetMetadata(tags map[string]string, replace bool) error { + return cloudprovider.ErrNotSupported +} diff --git a/pkg/multicloud/dbinstance_base.go b/pkg/multicloud/dbinstance_base.go index 5f7fac739c..386dcb2fd2 100644 --- a/pkg/multicloud/dbinstance_base.go +++ b/pkg/multicloud/dbinstance_base.go @@ -68,6 +68,10 @@ func (instance *SDBInstanceBase) Delete() error { return errors.Wrapf(cloudprovider.ErrNotImplemented, "Delete") } +func (instance *SDBInstanceBase) SetMetadata(tags map[string]string, replace bool) error { + return cloudprovider.ErrNotImplemented +} + func (instance *SDBInstanceBase) GetMasterInstanceId() string { return "" } diff --git a/pkg/multicloud/huawei/elasticcache_instance.go b/pkg/multicloud/huawei/elasticcache_instance.go index ceaada6924..8b64ca37b6 100644 --- a/pkg/multicloud/huawei/elasticcache_instance.go +++ b/pkg/multicloud/huawei/elasticcache_instance.go @@ -734,3 +734,7 @@ func (self *SElasticcache) GetICloudElasticcacheBackup(backupId string) (cloudpr return nil, cloudprovider.ErrNotFound } + +func (instance *SElasticcache) SetMetadata(tags map[string]string, replace bool) error { + return cloudprovider.ErrNotImplemented +} diff --git a/pkg/multicloud/huawei/loadbalancer.go b/pkg/multicloud/huawei/loadbalancer.go index 53a48f45a6..3c2bfcfbae 100644 --- a/pkg/multicloud/huawei/loadbalancer.go +++ b/pkg/multicloud/huawei/loadbalancer.go @@ -540,3 +540,7 @@ func (self *SRegion) UpdateLoadBalancerHealthCheck(healthCheckID string, healthC func (self *SRegion) DeleteLoadbalancerHealthCheck(healthCheckID string) error { return DoDelete(self.ecsClient.ElbHealthCheck.Delete, healthCheckID, nil, nil) } + +func (self *SLoadbalancer) SetMetadata(tags map[string]string, replace bool) error { + return cloudprovider.ErrNotSupported +} diff --git a/pkg/multicloud/openstack/loadbalbacer.go b/pkg/multicloud/openstack/loadbalbacer.go index 2c92b1dc78..5b7c0f1a8f 100644 --- a/pkg/multicloud/openstack/loadbalbacer.go +++ b/pkg/multicloud/openstack/loadbalbacer.go @@ -487,3 +487,7 @@ func (lb *SLoadbalancer) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoad func (lb *SLoadbalancer) GetProjectId() string { return lb.ProjectID } + +func (self *SLoadbalancer) SetMetadata(tags map[string]string, replace bool) error { + return cloudprovider.ErrNotSupported +} diff --git a/pkg/multicloud/qcloud/loadbalancer.go b/pkg/multicloud/qcloud/loadbalancer.go index c1a6ecab8b..c4c09d74a9 100644 --- a/pkg/multicloud/qcloud/loadbalancer.go +++ b/pkg/multicloud/qcloud/loadbalancer.go @@ -270,7 +270,20 @@ func (self *SLoadbalancer) GetMetadata() *jsonutils.JSONDict { meta.Add(jsonutils.NewInt(self.OpenBGP), "OpenBGP") meta.Add(jsonutils.NewString(self.Domain), "Domain") meta.Add(jsonutils.NewInt(self.ProjectID), "ProjectID") - + tags, err := self.region.FetchResourceTags("clb", "clb", []string{self.GetId()}) + if err != nil { + log.Errorf(`[err:%s]self.region.FetchResourceTags("clb", "clb", []string{self.GetId()})`, err.Error()) + return nil + } + if _, ok := tags[self.GetId()]; !ok { + return meta + } + resourceTag := tags[self.GetId()] + if resourceTag != nil { + for k, v := range *resourceTag { + meta.Add(jsonutils.NewString(v), k) + } + } return meta } @@ -645,3 +658,7 @@ func (self *SRegion) WaitLBTaskSuccess(requestId string, interval time.Duration, func (self *SLoadbalancer) GetProjectId() string { return strconv.Itoa(int(self.ProjectID)) } + +func (self *SLoadbalancer) SetMetadata(tags map[string]string, replace bool) error { + return self.region.SetResourceTags("clb", "clb", []string{self.LoadBalancerID}, tags, replace) +} diff --git a/pkg/multicloud/qcloud/rds_mysql.go b/pkg/multicloud/qcloud/rds_mysql.go index fbf187ba04..70b2caa8aa 100644 --- a/pkg/multicloud/qcloud/rds_mysql.go +++ b/pkg/multicloud/qcloud/rds_mysql.go @@ -809,3 +809,26 @@ func (self *SMySQLInstance) CreateIBackup(opts *cloudprovider.SDBInstanceBackupC } return self.region.CreateMySQLBackup(self.InstanceId, tables) } + +func (self *SMySQLInstance) GetMetadata() *jsonutils.JSONDict { + meta := jsonutils.NewDict() + tags, err := self.region.FetchResourceTags("cdb", "instanceId", []string{self.GetId()}) + if err != nil { + log.Errorf(`[err:%s]self.region.FetchResourceTags("cdb", "instanceId", []string{self.GetId()})`, err.Error()) + return nil + } + if _, ok := tags[self.GetId()]; !ok { + return meta + } + resourceTag := tags[self.GetId()] + if resourceTag != nil { + for k, v := range *resourceTag { + meta.Add(jsonutils.NewString(v), k) + } + } + return meta +} + +func (self *SMySQLInstance) SetMetadata(tags map[string]string, replace bool) error { + return self.region.SetResourceTags("cdb", "instanceId", []string{self.InstanceId}, tags, replace) +}