// 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 regiondrivers import ( "context" "database/sql" "fmt" "strings" "time" "yunion.io/x/cloudmux/pkg/cloudprovider" "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/pkg/errors" "yunion.io/x/pkg/gotypes" "yunion.io/x/pkg/util/billing" "yunion.io/x/pkg/util/netutils" "yunion.io/x/pkg/util/regutils" "yunion.io/x/pkg/util/secrules" "yunion.io/x/pkg/utils" "yunion.io/x/sqlchemy" "yunion.io/x/onecloud/pkg/apis" billing_api "yunion.io/x/onecloud/pkg/apis/billing" 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/cloudcommon/db/taskman" "yunion.io/x/onecloud/pkg/cloudcommon/validators" "yunion.io/x/onecloud/pkg/compute/models" "yunion.io/x/onecloud/pkg/compute/sshkeys" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/util/logclient" "yunion.io/x/onecloud/pkg/util/seclib2" ) type SManagedVirtualizationRegionDriver struct { SVirtualizationRegionDriver } func (self *SManagedVirtualizationRegionDriver) IsSupportedElasticcacheSecgroup() bool { return false } func (self *SManagedVirtualizationRegionDriver) GetMaxElasticcacheSecurityGroupCount() int { return 0 } func (self *SManagedVirtualizationRegionDriver) ValidateCreateLoadbalancerData(ctx context.Context, userCred mcclient.TokenCredential, owerId mcclient.IIdentityProvider, input *api.LoadbalancerCreateInput) (*api.LoadbalancerCreateInput, error) { if len(input.ManagerId) == 0 { return nil, httperrors.NewMissingParameterError("manager_id") } return input, nil } func (self *SManagedVirtualizationRegionDriver) ValidateManagerId(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { if managerId, _ := data.GetString("manager_id"); len(managerId) == 0 { return nil, httperrors.NewMissingParameterError("manager") } return data, nil } func (self *SManagedVirtualizationRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { return self.ValidateManagerId(ctx, userCred, data) } func (self *SManagedVirtualizationRegionDriver) ValidateCreateLoadbalancerBackendData(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, lbbg *models.SLoadbalancerBackendGroup, input *api.LoadbalancerBackendCreateInput) (*api.LoadbalancerBackendCreateInput, error) { if input.BackendType != api.LB_BACKEND_GUEST { return nil, httperrors.NewUnsupportOperationError("internal error: unexpected backend type %s", input.BackendType) } return input, nil } func (self *SManagedVirtualizationRegionDriver) ValidateUpdateLoadbalancerBackendData(ctx context.Context, userCred mcclient.TokenCredential, lbbg *models.SLoadbalancerBackendGroup, input *api.LoadbalancerBackendUpdateInput) (*api.LoadbalancerBackendUpdateInput, error) { return input, nil } func (self *SManagedVirtualizationRegionDriver) ValidateCreateLoadbalancerBackendGroupData(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, input *api.LoadbalancerBackendGroupCreateInput) (*api.LoadbalancerBackendGroupCreateInput, error) { for _, backend := range input.Backends { if len(backend.ExternalId) == 0 && backend.BackendType == api.LB_BACKEND_GUEST { return nil, httperrors.NewInputParameterError("invalid guest %s", backend.Name) } } return input, nil } func (self *SManagedVirtualizationRegionDriver) IsSupportLoadbalancerListenerRuleRedirect() bool { return false } func validateUniqueById(ctx context.Context, userCred mcclient.TokenCredential, man db.IResourceModelManager, id string) error { q := man.Query().Equals("id", id) q = man.FilterByOwner(ctx, q, man, userCred, userCred, man.NamespaceScope()) count, err := q.CountWithError() if err != nil { if err == sql.ErrNoRows { return httperrors.NewResourceNotFoundError("failed to find %s %s", man.Keyword(), id) } return httperrors.NewGeneralError(err) } if count > 1 { return httperrors.NewDuplicateResourceError("%s", id) } return nil } func (self *SManagedVirtualizationRegionDriver) ValidateUpdateLoadbalancerListenerData(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, input *api.LoadbalancerListenerUpdateInput) (*api.LoadbalancerListenerUpdateInput, error) { return input, nil } func (self *SManagedVirtualizationRegionDriver) GetBackendStatusForAdd() []string { return []string{api.VM_RUNNING} } func (self *SManagedVirtualizationRegionDriver) RequestCreateLoadbalancerInstance(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, input *api.LoadbalancerCreateInput, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iRegion, err := lb.GetIRegion(ctx) if err != nil { return nil, errors.Wrapf(err, "GetIRegion") } params := &cloudprovider.SLoadbalancerCreateOptions{ Name: lb.Name, Desc: lb.Description, Address: lb.Address, AddressType: lb.AddressType, ChargeType: string(lb.ChargeType), EgressMbps: lb.EgressMbps, LoadbalancerSpec: lb.LoadbalancerSpec, } params.Tags, _ = lb.GetAllUserMetadata() if len(input.EipId) > 0 { eipObj, err := models.ElasticipManager.FetchById(input.EipId) if err != nil { return nil, errors.Wrapf(err, "eip.FetchById(%s)", input.EipId) } eip := eipObj.(*models.SElasticip) params.EipId = eip.ExternalId } if len(lb.ZoneId) > 0 { zone, err := lb.GetZone() if err != nil { return nil, errors.Wrapf(err, "GetZone") } iZone, err := iRegion.GetIZoneById(zone.ExternalId) if err != nil { return nil, errors.Wrapf(err, "GetIZoneById(%s)", zone.ExternalId) } params.ZoneId = iZone.GetId() } if len(lb.Zone1) > 0 { z1 := models.ZoneManager.FetchZoneById(lb.Zone1) if z1 == nil { return nil, fmt.Errorf("failed to find zone 1 for lb %s", lb.Name) } iZone, err := iRegion.GetIZoneById(z1.ExternalId) if err != nil { return nil, errors.Wrap(err, "GetIZoneById") } params.SlaveZoneId = iZone.GetId() } if len(lb.VpcId) > 0 { vpc, err := lb.GetVpc() if err != nil { return nil, errors.Wrapf(err, "GetVpc") } params.VpcId = vpc.ExternalId } networks := []string{input.NetworkId} networks = append(networks, input.Networks...) for i := range networks { if len(networks[i]) > 0 { netObj, err := validators.ValidateModel(ctx, userCred, models.NetworkManager, &networks[i]) if err != nil { return nil, err } network := netObj.(*models.SNetwork) if !utils.IsInStringArray(network.ExternalId, params.NetworkIds) { params.NetworkIds = append(params.NetworkIds, network.ExternalId) } } } manager := lb.GetCloudprovider() params.ProjectId, err = manager.SyncProject(ctx, userCred, lb.ProjectId) if err != nil { if errors.Cause(err) != cloudprovider.ErrNotSupported && errors.Cause(err) != cloudprovider.ErrNotImplemented { logclient.AddSimpleActionLog(lb, logclient.ACT_SYNC_CLOUD_PROJECT, err, userCred, false) } } log.Debugf("create lb with params: %s", jsonutils.Marshal(params).String()) iLoadbalancer, err := iRegion.CreateILoadBalancer(params) if err != nil { return nil, errors.Wrapf(err, "CreateILoadBalancer") } err = db.SetExternalId(lb, userCred, iLoadbalancer.GetGlobalId()) if err != nil { return nil, errors.Wrapf(err, "SetExternalId") } //wait async create result err = cloudprovider.WaitMultiStatus(iLoadbalancer, []string{api.LB_STATUS_ENABLED, api.LB_STATUS_UNKNOWN}, 10*time.Second, 8*time.Minute) if err != nil { return nil, errors.Wrap(err, "cloudprovider.WaitMultiStatus") } err = lb.SyncWithCloudLoadbalancer(ctx, userCred, iLoadbalancer, lb.GetCloudprovider()) if err != nil { return nil, errors.Wrapf(err, "SyncWithCloudLoadbalancer") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestStartLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iRegion, err := lb.GetIRegion(ctx) if err != nil { return nil, err } iLoadbalancer, err := iRegion.GetILoadBalancerById(lb.ExternalId) if err != nil { return nil, err } return nil, iLoadbalancer.Start() }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestStopLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iRegion, err := lb.GetIRegion(ctx) if err != nil { return nil, err } iLoadbalancer, err := iRegion.GetILoadBalancerById(lb.ExternalId) if err != nil { return nil, err } return nil, iLoadbalancer.Stop() }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestSyncstatusLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iLb, err := lb.GetILoadbalancer(ctx) if err != nil { return nil, errors.Wrapf(err, "GetILoadbalancer") } provider := lb.GetCloudprovider() return nil, lb.SyncWithCloudLoadbalancer(ctx, userCred, iLb, provider) }) 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) { iLb, err := lb.GetILoadbalancer(ctx) if err != nil { return nil, errors.Wrapf(err, "GetILoadbalancer") } oldTags, err := iLb.GetTags() if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } return nil, errors.Wrap(err, "iLoadbalancer.GetTags()") } tags, err := lb.GetAllUserMetadata() if err != nil { return nil, errors.Wrapf(err, "lb.GetAllUserMetadata") } tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags} err = cloudprovider.SetTags(ctx, iLb, lb.ManagerId, tags, replaceTags) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } logclient.AddActionLogWithStartable(task, lb, logclient.ACT_UPDATE_TAGS, err, userCred, false) return nil, errors.Wrap(err, "iLoadbalancer.SetMetadata") } logclient.AddActionLogWithStartable(task, lb, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true) return nil, nil }) 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) { iLb, err := lb.GetILoadbalancer(ctx) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { return nil, nil } return nil, errors.Wrapf(err, "GetILoadbalancer") } err = iLb.Delete(ctx) if err != nil { return nil, errors.Wrapf(err, "iLb.Delete") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateLoadbalancerAcl(ctx context.Context, userCred mcclient.TokenCredential, lbacl *models.SLoadbalancerAcl, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iRegion, err := lbacl.GetIRegion(ctx) if err != nil { return nil, errors.Wrapf(err, "GetIRegion") } opts := &cloudprovider.SLoadbalancerAccessControlList{ Name: lbacl.Name, Entrys: []cloudprovider.SLoadbalancerAccessControlListEntry{}, } if lbacl.AclEntries != nil { for _, entry := range *lbacl.AclEntries { opts.Entrys = append(opts.Entrys, cloudprovider.SLoadbalancerAccessControlListEntry{ Comment: entry.Comment, CIDR: entry.Cidr, }) } } iAcl, err := iRegion.CreateILoadBalancerAcl(opts) if err != nil { return nil, errors.Wrapf(err, "CreateILoadBalancerAcl") } _, err = db.Update(lbacl, func() error { lbacl.ExternalId = iAcl.GetGlobalId() return nil }) return nil, err }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestUpdateLoadbalancerAcl(ctx context.Context, userCred mcclient.TokenCredential, lbacl *models.SLoadbalancerAcl, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iAcl, err := lbacl.GetILoadbalancerAcl(ctx) if err != nil { return nil, errors.Wrapf(err, "GetILoadbalancerAcl") } opts := &cloudprovider.SLoadbalancerAccessControlList{ Name: lbacl.Name, Entrys: []cloudprovider.SLoadbalancerAccessControlListEntry{}, } if lbacl.AclEntries != nil { for _, entry := range *lbacl.AclEntries { opts.Entrys = append(opts.Entrys, cloudprovider.SLoadbalancerAccessControlListEntry{ Comment: entry.Comment, CIDR: entry.Cidr, }) } } return nil, iAcl.Sync(opts) }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestLoadbalancerAclSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, lbacl *models.SLoadbalancerAcl, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iAcl, err := lbacl.GetILoadbalancerAcl(ctx) if err != nil { return nil, errors.Wrapf(err, "GetILoadbalancerAcl") } return nil, lbacl.SyncWithCloudAcl(ctx, userCred, iAcl, lbacl.GetCloudprovider()) }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteLoadbalancerAcl(ctx context.Context, userCred mcclient.TokenCredential, lbacl *models.SLoadbalancerAcl, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iAcl, err := lbacl.GetILoadbalancerAcl(ctx) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { return nil, nil } return nil, errors.Wrapf(err, "GetILoadbalancerAcl") } return nil, iAcl.Delete() }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateLoadbalancerCertificate(ctx context.Context, userCred mcclient.TokenCredential, lbcert *models.SLoadbalancerCertificate, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iRegion, err := lbcert.GetIRegion(ctx) if err != nil { return nil, err } opts := &cloudprovider.SLoadbalancerCertificate{ Name: lbcert.Name, PrivateKey: lbcert.PrivateKey, Certificate: lbcert.Certificate, } iCert, err := iRegion.CreateILoadBalancerCertificate(opts) if err != nil { return nil, err } _, err = db.Update(lbcert, func() error { lbcert.ExternalId = iCert.GetGlobalId() return nil }) return nil, err }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteLoadbalancerCertificate(ctx context.Context, userCred mcclient.TokenCredential, lbcert *models.SLoadbalancerCertificate, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iCert, err := lbcert.GetILoadbalancerCertificate(ctx) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { return nil, nil } return nil, err } return nil, iCert.Delete() }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestLoadbalancerCertificateSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, lbcert *models.SLoadbalancerCertificate, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iCert, err := lbcert.GetILoadbalancerCertificate(ctx) if err != nil { return nil, err } return nil, lbcert.SyncWithCloudCert(ctx, userCred, iCert, lbcert.GetCloudprovider()) }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, lbbg *models.SLoadbalancerBackendGroup, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { lb, err := lbbg.GetLoadbalancer() if err != nil { return nil, errors.Wrapf(err, "GetLoadbalancer") } iLb, err := lb.GetILoadbalancer(ctx) if err != nil { return nil, errors.Wrapf(err, "GetILoadBalancer(%s)", lb.ExternalId) } group := &cloudprovider.SLoadbalancerBackendGroup{ Name: lbbg.Name, GroupType: lbbg.Type, Scheduler: lbbg.Scheduler, Backends: []cloudprovider.SLoadbalancerBackend{}, } if hc, err := lbbg.GetHealthCheck(); err == nil { group.HealthCheckId = hc.ExternalId } backends, err := lbbg.GetBackends() if err != nil { return nil, errors.Wrapf(err, "GetBackends") } for i := range backends { group.Backends = append(group.Backends, cloudprovider.SLoadbalancerBackend{ Weight: backends[i].Weight, Port: backends[i].Port, Name: backends[i].Name, BackendType: backends[i].BackendType, BackendRole: backends[i].BackendRole, Address: backends[i].Address, }) } iLbbg, err := iLb.CreateILoadBalancerBackendGroup(group) if err != nil { return nil, err } err = db.SetExternalId(lbbg, userCred, iLbbg.GetGlobalId()) if err != nil { return nil, errors.Wrapf(err, "db.SetExternalId") } iBackends, err := iLbbg.GetILoadbalancerBackends() if err != nil { return nil, errors.Wrapf(err, "GetILoadBalancerBackends") } for i := 0; i < len(backends) && i < len(iBackends); i++ { db.Update(&backends[i], func() error { backends[i].ExternalId = iBackends[i].GetGlobalId() return nil }) } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, lbbg *models.SLoadbalancerBackendGroup, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { if jsonutils.QueryBoolean(task.GetParams(), "purge", false) { return nil, nil } iRegion, err := lbbg.GetIRegion(ctx) if err != nil { return nil, err } loadbalancer, err := lbbg.GetLoadbalancer() if err != nil { return nil, err } iLoadbalancer, err := iRegion.GetILoadBalancerById(loadbalancer.ExternalId) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { return nil, nil } return nil, err } if len(lbbg.ExternalId) == 0 { return nil, nil } iLoadbalancerBackendGroup, err := iLoadbalancer.GetILoadBalancerBackendGroupById(lbbg.ExternalId) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { return nil, nil } return nil, err } err = iLoadbalancerBackendGroup.Delete(ctx) if err != nil { return nil, err } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, lbb *models.SLoadbalancerBackend, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { lbbg, err := lbb.GetLoadbalancerBackendGroup() if err != nil { return nil, err } lb, err := lbbg.GetLoadbalancer() if err != nil { return nil, err } iRegion, err := lb.GetIRegion(ctx) if err != nil { return nil, err } iLoadbalancer, err := iRegion.GetILoadBalancerById(lb.ExternalId) if err != nil { return nil, err } iLoadbalancerBackendGroup, err := iLoadbalancer.GetILoadBalancerBackendGroupById(lbbg.ExternalId) if err != nil { return nil, err } opts := &cloudprovider.SLoadbalancerBackend{ Name: lbb.Name, Weight: lbb.Weight, Port: lbb.Port, Address: lbb.Address, } if lbb.BackendType == api.LB_BACKEND_GUEST { guest := lbb.GetGuest() if guest == nil { return nil, fmt.Errorf("failed to find guest for lbb %s", lbb.Name) } opts.ExternalId = guest.ExternalId } iLoadbalancerBackend, err := iLoadbalancerBackendGroup.AddBackendServer(opts) if err != nil { return nil, err } if err := db.SetExternalId(lbb, userCred, iLoadbalancerBackend.GetGlobalId()); err != nil { return nil, err } return nil, lbb.SyncWithCloudLoadbalancerBackend(ctx, userCred, iLoadbalancerBackend, lb.GetCloudprovider()) }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, lbb *models.SLoadbalancerBackend, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { if jsonutils.QueryBoolean(task.GetParams(), "purge", false) { return nil, nil } lbbg, err := lbb.GetLoadbalancerBackendGroup() if err != nil { return nil, err } lb, err := lbbg.GetLoadbalancer() if err != nil { return nil, err } iRegion, err := lb.GetIRegion(ctx) if err != nil { return nil, err } iLoadbalancer, err := iRegion.GetILoadBalancerById(lb.ExternalId) if err != nil { return nil, err } iLoadbalancerBackendGroup, err := iLoadbalancer.GetILoadBalancerBackendGroupById(lbbg.ExternalId) if err != nil { return nil, err } opts := &cloudprovider.SLoadbalancerBackend{ Weight: lbb.Weight, Port: lbb.Port, Name: lbb.Name, Address: lbb.Address, ExternalId: lbb.ExternalId, } if lbb.BackendType == api.LB_BACKEND_GUEST { guest := lbb.GetGuest() if guest == nil { log.Warningf("failed to find guest for lbb %s", lbb.Name) return nil, nil } _, err = guest.GetIVM(ctx) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { return nil, nil } return nil, err } opts.ExternalId = guest.ExternalId } return nil, iLoadbalancerBackendGroup.RemoveBackendServer(opts) }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestSyncLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, lbb *models.SLoadbalancerBackend, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { lbbg, err := lbb.GetLoadbalancerBackendGroup() if err != nil { return nil, err } lb, err := lbbg.GetLoadbalancer() if err != nil { return nil, err } iLb, err := lb.GetILoadbalancer(ctx) if err != nil { return nil, errors.Wrap(err, "GetILoadbalancer") } iLoadbalancerBackendGroup, err := iLb.GetILoadBalancerBackendGroupById(lbbg.ExternalId) if err != nil { return nil, errors.Wrap(err, "GetILoadBalancerBackendGroupById") } iBackend, err := iLoadbalancerBackendGroup.GetILoadbalancerBackendById(lbb.ExternalId) if err != nil { return nil, errors.Wrap(err, "GetILoadbalancerBackendById") } opts := &cloudprovider.SLoadbalancerBackend{ Weight: lbb.Weight, Port: lbb.Port, ExternalId: lbb.ExternalId, BackendType: lbb.BackendType, BackendRole: lbb.BackendRole, Address: lbb.Address, } opts.Enabled = jsonutils.QueryBoolean(task.GetParams(), "enabled", true) err = iBackend.Update(ctx, opts) if err != nil { return nil, errors.Wrap(err, "Update") } iBackend, err = iLoadbalancerBackendGroup.GetILoadbalancerBackendById(lbb.ExternalId) if err != nil { return nil, errors.Wrap(err, "regionDriver.RequestSyncLoadbalancerBackend.GetILoadbalancerBackendById") } return nil, lbb.SyncWithCloudLoadbalancerBackend(ctx, userCred, iBackend, lb.GetCloudprovider()) }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { provider := lblis.GetCloudprovider() if provider == nil { return nil, fmt.Errorf("failed to find provider for lblis %s", lblis.Name) } params, err := lblis.GetLoadbalancerListenerParams() if err != nil { return nil, errors.Wrapf(err, "lblis.GetLoadbalancerListenerParams") } { if lblis.ListenerType == api.LB_LISTENER_TYPE_HTTPS && len(lblis.CertificateId) > 0 { cert, err := lblis.GetCertificate() if err != nil { return nil, errors.Wrapf(err, "GetCertificate") } params.CertificateId = cert.ExternalId } } { if len(lblis.AclId) > 0 { acl, err := lblis.GetAcl() if err != nil { return nil, errors.Wrap(err, "GetAcl") } params.AccessControlListId = acl.ExternalId params.AccessControlListType = lblis.AclType params.AccessControlListStatus = lblis.AclStatus } } loadbalancer, err := lblis.GetLoadbalancer() if err != nil { return nil, err } iRegion, err := loadbalancer.GetIRegion(ctx) if err != nil { return nil, errors.Wrap(err, "loadbalancer.GetIRegion") } iLoadbalancer, err := iRegion.GetILoadBalancerById(loadbalancer.ExternalId) if err != nil { return nil, errors.Wrapf(err, "iRegion.GetILoadBalancerById(%s)", loadbalancer.ExternalId) } iListener, err := iLoadbalancer.CreateILoadBalancerListener(ctx, params) if err != nil { return nil, errors.Wrap(err, "iLoadbalancer.CreateILoadBalancerListener") } if err := db.SetExternalId(lblis, userCred, iListener.GetGlobalId()); err != nil { return nil, errors.Wrap(err, "db.SetExternalId") } return nil, lblis.SyncWithCloudLoadbalancerListener(ctx, userCred, loadbalancer, iListener, loadbalancer.GetOwnerId(), lblis.GetCloudprovider()) }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { if len(lblis.ExternalId) == 0 { return nil, nil } lb, err := lblis.GetLoadbalancer() if err != nil { return nil, err } iLb, err := lb.GetILoadbalancer(ctx) if err != nil { return nil, errors.Wrapf(err, "GetILoadbalancer") } iListener, err := iLb.GetILoadBalancerListenerById(lblis.ExternalId) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { return nil, nil } return nil, errors.Wrapf(err, "GetILoadBalancerListenerById(%s)", lblis.ExternalId) } return nil, iListener.Delete(ctx) }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestStartLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { loadbalancer, err := lblis.GetLoadbalancer() if err != nil { return nil, err } iRegion, err := loadbalancer.GetIRegion(ctx) if err != nil { return nil, err } iLoadbalancer, err := iRegion.GetILoadBalancerById(loadbalancer.ExternalId) if err != nil { return nil, err } iListener, err := iLoadbalancer.GetILoadBalancerListenerById(lblis.ExternalId) if err != nil { return nil, err } return nil, iListener.Start() }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestSyncLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, input *api.LoadbalancerListenerUpdateInput, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iLis, err := lblis.GetILoadbalancerListener(ctx) if err != nil { return nil, errors.Wrapf(err, "GetILoadbalancerListener") } provider := lblis.GetCloudprovider() if provider == nil { return nil, fmt.Errorf("failed to find provider for lblis %s", lblis.Name) } { if lblis.ListenerType == api.LB_LISTENER_TYPE_HTTPS && input.CertificateId != nil { cert, err := lblis.GetCertificate() if err != nil { return nil, errors.Wrapf(err, "GetCertificate") } err = iLis.ChangeCertificate(ctx, &cloudprovider.ListenerCertificateOptions{ CertificateId: cert.ExternalId, }) if err != nil && errors.Cause(err) != cloudprovider.ErrNotSupported && errors.Cause(err) != cloudprovider.ErrNotImplemented { return nil, errors.Wrapf(err, "ChangeCertificate") } } } { if input.AclStatus != nil { opts := &cloudprovider.ListenerAclOptions{AclStatus: *input.AclStatus, AclType: lblis.AclType} if *input.AclStatus == api.LB_BOOL_ON { acl, err := lblis.GetAcl() if err != nil { return nil, errors.Wrapf(err, "GetAcl") } opts.AclId = acl.ExternalId } err := iLis.SetAcl(ctx, opts) if err != nil && errors.Cause(err) != cloudprovider.ErrNotSupported { return nil, errors.Wrapf(err, "SetAcl") } } } if iLis.GetScheduler() != lblis.Scheduler { err := iLis.ChangeScheduler(ctx, &cloudprovider.ChangeListenerSchedulerOptions{ Scheduler: lblis.Scheduler, ListenerStickySessionOptions: cloudprovider.ListenerStickySessionOptions{ StickySession: lblis.StickySession, StickySessionCookie: lblis.StickySessionCookie, StickySessionType: lblis.StickySessionType, StickySessionCookieTimeout: lblis.StickySessionCookieTimeout, }, }) if err != nil && errors.Cause(err) != cloudprovider.ErrNotSupported && errors.Cause(err) != cloudprovider.ErrNotImplemented { return nil, errors.Wrapf(err, "ChangeScheduler") } } if input.HealthCheck != nil { err := iLis.SetHealthCheck(ctx, &cloudprovider.ListenerHealthCheckOptions{ HealthCheckReq: lblis.HealthCheckReq, HealthCheckExp: lblis.HealthCheckExp, HealthCheck: lblis.HealthCheck, HealthCheckType: lblis.HealthCheckType, HealthCheckTimeout: lblis.HealthCheckTimeout, HealthCheckDomain: lblis.HealthCheckDomain, HealthCheckHttpCode: lblis.HealthCheckHttpCode, HealthCheckURI: lblis.HealthCheckURI, HealthCheckInterval: lblis.HealthCheckInterval, HealthCheckRise: lblis.HealthCheckRise, HealthCheckFail: lblis.HealthCheckFall, }) if err != nil && errors.Cause(err) != cloudprovider.ErrNotSupported && errors.Cause(err) != cloudprovider.ErrNotImplemented { return nil, errors.Wrapf(err, "SetHealthCheck") } } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestStopLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { loadbalancer, err := lblis.GetLoadbalancer() if err != nil { return nil, err } iRegion, err := loadbalancer.GetIRegion(ctx) if err != nil { return nil, err } iLoadbalancer, err := iRegion.GetILoadBalancerById(loadbalancer.ExternalId) if err != nil { return nil, err } iListener, err := iLoadbalancer.GetILoadBalancerListenerById(lblis.ExternalId) if err != nil { return nil, err } return nil, iListener.Stop() }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestSyncstatusLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { loadbalancer, err := lblis.GetLoadbalancer() if err != nil { return nil, err } iRegion, err := loadbalancer.GetIRegion(ctx) if err != nil { return nil, err } iLoadbalancer, err := iRegion.GetILoadBalancerById(loadbalancer.ExternalId) if err != nil { return nil, err } iListener, err := iLoadbalancer.GetILoadBalancerListenerById(lblis.ExternalId) if err != nil { return nil, err } status := iListener.GetStatus() if utils.IsInStringArray(status, []string{api.LB_STATUS_ENABLED, api.LB_STATUS_DISABLED}) { return nil, lblis.SetStatus(ctx, userCred, status, "") } return nil, fmt.Errorf("Unknown loadbalancer listener status %s", status) }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateLoadbalancerListenerRule(ctx context.Context, userCred mcclient.TokenCredential, lbr *models.SLoadbalancerListenerRule, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { listener, err := lbr.GetLoadbalancerListener() if err != nil { return nil, err } loadbalancer, err := listener.GetLoadbalancer() if err != nil { return nil, err } iLb, err := loadbalancer.GetILoadbalancer(ctx) if err != nil { return nil, err } iListener, err := iLb.GetILoadBalancerListenerById(listener.ExternalId) if err != nil { return nil, err } opts := &cloudprovider.SLoadbalancerListenerRule{ Name: lbr.Name, Domain: lbr.Domain, Path: lbr.Path, BackendGroups: []string{}, } if lbr.RedirectPool != nil { opts.RedirectPool = cloudprovider.SRedirectPool{ CountryPools: map[string][]string{}, RegionPools: map[string][]string{}, } for poolName, pools := range lbr.RedirectPool.CountryPools { poolIds := []string{} for _, pool := range pools { poolIds = append(poolIds, pool.ExternalId) } opts.RedirectPool.CountryPools[poolName] = poolIds } for poolName, pools := range lbr.RedirectPool.RegionPools { poolIds := []string{} for _, pool := range pools { poolIds = append(poolIds, pool.ExternalId) } opts.RedirectPool.RegionPools[poolName] = poolIds } } if lbr.BackendGroups != nil { for _, backendGroup := range *lbr.BackendGroups { opts.BackendGroups = append(opts.BackendGroups, backendGroup.ExternalId) } } if len(lbr.BackendGroupId) > 0 { group := lbr.GetLoadbalancerBackendGroup() if group == nil { return nil, fmt.Errorf("failed to find backend group for listener rule %s", lbr.Name) } opts.BackendGroupId = group.ExternalId opts.BackendGroupType = group.Type } iListenerRule, err := iListener.CreateILoadBalancerListenerRule(opts) if err != nil { return nil, err } if err := db.SetExternalId(lbr, userCred, iListenerRule.GetGlobalId()); err != nil { return nil, err } return nil, lbr.SyncWithCloudLoadbalancerListenerRule(ctx, userCred, iListenerRule, listener.GetOwnerId(), loadbalancer.GetCloudprovider()) }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteLoadbalancerListenerRule(ctx context.Context, userCred mcclient.TokenCredential, lbr *models.SLoadbalancerListenerRule, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { if jsonutils.QueryBoolean(task.GetParams(), "purge", false) { return nil, nil } listener, err := lbr.GetLoadbalancerListener() if err != nil { return nil, err } loadbalancer, err := listener.GetLoadbalancer() if err != nil { return nil, err } iRegion, err := loadbalancer.GetIRegion(ctx) if err != nil { return nil, err } iLoadbalancer, err := iRegion.GetILoadBalancerById(loadbalancer.ExternalId) if err != nil { return nil, err } iListener, err := iLoadbalancer.GetILoadBalancerListenerById(listener.ExternalId) if err != nil { return nil, err } if len(lbr.ExternalId) == 0 { return nil, nil } iListenerRule, err := iListener.GetILoadBalancerListenerRuleById(lbr.ExternalId) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { return nil, nil } return nil, err } return nil, iListenerRule.Delete(ctx) }) return nil } func (self *SManagedVirtualizationRegionDriver) ValidateCreateVpcData(ctx context.Context, userCred mcclient.TokenCredential, input api.VpcCreateInput) (api.VpcCreateInput, error) { return input, nil } func (self *SManagedVirtualizationRegionDriver) GetEipDefaultChargeType() billing_api.TNetChargeType { return billing_api.NET_CHARGE_TYPE_BY_TRAFFIC } func (self *SManagedVirtualizationRegionDriver) ValidateEipChargeType(chargeType billing_api.TNetChargeType) error { return nil } func (self *SManagedVirtualizationRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SElasticipCreateInput) error { return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateVpc(ctx context.Context, userCred mcclient.TokenCredential, region *models.SCloudregion, vpc *models.SVpc, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iregion, err := vpc.GetIRegion(ctx) if err != nil { return nil, errors.Wrap(err, "vpc.GetIRegion") } opts := &cloudprovider.VpcCreateOptions{ NAME: vpc.Name, CIDR: vpc.CidrBlock, Desc: vpc.Description, } ivpc, err := iregion.CreateIVpc(opts) if err != nil { return nil, errors.Wrap(err, "iregion.CreateIVpc") } db.SetExternalId(vpc, userCred, ivpc.GetGlobalId()) err = cloudprovider.WaitStatus(ivpc, api.VPC_STATUS_AVAILABLE, 10*time.Second, 300*time.Second) if err != nil { return nil, errors.Wrap(err, "cloudprovider.WaitStatus") } if ivpc.IsSupportSetExternalAccess() && vpc.ExternalAccessMode == api.VPC_EXTERNAL_ACCESS_MODE_EIP { igw, err := iregion.CreateInternetGateway() if err != nil { return nil, errors.Wrap(err, "vpc.AttachInternetGateway") } err = ivpc.AttachInternetGateway(igw.GetId()) if err != nil { return nil, errors.Wrap(err, "vpc.AttachInternetGateway") } } err = vpc.SyncRemoteWires(ctx, userCred) if err != nil { return nil, errors.Wrap(err, "vpc.SyncRemoteWires") } err = vpc.SyncWithCloudVpc(ctx, userCred, ivpc, nil) if err != nil { return nil, errors.Wrap(err, "vpc.SyncWithCloudVpc") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteVpc(ctx context.Context, userCred mcclient.TokenCredential, region *models.SCloudregion, vpc *models.SVpc, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { secgroups, err := vpc.GetSecurityGroups() if err != nil { return nil, errors.Wrapf(err, "GetSecurityGroups") } for i := range secgroups { iGroup, err := secgroups[i].GetISecurityGroup(ctx) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { continue } return nil, errors.Wrapf(err, "GetISecurityGroup") } err = iGroup.Delete() if err != nil && errors.Cause(err) != cloudprovider.ErrNotSupported { return nil, errors.Wrapf(err, "delete secgroup %s", secgroups[i].Name) } err = secgroups[i].RealDelete(ctx, userCred) if err != nil { return nil, errors.Wrapf(err, "real delete secgroup %s", secgroups[i].Name) } } ivpc, err := vpc.GetIVpc(ctx) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { // already deleted, do nothing return nil, nil } return nil, errors.Wrap(err, "GetIVpc") } err = ivpc.Delete() if err != nil { return nil, errors.Wrap(err, "Delete") } err = cloudprovider.WaitDeleted(ivpc, 10*time.Second, 300*time.Second) if err != nil { return nil, errors.Wrap(err, "cloudprovider.WaitDeleted") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) ValidateSnapshotDelete(ctx context.Context, snapshot *models.SSnapshot) error { return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteSnapshot(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { cloudRegion, err := snapshot.GetISnapshotRegion(ctx) if err != nil { return nil, err } cloudSnapshot, err := cloudRegion.GetISnapshotById(snapshot.ExternalId) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { return nil, nil } return nil, err } if err := cloudSnapshot.Delete(); err != nil { return nil, err } if err := cloudprovider.WaitDeleted(cloudSnapshot, 10*time.Second, 300*time.Second); err != nil { return nil, err } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SnapshotCreateInput) error { return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateSnapshot(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask) error { disk, err := snapshot.GetDisk() if err != nil { return err } iDisk, err := disk.GetIDisk(ctx) if err != nil { return err } taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iSnapshot, err := iDisk.CreateISnapshot(ctx, snapshot.Name, "") if err != nil { return nil, err } _, err = db.Update(snapshot, func() error { snapshot.Size = int(iSnapshot.GetSizeMb()) snapshot.VirtualSize = int(iSnapshot.GetSizeMb()) snapshot.ExternalId = iSnapshot.GetGlobalId() return nil }) return nil, err }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateInstanceSnapshot(ctx context.Context, guest *models.SGuest, isp *models.SInstanceSnapshot, task taskman.ITask, params *jsonutils.JSONDict) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteInstanceSnapshot(ctx context.Context, isp *models.SInstanceSnapshot, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestResetToInstanceSnapshot(ctx context.Context, guest *models.SGuest, isp *models.SInstanceSnapshot, task taskman.ITask, params *jsonutils.JSONDict) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) GetDiskResetParams(snapshot *models.SSnapshot) *jsonutils.JSONDict { params := jsonutils.NewDict() params.Set("snapshot_id", jsonutils.NewString(snapshot.ExternalId)) return params } func (self *SManagedVirtualizationRegionDriver) OnDiskReset(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, snapshot *models.SSnapshot, data jsonutils.JSONObject) error { return nil } func (self *SManagedVirtualizationRegionDriver) OnSnapshotDelete(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask, data jsonutils.JSONObject) error { task.SetStage("OnManagedSnapshotDelete", nil) task.ScheduleRun(data) return nil } func (self *SManagedVirtualizationRegionDriver) RequestAssociateEipForNAT(ctx context.Context, userCred mcclient.TokenCredential, nat *models.SNatGateway, eip *models.SElasticip, task taskman.ITask) error { opts := api.ElasticipAssociateInput{ InstanceType: api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY, InstanceId: nat.Id, } return eip.StartEipAssociateTask(ctx, userCred, jsonutils.Marshal(opts).(*jsonutils.JSONDict), task.GetTaskId()) } func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstance(ctx context.Context, userCred mcclient.TokenCredential, dbinstance *models.SDBInstance, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iregion, err := dbinstance.GetIRegion(ctx) if err != nil { return nil, errors.Wrap(err, "GetIRegionAndProvider") } vpc, err := dbinstance.GetVpc() if err != nil { return nil, errors.Wrap(err, "dbinstance.GetVpc()") } input := api.DBInstanceCreateInput{} task.GetParams().Unmarshal(&input) if len(input.Password) == 0 && jsonutils.QueryBoolean(task.GetParams(), "reset_password", true) { input.Password = seclib2.RandomPassword2(12) } desc := cloudprovider.SManagedDBInstanceCreateConfig{ Name: dbinstance.Name, Description: dbinstance.Description, StorageType: dbinstance.StorageType, DiskSizeGB: dbinstance.DiskSizeGB, VcpuCount: dbinstance.VcpuCount, VmemSizeMb: dbinstance.VmemSizeMb, VpcId: vpc.ExternalId, Engine: dbinstance.Engine, EngineVersion: dbinstance.EngineVersion, Category: dbinstance.Category, Port: dbinstance.Port, Password: input.Password, MultiAz: input.MultiAZ, } desc.Tags, _ = dbinstance.GetAllUserMetadata() networks, err := dbinstance.GetDBNetworks() if err != nil { return nil, errors.Wrapf(err, "dbinstance.GetDBNetworks") } if len(networks) > 0 { net, err := networks[0].GetNetwork() if err != nil { return nil, errors.Wrapf(err, "GetNetwork") } desc.NetworkId, desc.Address = net.ExternalId, networks[0].IpAddr } _cloudprovider := dbinstance.GetCloudprovider() desc.ProjectId, err = _cloudprovider.SyncProject(ctx, userCred, dbinstance.ProjectId) if err != nil { if errors.Cause(err) != cloudprovider.ErrNotSupported && errors.Cause(err) != cloudprovider.ErrNotImplemented { logclient.AddSimpleActionLog(dbinstance, logclient.ACT_SYNC_CLOUD_PROJECT, err, userCred, false) } } region, err := dbinstance.GetRegion() if err != nil { return nil, err } err = region.GetDriver().InitDBInstanceUser(ctx, dbinstance, task, &desc) if err != nil { return nil, err } secgroups, err := dbinstance.GetSecgroups() if err != nil { return nil, errors.Wrapf(err, "GetSecgroups") } driver := region.GetDriver() ownerId := dbinstance.GetOwnerId() for i := range secgroups { if secgroups[i].Id == api.SECGROUP_DEFAULT_ID { filter, err := driver.GetSecurityGroupFilter(vpc) if err != nil { return nil, errors.Wrapf(err, "GetSecurityGroupFilter") } group, err := vpc.GetDefaultSecurityGroup(ownerId, filter) if err != nil && errors.Cause(err) != sql.ErrNoRows { return nil, err } if gotypes.IsNil(group) { group, err = driver.CreateDefaultSecurityGroup(ctx, userCred, ownerId, vpc) if err != nil { return nil, errors.Wrapf(err, "CreateDefaultSecurityGroup") } } if !utils.IsInStringArray(group.ExternalId, desc.SecgroupIds) { desc.SecgroupIds = append(desc.SecgroupIds, group.ExternalId) } continue } if !utils.IsInStringArray(secgroups[i].ExternalId, desc.SecgroupIds) { desc.SecgroupIds = append(desc.SecgroupIds, secgroups[i].ExternalId) } } if dbinstance.BillingType == billing_api.BILLING_TYPE_PREPAID { bc, err := billing.ParseBillingCycle(dbinstance.BillingCycle) if err != nil { log.Errorf("failed to parse billing cycle %s: %v", dbinstance.BillingCycle, err) } else if bc.IsValid() { desc.BillingCycle = &bc desc.BillingCycle.AutoRenew = dbinstance.AutoRenew } } if len(dbinstance.MasterInstanceId) > 0 { master, err := dbinstance.GetMasterInstance() if err != nil { return nil, errors.Wrap(err, "dbinstnace.GetMasterInstance()") } desc.MasterInstanceId = master.ExternalId } instanceTypes, err := dbinstance.GetAvailableInstanceTypes() if err != nil { return nil, errors.Wrapf(err, "GetAvailableInstanceTypes") } if len(instanceTypes) == 0 { return nil, fmt.Errorf("no avaiable sku for create") } var createFunc = func() (cloudprovider.ICloudDBInstance, error) { errMsgs := []string{} for i := range instanceTypes { desc.SInstanceType = instanceTypes[i] log.Debugf("create dbinstance params: %s", jsonutils.Marshal(desc).String()) iRds, err := iregion.CreateIDBInstance(&desc) if err != nil { errMsgs = append(errMsgs, err.Error()) continue } return iRds, nil } if len(errMsgs) > 0 { return nil, fmt.Errorf("%s", strings.Join(errMsgs, "\n")) } return nil, fmt.Errorf("no avaiable skus %s(%dC%d) for create", dbinstance.InstanceType, desc.VcpuCount, desc.VmemSizeMb) } iRds, err := createFunc() if err != nil { return nil, errors.Wrapf(err, "create") } err = db.SetExternalId(dbinstance, userCred, iRds.GetGlobalId()) if err != nil { return nil, errors.Wrapf(err, "db.SetExternalId") } err = cloudprovider.WaitStatus(iRds, api.DBINSTANCE_RUNNING, time.Second*10, time.Hour*1) if err != nil { return nil, errors.Wrapf(err, "cloudprovider.WaitStatus runing") } secgroupIds, err := iRds.GetSecurityGroupIds() if err == nil && len(secgroupIds) != len(desc.SecgroupIds) { err = iRds.SetSecurityGroups(desc.SecgroupIds) if err != nil && errors.Cause(err) != cloudprovider.ErrNotImplemented { logclient.AddSimpleActionLog(dbinstance, logclient.ACT_SYNC_CONF, map[string][]string{"secgroup_ids": desc.SecgroupIds}, userCred, false) } } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstanceFromBackup(ctx context.Context, userCred mcclient.TokenCredential, rds *models.SDBInstance, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { _backup, err := models.DBInstanceBackupManager.FetchById(rds.DBInstancebackupId) if err != nil { return nil, errors.Wrapf(err, "DBInstanceBackupManager.FetchById(%s)", rds.DBInstancebackupId) } backup := _backup.(*models.SDBInstanceBackup) iBackup, err := backup.GetIDBInstanceBackup(ctx) if err != nil { return nil, errors.Wrapf(err, "backup.GetIDBInstanceBackup") } vpc, err := rds.GetVpc() if err != nil { return nil, errors.Wrap(err, "rds.GetVpc()") } params := task.GetParams() passwd, _ := params.GetString("password") if len(passwd) == 0 && jsonutils.QueryBoolean(params, "reset_password", true) { passwd = seclib2.RandomPassword2(12) } desc := cloudprovider.SManagedDBInstanceCreateConfig{ Name: rds.Name, Description: rds.Description, StorageType: rds.StorageType, DiskSizeGB: rds.DiskSizeGB, VcpuCount: rds.VcpuCount, VmemSizeMb: rds.VmemSizeMb, VpcId: vpc.ExternalId, Engine: rds.Engine, EngineVersion: rds.EngineVersion, Category: rds.Category, Port: rds.Port, Password: passwd, } if len(backup.DBInstanceId) > 0 { parentRds, err := backup.GetDBInstance() if err != nil { return nil, errors.Wrapf(err, "backup.GetDBInstance") } desc.RdsId = parentRds.ExternalId } log.Debugf("create from backup params: %s", jsonutils.Marshal(desc).String()) networks, err := rds.GetDBNetworks() if err != nil { return nil, errors.Wrapf(err, "dbinstance.GetDBNetworks") } if len(networks) > 0 { net, err := networks[0].GetNetwork() if err != nil { return nil, errors.Wrapf(err, "GetNetwork") } desc.NetworkId, desc.Address = net.ExternalId, networks[0].IpAddr } _cloudprovider := rds.GetCloudprovider() desc.ProjectId, err = _cloudprovider.SyncProject(ctx, userCred, rds.ProjectId) if err != nil { if errors.Cause(err) != cloudprovider.ErrNotSupported && errors.Cause(err) != cloudprovider.ErrNotImplemented { logclient.AddSimpleActionLog(rds, logclient.ACT_SYNC_CLOUD_PROJECT, err, userCred, false) } } region, err := rds.GetRegion() if err != nil { return nil, err } err = region.GetDriver().InitDBInstanceUser(ctx, rds, task, &desc) if err != nil { return nil, err } secgroups, err := rds.GetSecgroups() if err != nil { return nil, errors.Wrapf(err, "GetSecgroups") } driver := region.GetDriver() ownerId := rds.GetOwnerId() for i := range secgroups { if secgroups[i].Id == api.SECGROUP_DEFAULT_ID { filter, err := driver.GetSecurityGroupFilter(vpc) if err != nil { return nil, errors.Wrapf(err, "GetSecurityGroupFilter") } group, err := vpc.GetDefaultSecurityGroup(ownerId, filter) if err != nil && errors.Cause(err) != sql.ErrNoRows { return nil, err } if gotypes.IsNil(group) { group, err = driver.CreateDefaultSecurityGroup(ctx, userCred, ownerId, vpc) if err != nil { return nil, errors.Wrapf(err, "CreateDefaultSecurityGroup") } } if !utils.IsInStringArray(group.ExternalId, desc.SecgroupIds) { desc.SecgroupIds = append(desc.SecgroupIds, group.ExternalId) } continue } if !utils.IsInStringArray(secgroups[i].ExternalId, desc.SecgroupIds) { desc.SecgroupIds = append(desc.SecgroupIds, secgroups[i].ExternalId) } } if rds.BillingType == billing_api.BILLING_TYPE_PREPAID { bc, err := billing.ParseBillingCycle(rds.BillingCycle) if err != nil { log.Errorf("failed to parse billing cycle %s: %v", rds.BillingCycle, err) } else if bc.IsValid() { desc.BillingCycle = &bc desc.BillingCycle.AutoRenew = rds.AutoRenew } } instanceTypes, err := rds.GetAvailableInstanceTypes() if err != nil { return nil, errors.Wrapf(err, "GetAvailableInstanceTypes") } if len(instanceTypes) == 0 { return nil, fmt.Errorf("no avaiable sku for create") } var createFunc = func() (cloudprovider.ICloudDBInstance, error) { errMsgs := []string{} for i := range instanceTypes { desc.SInstanceType = instanceTypes[i] log.Debugf("create dbinstance params: %s", jsonutils.Marshal(desc).String()) iRds, err := iBackup.CreateICloudDBInstance(&desc) if err != nil { errMsgs = append(errMsgs, err.Error()) continue } return iRds, nil } if len(errMsgs) > 0 { return nil, fmt.Errorf("%s", strings.Join(errMsgs, "\n")) } return nil, fmt.Errorf("no avaiable skus %s(%dC%d) for create", rds.InstanceType, desc.VcpuCount, desc.VmemSizeMb) } iRds, err := createFunc() if err != nil { return nil, errors.Wrapf(err, "create") } err = db.SetExternalId(rds, userCred, iRds.GetGlobalId()) if err != nil { return nil, errors.Wrapf(err, "db.SetExternalId") } err = cloudprovider.WaitStatus(iRds, api.DBINSTANCE_RUNNING, time.Second*5, time.Hour*1) if err != nil { return nil, errors.Wrapf(err, "cloudprovider.WaitStatus runing") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask, data *jsonutils.JSONDict) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iRegion, err := ec.GetIRegion(ctx) if err != nil { return nil, errors.Wrap(err, "GetIRegion") } iprovider, err := db.FetchById(models.CloudproviderManager, ec.GetCloudproviderId()) if err != nil { return nil, errors.Wrap(err, "GetProvider") } vpc, err := ec.GetVpc() if err != nil { return nil, errors.Wrapf(err, "GetVpc") } networkObj, err := db.FetchById(models.NetworkManager, ec.NetworkId) if err != nil { return nil, errors.Wrap(err, "GetNetwork") } network := networkObj.(*models.SNetwork) params := &cloudprovider.SCloudElasticCacheInput{ InstanceType: ec.InstanceType, InstanceName: ec.Name, Engine: ec.Engine, EngineVersion: ec.EngineVersion, PrivateIpAddress: ec.PrivateIpAddr, CapacityGB: int64(ec.CapacityMB / 1024), NodeType: ec.NodeType, NetworkType: ec.NetworkType, VpcId: vpc.ExternalId, NetworkId: network.ExternalId, MaintainBegin: ec.MaintainStartTime, MaintainEnd: ec.MaintainEndTime, } params.Password, _ = task.GetParams().GetString("password") if ec.BillingType == billing_api.BILLING_TYPE_PREPAID { bc, err := billing.ParseBillingCycle(ec.BillingCycle) if err != nil { return nil, errors.Wrapf(err, "ParseBillingCycle(%s)", ec.BillingCycle) } bc.AutoRenew = ec.AutoRenew params.BillingCycle = &bc } params.Tags, _ = ec.GetAllUserMetadata() zone, err := ec.GetZone() if zone != nil { izone, err := iRegion.GetIZoneById(zone.ExternalId) if err != nil { return nil, errors.Wrapf(err, "GetIZoneById(%s)", zone.ExternalId) } params.ZoneIds = []string{izone.GetId()} } slaveZones, err := ec.GetSlaveZones() if err != nil { return nil, errors.Wrapf(err, "GetSlaveZones") } for i := range slaveZones { izone, err := iRegion.GetIZoneById(slaveZones[i].ExternalId) if err != nil { return nil, errors.Wrapf(err, "GetSlaveZoneBy(%s)", slaveZones[i].ExternalId) } if !utils.IsInStringArray(izone.GetId(), params.ZoneIds) { params.ZoneIds = append(params.ZoneIds, izone.GetId()) } } data.Unmarshal(¶ms.SecurityGroupIds, "ext_secgroup_ids") provider := iprovider.(*models.SCloudprovider) params.ProjectId, err = provider.SyncProject(ctx, userCred, ec.ProjectId) if err != nil { if errors.Cause(err) != cloudprovider.ErrNotSupported && errors.Cause(err) != cloudprovider.ErrNotImplemented { logclient.AddSimpleActionLog(ec, logclient.ACT_SYNC_CLOUD_PROJECT, err, userCred, false) } } iec, err := iRegion.CreateIElasticcaches(params) if err != nil { return nil, errors.Wrap(err, "CreateIElasticcaches") } err = db.SetExternalId(ec, userCred, iec.GetGlobalId()) if err != nil { return nil, errors.Wrap(err, "SetExternalId") } err = cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 30*time.Second, 15*time.Second, 30*time.Minute) if err != nil { return nil, errors.Wrap(err, "WaitStatusWithDelay") } err = ec.SyncWithCloudElasticcache(ctx, userCred, provider, iec) if err != nil { return nil, errors.Wrap(err, "SyncWithCloudElasticcache") } // sync accounts { iaccounts, err := iec.GetICloudElasticcacheAccounts() if err != nil { return nil, errors.Wrap(err, "GetICloudElasticcacheAccounts") } models.ElasticcacheAccountManager.SyncElasticcacheAccounts(ctx, userCred, ec, iaccounts) account, err := ec.GetAdminAccount() if err == nil { account.SavePassword(params.Password) } } // sync acl { iacls, err := iec.GetICloudElasticcacheAcls() if err != nil { if !(errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented) { return nil, errors.Wrap(err, "GetICloudElasticcacheAcls") } models.ElasticcacheAclManager.SyncElasticcacheAcls(ctx, userCred, ec, iacls) } } // sync parameters { iparams, err := iec.GetICloudElasticcacheParameters() if err != nil { if !(errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotSupported) { return nil, errors.Wrap(err, "GetICloudElasticcacheParameters") } models.ElasticcacheParameterManager.SyncElasticcacheParameters(ctx, userCred, ec, iparams) } } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) ValidateCreateElasticcacheData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input *api.ElasticcacheCreateInput) (*api.ElasticcacheCreateInput, error) { if len(input.ManagerId) == 0 { return nil, httperrors.NewMissingParameterError("manager_id") } if len(input.NetworkType) == 0 { input.NetworkType = api.LB_NETWORK_TYPE_VPC } return input, nil } func (self *SManagedVirtualizationRegionDriver) RequestRestartElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { iregion, err := ec.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestRestartElasticcache.GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.ExternalId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestRestartElasticcache.GetIElasticcacheById") } err = iec.Restart() if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestRestartElasticcache.Restart") } err = cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 10*time.Second, 10*time.Second, 1800*time.Second) if err != nil { return err } return ec.SetStatus(ctx, userCred, api.ELASTIC_CACHE_STATUS_RUNNING, "") } func (self *SManagedVirtualizationRegionDriver) RequestSyncElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { iregion, err := ec.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.ExternalId) if err != nil { return errors.Wrap(err, "GetIElasticcacheById") } provider := ec.GetCloudprovider() if provider == nil { return errors.Wrap(fmt.Errorf("provider is nil"), "GetCloudprovider") } lockman.LockRawObject(ctx, "elastic-cache", ec.Id) defer lockman.ReleaseRawObject(ctx, "elastic-cache", ec.Id) err = ec.SyncWithCloudElasticcache(ctx, userCred, provider, iec) if err != nil { return errors.Wrap(err, "SyncWithCloudElasticcache") } if fullsync, _ := task.GetParams().Bool("full"); fullsync { lockman.LockObject(ctx, ec) defer lockman.ReleaseObject(ctx, ec) parameters, err := iec.GetICloudElasticcacheParameters() if err != nil { if !(errors.Cause(err) == cloudprovider.ErrNotImplemented || errors.Cause(err) == cloudprovider.ErrNotSupported) { return errors.Wrapf(err, "GetICloudElasticcacheParameters") } result := models.ElasticcacheParameterManager.SyncElasticcacheParameters(ctx, userCred, ec, parameters) log.Infof("SyncElasticcacheParameters %s", result.Result()) } // acl acls, err := iec.GetICloudElasticcacheAcls() if err != nil { if !(errors.Cause(err) == cloudprovider.ErrNotImplemented || errors.Cause(err) == cloudprovider.ErrNotSupported) { return errors.Wrapf(err, "GetICloudElasticcacheAcls") } result := models.ElasticcacheAclManager.SyncElasticcacheAcls(ctx, userCred, ec, acls) log.Infof("SyncElasticcacheAcls %s", result.Result()) } // account accounts, err := iec.GetICloudElasticcacheAccounts() if err != nil { if !(errors.Cause(err) == cloudprovider.ErrNotImplemented || errors.Cause(err) == cloudprovider.ErrNotSupported) { return errors.Wrapf(err, "GetICloudElasticcacheAccounts") } result := models.ElasticcacheAccountManager.SyncElasticcacheAccounts(ctx, userCred, ec, accounts) log.Infof("SyncElasticcacheAccounts %s", result.Result()) } // backups backups, err := iec.GetICloudElasticcacheBackups() if err != nil { if !(errors.Cause(err) == cloudprovider.ErrNotImplemented || errors.Cause(err) == cloudprovider.ErrNotSupported) { return errors.Wrapf(err, "GetICloudElasticcacheAccounts") } result := models.ElasticcacheBackupManager.SyncElasticcacheBackups(ctx, userCred, ec, backups) log.Infof("SyncElasticcacheBackups %s", result.Result()) } } return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { if len(ec.ExternalId) == 0 { return nil } iregion, err := ec.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.ExternalId) if errors.Cause(err) == cloudprovider.ErrNotFound { return nil } else if err != nil { return errors.Wrap(err, "GetIElasticcacheById") } err = iec.Delete() if err != nil { return errors.Wrap(err, "Delete") } return cloudprovider.WaitDeleted(iec, 10*time.Second, 10*time.Minute) } func (self *SManagedVirtualizationRegionDriver) RequestSetElasticcacheMaintainTime(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { mStart, err := task.GetParams().GetString("maintain_start_time") if err != nil { return errors.Wrap(fmt.Errorf("missing parameter maintain_start_time"), "managedVirtualizationRegionDriver.RequestSetElasticcacheMaintainTime") } mEnd, err := task.GetParams().GetString("maintain_end_time") if err != nil { return errors.Wrap(fmt.Errorf("missing parameter maintain_end_time"), "managedVirtualizationRegionDriver.RequestSetElasticcacheMaintainTime") } iregion, err := ec.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestSetElasticcacheMaintainTime.GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.ExternalId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestSetElasticcacheMaintainTime.GetIElasticcacheById") } err = iec.SetMaintainTime(mStart, mEnd) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestSetElasticcacheMaintainTime.SetMaintainTime") } return cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 10*time.Second, 10*time.Second, 300*time.Second) } func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheChangeSpec(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { sku, err := task.GetParams().GetString("sku_ext_id") if err != nil { return errors.Wrap(fmt.Errorf("missing parameter sku"), "managedVirtualizationRegionDriver.RequestElasticcacheChangeSpec") } provider := ec.GetCloudprovider() if provider == nil { return errors.Wrap(fmt.Errorf("provider is nil"), "managedVirtualizationRegionDriver.RequestElasticcacheChangeSpec.GetCloudprovider") } iregion, err := ec.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheChangeSpec.GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.ExternalId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheChangeSpec.GetIElasticcacheById") } err = iec.ChangeInstanceSpec(sku) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheChangeSpec.ChangeInstanceSpec") } err = cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 10*time.Second, 10*time.Second, 1800*time.Second) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheChangeSpec.ChangeInstanceSpec") } err = ec.SyncWithCloudElasticcache(ctx, userCred, provider, iec) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheChangeSpec.SyncWithCloudElasticcache") } return nil } func (self *SManagedVirtualizationRegionDriver) RequestUpdateElasticcacheAuthMode(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { authMode, err := task.GetParams().GetString("auth_mode") if err != nil { return errors.Wrap(fmt.Errorf("missing parameter auth_mode"), "managedVirtualizationRegionDriver.RequestUpdateElasticcacheAuthMode") } iregion, err := ec.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestUpdateElasticcacheAuthMode.GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.ExternalId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestUpdateElasticcacheAuthMode.GetIElasticcacheById") } noPassword := true if authMode == "on" { noPassword = false } err = iec.UpdateAuthMode(noPassword, "") if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestUpdateElasticcacheAuthMode.UpdateAuthMode") } _, err = db.Update(ec, func() error { ec.AuthMode = authMode return nil }) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestUpdateElasticcacheAuthMode.UpdatedbAuthMode") } return cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 10*time.Second, 10*time.Second, 600*time.Second) } func (self *SManagedVirtualizationRegionDriver) RequestUpdateElasticcacheSecgroups(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { // todo: finish me return nil } func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheSetMaintainTime(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { startTime, err := task.GetParams().GetString("maintain_start_time") if err != nil { return errors.Wrap(fmt.Errorf("missing parameter maintain_start_time"), "managedVirtualizationRegionDriver.RequestElasticcacheSetMaintainTime") } endTime, err := task.GetParams().GetString("maintain_end_time") if err != nil { return errors.Wrap(fmt.Errorf("missing parameter maintain_end_time"), "managedVirtualizationRegionDriver.RequestElasticcacheSetMaintainTime") } iregion, err := ec.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheSetMaintainTime.GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.ExternalId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheSetMaintainTime.GetIElasticcacheById") } err = iec.SetMaintainTime(startTime, endTime) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheSetMaintainTime.SetMaintainTime") } // todo: sync instance spec return cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 10*time.Second, 10*time.Second, 300*time.Second) } func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheAllocatePublicConnection(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { port, _ := task.GetParams().Int("port") iregion, err := ec.GetIRegion(ctx) if err != nil { return nil, errors.Wrap(err, "GerIRegion") } iec, err := iregion.GetIElasticcacheById(ec.ExternalId) if err != nil { return nil, errors.Wrapf(err, "GetIElasticcacheById(%s)", ec.ExternalId) } _, err = iec.AllocatePublicConnection(int(port)) if err != nil { return nil, errors.Wrapf(err, "AllocatePublicConnection(%d)", port) } err = cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 10*time.Second, 10*time.Second, 300*time.Second) if err != nil { return nil, errors.Wrap(err, "WaitStatusWithDelay") } err = ec.SyncWithCloudElasticcache(ctx, task.GetUserCred(), ec.GetCloudprovider(), iec) if err != nil { return nil, errors.Wrap(err, "SyncWithCloudElasticcache") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheReleasePublicConnection(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iregion, err := ec.GetIRegion(ctx) if err != nil { return nil, errors.Wrap(err, "GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.ExternalId) if err != nil { return nil, errors.Wrapf(err, "GetIElasticcacheById(%s)", ec.ExternalId) } err = iec.ReleasePublicConnection() if err != nil { return nil, errors.Wrap(err, "ReleasePublicConnection") } err = cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 10*time.Second, 10*time.Second, 300*time.Second) if err != nil { return nil, errors.Wrap(errors.ErrTimeout, "WaitStatusWithDelay") } err = ec.SyncWithCloudElasticcache(ctx, task.GetUserCred(), ec.GetCloudprovider(), iec) if err != nil { return nil, errors.Wrap(err, "SyncWithCloudElasticcache") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheFlushInstance(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { iregion, err := ec.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheFlushInstance.GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.ExternalId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheFlushInstance.GetIElasticcacheById") } password, _ := task.GetParams().GetString("password") input := cloudprovider.SCloudElasticCacheFlushInstanceInput{} if len(password) > 0 { input.Password = password } else { if info, err := ec.GetDetailsLoginInfo(ctx, userCred, jsonutils.NewDict()); err == nil && info != nil { pwd, _ := info.GetString("password") input.Password = pwd } } err = iec.FlushInstance(input) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheFlushInstance.FlushInstance") } // todo: sync instance spec return cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 10*time.Second, 10*time.Second, 300*time.Second) } func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheUpdateInstanceParameters(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { parameters, err := task.GetParams().Get("parameters") if err != nil { return errors.Wrap(fmt.Errorf("missing parameter parameters"), "managedVirtualizationRegionDriver.RequestElasticcacheUpdateInstanceParameters") } iregion, err := ec.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheUpdateInstanceParameters.GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.ExternalId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheUpdateInstanceParameters.GetIElasticcacheById") } err = iec.UpdateInstanceParameters(parameters) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheUpdateInstanceParameters.UpdateInstanceParameters") } // todo: sync instance spec return cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 10*time.Second, 10*time.Second, 300*time.Second) } func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheUpdateBackupPolicy(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { backupType, _ := task.GetParams().GetString("backup_type") backupReservedDays, _ := task.GetParams().Int("backup_reserved_days") preferredBackupPeriod, _ := task.GetParams().GetString("preferred_backup_period") preferredBackupTime, _ := task.GetParams().GetString("preferred_backup_time") config := cloudprovider.SCloudElasticCacheBackupPolicyUpdateInput{ BackupType: backupType, BackupReservedDays: int(backupReservedDays), PreferredBackupPeriod: preferredBackupPeriod, PreferredBackupTime: preferredBackupTime, } iregion, err := ec.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheUpdateBackupPolicy.GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.ExternalId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheUpdateBackupPolicy.GetIElasticcacheById") } err = iec.UpdateBackupPolicy(config) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheUpdateBackupPolicy.UpdateBackupPolicy") } // todo: sync instance spec return cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 10*time.Second, 10*time.Second, 300*time.Second) } func (self *SManagedVirtualizationRegionDriver) ValidateCreateElasticcacheAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { reservedNames := []string{ "add", "admin", "all", "alter", "analyze", "and", "as", "asc", "asensitive", "aurora", "before", "between", "bigint", "binary", "blob", "both", "by", "call", "cascade", "case", "change", "char", "character", "check", "collate", "column", "condition", "connection", "constraint", "continue", "convert", "create", "cross", "current_date", "current_time", "current_timestamp", "current_user", "cursor", " database", "databases", "day_hour", "day_microsecond", "day_minute", "day_second", "dec", "decimal", "declare", "default", "delayed", "delete", "desc", "describe", "deterministic", "distinct", "distinctrow", "div", "double", "drc_rds", "drop", "dual", "each", "eagleye", "else", "elseif", "enclosed", "escaped", "exists", "exit", "explain", "false", "fetch", "float", "float4", "float8", "for", "force", "foreign", "from", "fulltext", " goto", "grant", "group", "guest", "having", "high_priority", "hour_microsecond", "hour_minute", "hour_second", "if", "ignore", "in", "index", "infile", "information_schema", "inner", "inout", "insensitive", "insert", "int", "int1", "int2", "int3", "int4", "int8", "integer", "interval", "into", "is", "iterate", "join", "key", "keys", "kill", "label", "leading", "leave", "left", "like", "limit", "linear", "lines", "load", "localtime", "localtimestamp", "lock", "long", "longblob", "longtext", "loop", "low_priority", " match", "mediumblob", "mediumint", "mediumtext", "middleint", "minute_microsecond", "minute_second", "mod", "modifies", "mysql", "natural", "no_write_to_binlog", "not", "null", "numeric", "on", "optimize", "option", "optionally", "or", "order", "out", "outer", "outfile", "precision", "primary", "procedure", "purge", "raid0", "range", "read", "reads", "real", "references", "regexp", "release", "rename", "repeat", "replace", "replicator", "require", "restrict", "return", "revoke", "right", "rlike", "root", "schema", "schemas", "second_microsecond", "select", "sensitive", "separator", "set", "show", "smallint", "spatial", "specific", "sql", "sql_big_result", "sql_calc_found_rows", "sql_small_result", "sqlexception", "sqlstate", "sqlwarning", "ssl", "starting", "straight_join", "table", "terminated", "test", "then", "tinyblob", "tinyint", "tinytext", "to", "trailing", "trigger", "true", "undo", "union", "unique", "unlock", "unsigned", "update", "usage", "use", "using", "utc_date", "utc_time", "utc_timestamp", "values", "varbinary", "varchar", "varcharacter", "varying", "when", "where", "while", "with", "write", "x509", "xor", "xtrabak", "year_month", "zerofill"} if name, _ := data.GetString("name"); utils.IsInStringArray(name, reservedNames) { return nil, httperrors.NewConflictError("account name '%s' is not allowed", name) } return data, nil } func (self *SManagedVirtualizationRegionDriver) ValidateCreateElasticcacheAclData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { ips, err := data.GetString("ip_list") if err != nil || ips == "" { return nil, httperrors.NewMissingParameterError("ip_list") } ipV := validators.NewIPv4AddrValidator("ip") cidrV := validators.NewIPv4PrefixValidator("ip") _ips := strings.Split(ips, ",") for _, ip := range _ips { params := jsonutils.NewDict() params.Set("ip", jsonutils.NewString(ip)) if strings.Contains(ip, "/") { if err := cidrV.Validate(ctx, params); err != nil { return nil, err } } else { if err := ipV.Validate(ctx, params); err != nil { return nil, err } } } elasticcacheV := validators.NewModelIdOrNameValidator("elasticcache", "elasticcache", ownerId) if err := elasticcacheV.Validate(ctx, data); err != nil { return nil, err } return data, nil } func (self *SManagedVirtualizationRegionDriver) AllowCreateElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, elasticcache *models.SElasticcache) error { return nil } func (self *SManagedVirtualizationRegionDriver) ValidateCreateElasticcacheBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { elasticcacheV := validators.NewModelIdOrNameValidator("elasticcache", "elasticcache", ownerId) if err := elasticcacheV.Validate(ctx, data); err != nil { return nil, err } ec := elasticcacheV.Model.(*models.SElasticcache) if !utils.IsInStringArray(ec.Status, []string{api.ELASTIC_CACHE_STATUS_RUNNING}) { return nil, httperrors.NewInputParameterError("can not make backup in status %s", ec.Status) } data.Set("backup_mode", jsonutils.NewString(api.BACKUP_MODE_MANUAL)) return data, nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateElasticcacheAccount(ctx context.Context, userCred mcclient.TokenCredential, elasticcacheAccount *models.SElasticcacheAccount, task taskman.ITask) error { return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateElasticcacheAcl(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheAcl, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { _ec, err := db.FetchById(models.ElasticcacheManager, ea.ElasticcacheId) if err != nil { return nil, errors.Wrap(nil, "managedVirtualizationRegionDriver.CreateElasticcacheAcl.GetElasticcache") } ec := _ec.(*models.SElasticcache) iregion, err := ec.GetIRegion(ctx) if err != nil { return nil, errors.Wrap(nil, "managedVirtualizationRegionDriver.CreateElasticcacheAcl.GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.GetExternalId()) if err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheAcl.GetIElasticcacheById") } iea, err := iec.CreateAcl(ea.Name, ea.IpList) if err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheAcl.CreateAcl") } // todo: wait elastic cache instance running ea.SetModelManager(models.ElasticcacheAclManager, ea) if err := db.SetExternalId(ea, userCred, iea.GetGlobalId()); err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheAcl.SetExternalId") } if err := ea.SyncWithCloudElasticcacheAcl(ctx, userCred, iea); err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheAcl.SyncWithCloudElasticcache") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestChangeDBInstanceConfig(ctx context.Context, userCred mcclient.TokenCredential, rds *models.SDBInstance, input *api.SDBInstanceChangeConfigInput, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { conf := cloudprovider.SManagedDBInstanceChangeConfig{} if input.DiskSizeGB > 0 && input.DiskSizeGB != rds.DiskSizeGB { conf.DiskSizeGB = input.DiskSizeGB } if len(input.InstanceType) > 0 && input.InstanceType != rds.InstanceType { conf.InstanceType = input.InstanceType } iRds, err := rds.GetIDBInstance(ctx) if err != nil { return nil, errors.Wrap(err, "rds.GetIDBInstance") } log.Infof("change config: %s", jsonutils.Marshal(conf).String()) err = iRds.ChangeConfig(ctx, &conf) if err != nil { return nil, errors.Wrapf(err, "iRds.ChangeConfig") } err = cloudprovider.WaitStatus(iRds, api.DBINSTANCE_RUNNING, time.Second*10, time.Minute*40) if err != nil { return nil, errors.Wrapf(err, "cloudprovider.WaitStatus") } err = iRds.Refresh() if err != nil { return nil, errors.Wrapf(err, "iRds.Refresh") } _, err = db.Update(rds, func() error { rds.InstanceType = iRds.GetInstanceType() rds.Category = iRds.GetCategory() rds.VcpuCount = iRds.GetVcpuCount() rds.VmemSizeMb = iRds.GetVmemSizeMB() rds.StorageType = iRds.GetStorageType() rds.DiskSizeGB = iRds.GetDiskSizeGB() return nil }) if err != nil { return nil, errors.Wrapf(err, "db.Update(instance)") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateDBInstanceBackup(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, backup *models.SDBInstanceBackup, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iRds, err := instance.GetIDBInstance(ctx) if err != nil { return nil, errors.Wrap(err, "instance.GetIDBInstance") } desc := &cloudprovider.SDBInstanceBackupCreateConfig{ Name: backup.Name, } if len(backup.DBNames) > 0 { desc.Databases = strings.Split(backup.DBNames, ",") } backupId, err := iRds.CreateIBackup(desc) if err != nil { return nil, errors.Wrap(err, "iRds.CreateBackup") } err = db.SetExternalId(backup, userCred, backupId) if err != nil { return nil, errors.Wrapf(err, "db.SetExternalId") } err = cloudprovider.Wait(time.Second*5, time.Minute*15, func() (bool, error) { iBackup, err := backup.GetIDBInstanceBackup(ctx) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { log.Warningf("GetIDBInstanceBackup: %v", err) return false, nil } return false, errors.Wrapf(err, "GetIDBInstanceBackup") } err = backup.SyncWithCloudDBInstanceBackup(ctx, userCred, iBackup, instance.GetCloudprovider()) if err != nil { log.Warningf("sync backup info error: %v", err) } return true, nil }) if err != nil { return nil, errors.Wrapf(err, "cloudprovider.Wait backup sync") } instance.SetStatus(ctx, userCred, api.DBINSTANCE_RUNNING, "") return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) ValidateResetDBInstancePassword(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, account string) error { 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(ctx) if err != nil { return nil, errors.Wrap(err, "instance.GetIDBInstance") } oldTags, err := iRds.GetTags() if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } return nil, errors.Wrap(err, "iRds.GetTags()") } tags, err := instance.GetAllUserMetadata() if err != nil { return nil, errors.Wrapf(err, "instance.GetAllUserMetadata") } tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags} err = cloudprovider.SetTags(ctx, iRds, instance.ManagerId, tags, replaceTags) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } logclient.AddActionLogWithStartable(task, instance, logclient.ACT_UPDATE_TAGS, err, userCred, false) return nil, errors.Wrap(err, "iRds.SetTags") } logclient.AddActionLogWithStartable(task, instance, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true) err = iRds.Update(ctx, cloudprovider.SDBInstanceUpdateOptions{NAME: instance.Name, Description: instance.Description}) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } return nil, errors.Wrap(err, "iRds.Update") } return nil, nil }) 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) if err != nil { return nil, errors.Wrap(nil, "managedVirtualizationRegionDriver.CreateElasticcacheBackup.GetElasticcache") } ec := _ec.(*models.SElasticcache) iregion, err := ec.GetIRegion(ctx) if err != nil { return nil, errors.Wrap(nil, "managedVirtualizationRegionDriver.CreateElasticcacheBackup.GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.GetExternalId()) if err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheBackup.GetIElasticcacheById") } ieb, err := iec.CreateBackup(eb.Name) if err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheBackup.CreateBackup") } err = cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 30*time.Second, 30*time.Second, 1800*time.Second) if err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheBackup.WaitStatusWithDelay") } eb.SetModelManager(models.ElasticcacheBackupManager, eb) if err := db.SetExternalId(eb, userCred, ieb.GetGlobalId()); err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheBackup.SetExternalId") } if err := eb.SyncWithCloudElasticcacheBackup(ctx, userCred, ieb); err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheBackup.SyncWithCloudElasticcacheBackup") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteElasticcacheAccount(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheAccount, task taskman.ITask) error { iregion, err := ea.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheAccount.GetIRegion") } _ec, err := db.FetchById(models.ElasticcacheManager, ea.ElasticcacheId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheAccount.FetchById") } ec := _ec.(*models.SElasticcache) iec, err := iregion.GetIElasticcacheById(ec.GetExternalId()) if errors.Cause(err) == cloudprovider.ErrNotFound { return nil } else if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheAccount.GetIElasticcacheById") } iea, err := iec.GetICloudElasticcacheAccount(ea.GetExternalId()) if errors.Cause(err) == cloudprovider.ErrNotFound { return nil } else if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheAccount.GetICloudElasticcacheAccount") } err = iea.Delete() if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheAccount.Delete") } err = cloudprovider.WaitDeleted(iea, 10*time.Second, 300*time.Second) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheAccount.WaitDeleted") } return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteElasticcacheAcl(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheAcl, task taskman.ITask) error { iregion, err := ea.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheAcl.GetIRegion") } _ec, err := db.FetchById(models.ElasticcacheManager, ea.ElasticcacheId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheAcl.FetchElasticcacheById") } ec := _ec.(*models.SElasticcache) iec, err := iregion.GetIElasticcacheById(ec.GetExternalId()) if errors.Cause(err) == cloudprovider.ErrNotFound { return nil } else if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheAcl.GetIElasticcacheById") } iea, err := iec.GetICloudElasticcacheAcl(ea.GetExternalId()) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound { return nil } return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheAcl.GetICloudElasticcacheAccount") } err = iea.Delete() if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheAcl.Delete") } return cloudprovider.WaitDeleted(iea, 10*time.Second, 300*time.Second) } func (self *SManagedVirtualizationRegionDriver) RequestDeleteElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential, eb *models.SElasticcacheBackup, task taskman.ITask) error { iregion, err := eb.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheBackup.GetIRegion") } _ec, err := db.FetchById(models.ElasticcacheAclManager, eb.ElasticcacheId) if err != nil { return err } ec := _ec.(*models.SElasticcache) iec, err := iregion.GetIElasticcacheById(ec.GetExternalId()) if errors.Cause(err) == cloudprovider.ErrNotFound { return nil } else if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheBackup.GetIElasticcacheById") } ieb, err := iec.GetICloudElasticcacheBackup(eb.GetExternalId()) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheBackup.GetICloudElasticcacheBackup") } err = ieb.Delete() if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestDeleteElasticcacheBackup.Delete") } return cloudprovider.WaitDeleted(ieb, 10*time.Second, 300*time.Second) } func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheAccountResetPassword(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheAccount, task taskman.ITask) error { iregion, err := ea.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheAccountResetPassword.GetIRegion") } _ec, err := db.FetchById(models.ElasticcacheManager, ea.ElasticcacheId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheAccountResetPassword.FetchById") } ec := _ec.(*models.SElasticcache) iec, err := iregion.GetIElasticcacheById(ec.GetExternalId()) if errors.Cause(err) == cloudprovider.ErrNotFound { return nil } else if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheAccountResetPassword.GetIElasticcacheById") } iea, err := iec.GetICloudElasticcacheAccount(ea.GetExternalId()) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheAccountResetPassword.GetICloudElasticcacheBackup") } input := cloudprovider.SCloudElasticCacheAccountUpdateInput{} passwd, _ := task.GetParams().GetString("password") input.Password = &passwd err = iea.UpdateAccount(input) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheAccountResetPassword.UpdateAccount") } err = ea.SavePassword(passwd) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheAccountResetPassword.SavePassword") } return ea.SetStatus(ctx, userCred, api.ELASTIC_CACHE_ACCOUNT_STATUS_AVAILABLE, "") } func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheAclUpdate(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheAcl, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { _ec, err := db.FetchById(models.ElasticcacheManager, ea.ElasticcacheId) if err != nil { return nil, errors.Wrap(nil, "managedVirtualizationRegionDriver.CreateElasticcacheAcl.GetElasticcache") } ec := _ec.(*models.SElasticcache) iregion, err := ec.GetIRegion(ctx) if err != nil { return nil, errors.Wrap(nil, "managedVirtualizationRegionDriver.CreateElasticcacheAcl.GetIRegion") } iec, err := iregion.GetIElasticcacheById(ec.GetExternalId()) if err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheAcl.GetIElasticcacheById") } iea, err := iec.GetICloudElasticcacheAcl(ea.ExternalId) if err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheAcl.GetICloudElasticcacheAcl") } ipList, _ := task.GetParams().GetString("ip_list") err = iea.UpdateAcl(ipList) if err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheAcl.UpdateAcl") } err = ea.SetStatus(ctx, userCred, api.ELASTIC_CACHE_ACL_STATUS_AVAILABLE, "") if err != nil { return nil, errors.Wrap(err, "managedVirtualizationRegionDriver.CreateElasticcacheAcl.UpdateAclStatus") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheBackupRestoreInstance(ctx context.Context, userCred mcclient.TokenCredential, eb *models.SElasticcacheBackup, task taskman.ITask) error { iregion, err := eb.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheBackupRestoreInstance.GetIRegion") } _ec, err := db.FetchById(models.ElasticcacheManager, eb.ElasticcacheId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheBackupRestoreInstance.FetchById") } ec := _ec.(*models.SElasticcache) iec, err := iregion.GetIElasticcacheById(ec.GetExternalId()) if errors.Cause(err) == cloudprovider.ErrNotFound { return nil } else if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheBackupRestoreInstance.GetIElasticcacheById") } ieb, err := iec.GetICloudElasticcacheBackup(eb.GetExternalId()) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheBackupRestoreInstance.GetICloudElasticcacheBackup") } err = ieb.RestoreInstance(ec.ExternalId) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheBackupRestoreInstance.RestoreInstance") } _, err = db.Update(ec, func() error { ec.Status = api.ELASTIC_CACHE_STATUS_BACKUPRECOVERING return nil }) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheBackupRestoreInstance.UpdateStatus") } err = cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 30*time.Second, 30*time.Second, 1800*time.Second) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheBackupRestoreInstance.WaitStatusWithDelay") } _, err = db.Update(ec, func() error { ec.Status = api.ELASTIC_CACHE_STATUS_RUNNING return nil }) if err != nil { return errors.Wrap(err, "managedVirtualizationRegionDriver.RequestElasticcacheBackupRestoreInstance.UpdateStatus") } return nil } func (self *SManagedVirtualizationRegionDriver) AllowUpdateElasticcacheAuthMode(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, elasticcache *models.SElasticcache) error { return nil } func (self *SManagedVirtualizationRegionDriver) RequestSyncDiskStatus(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iDisk, err := disk.GetIDisk(ctx) if err != nil { return nil, errors.Wrap(err, "disk.GetIDisk") } return nil, disk.SetStatus(ctx, userCred, iDisk.GetStatus(), "syncstatus") }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestSyncDiskBackupStatus(ctx context.Context, userCred mcclient.TokenCredential, backup *models.SDiskBackup, task taskman.ITask) error { return fmt.Errorf("Not Implement RequestSyncDiskBackupStatus") } func (self *SManagedVirtualizationRegionDriver) RequestSyncSnapshotStatus(ctx context.Context, userCred mcclient.TokenCredential, snapshot *models.SSnapshot, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iRegion, err := snapshot.GetISnapshotRegion(ctx) if err != nil { return nil, errors.Wrap(err, "snapshot.GetISnapshotRegion") } iSnapshot, err := iRegion.GetISnapshotById(snapshot.ExternalId) if err != nil { return nil, errors.Wrapf(err, "iRegion.GetISnapshotById(%s)", snapshot.ExternalId) } return nil, snapshot.SetStatus(ctx, userCred, iSnapshot.GetStatus(), "syncstatus") }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestSyncNatGatewayStatus(ctx context.Context, userCred mcclient.TokenCredential, nat *models.SNatGateway, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iNat, err := nat.GetINatGateway(ctx) if err != nil { return nil, errors.Wrap(err, "nat.GetINatGateway") } return nil, nat.SyncWithCloudNatGateway(ctx, userCred, nat.GetCloudprovider(), iNat) }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestSyncBucketStatus(ctx context.Context, userCred mcclient.TokenCredential, bucket *models.SBucket, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iBucket, err := bucket.GetIBucket(ctx) if err != nil { return nil, errors.Wrap(err, "bucket.GetIBucket") } return nil, bucket.SyncWithCloudBucket(ctx, userCred, iBucket, false) }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestSyncDBInstanceBackupStatus(ctx context.Context, userCred mcclient.TokenCredential, backup *models.SDBInstanceBackup, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iDBInstanceBackup, err := backup.GetIDBInstanceBackup(ctx) if err != nil { return nil, errors.Wrap(err, "backup.GetIDBInstanceBackup") } return nil, backup.SetStatus(ctx, userCred, iDBInstanceBackup.GetStatus(), "syncstatus") }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestSyncElasticcacheStatus(ctx context.Context, userCred mcclient.TokenCredential, elasticcache *models.SElasticcache, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iRegion, err := elasticcache.GetIRegion(ctx) if err != nil { return nil, errors.Wrap(err, "elasticcache.GetIRegion") } iElasticcache, err := iRegion.GetIElasticcacheById(elasticcache.ExternalId) if err != nil { return nil, errors.Wrap(err, "elasticcache.GetIElasticcache") } if account := elasticcache.GetCloudaccount(); account != nil { models.SyncVirtualResourceMetadata(ctx, userCred, elasticcache, iElasticcache, account.ReadOnly) } return nil, elasticcache.SetStatus(ctx, userCred, iElasticcache.GetStatus(), "syncstatus") }) 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(ctx) if err != nil { return nil, errors.Wrap(err, "elasticcache.GetIRegion") } iElasticcache, err := iRegion.GetIElasticcacheById(elasticcache.ExternalId) if err != nil { return nil, errors.Wrapf(err, "GetIElasticcacheById(%s)", elasticcache.ExternalId) } oldTags, err := iElasticcache.GetTags() if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } return nil, errors.Wrap(err, "iElasticcache.GetTags()") } tags, err := elasticcache.GetAllUserMetadata() if err != nil { return nil, errors.Wrapf(err, "GetAllUserMetadata") } tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags} mangerId := "" if vpc, _ := elasticcache.GetVpc(); vpc != nil { mangerId = vpc.ManagerId } err = cloudprovider.SetTags(ctx, iElasticcache, mangerId, tags, replaceTags) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } logclient.AddActionLogWithStartable(task, elasticcache, logclient.ACT_UPDATE_TAGS, err, userCred, false) return nil, errors.Wrap(err, "iElasticcache.SetTags") } logclient.AddActionLogWithStartable(task, elasticcache, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true) return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestSyncSecgroupsForElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { // sync secgroups to cloud secgroupExternalIds := []string{} { vpc, err := ec.GetVpc() if err != nil { return nil, errors.Wrapf(err, "GetVpc") } region, err := vpc.GetRegion() if err != nil { return nil, errors.Wrapf(err, "GetRegion") } secgroups, err := ec.GetSecgroups() if err != nil { return nil, errors.Wrapf(err, "GetSecgroups") } driver := region.GetDriver() ownerId := ec.GetOwnerId() for i := range secgroups { if secgroups[i].Id == api.SECGROUP_DEFAULT_ID { filter, err := driver.GetSecurityGroupFilter(vpc) if err != nil { return nil, errors.Wrapf(err, "GetSecurityGroupFilter") } group, err := vpc.GetDefaultSecurityGroup(ownerId, filter) if err != nil && errors.Cause(err) != sql.ErrNoRows { return nil, err } if gotypes.IsNil(group) { group, err = driver.CreateDefaultSecurityGroup(ctx, userCred, ownerId, vpc) if err != nil { return nil, errors.Wrapf(err, "CreateDefaultSecurityGroup") } } if !utils.IsInStringArray(group.ExternalId, secgroupExternalIds) { secgroupExternalIds = append(secgroupExternalIds, group.ExternalId) } continue } if !utils.IsInStringArray(secgroups[i].ExternalId, secgroupExternalIds) { secgroupExternalIds = append(secgroupExternalIds, secgroups[i].ExternalId) } } } ret := jsonutils.NewDict() ret.Set("ext_secgroup_ids", jsonutils.NewStringArray(secgroupExternalIds)) return ret, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestRenewElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, bc billing.SBillingCycle) error { iregion, err := ec.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "GetIRegion") } if len(ec.GetExternalId()) == 0 { return errors.Wrap(err, "ExternalId is empty") } iec, err := iregion.GetIElasticcacheById(ec.GetExternalId()) if err != nil { return errors.Wrap(err, "GetIElasticcacheById") } oldExpired := iec.GetExpiredAt() err = iec.Renew(bc) if err != nil { return err } //避免有些云续费后过期时间刷新比较慢问题 cloudprovider.WaitCreated(15*time.Second, 5*time.Minute, func() bool { err := iec.Refresh() if err != nil { log.Errorf("failed refresh instance %s error: %v", ec.Name, err) } newExipred := iec.GetExpiredAt() if newExipred.After(oldExpired) { return true } return false }) db.Update(ec, func() error { ec.ExpiredAt = iec.GetExpiredAt() return nil }) return nil } func (self *SManagedVirtualizationRegionDriver) IsSupportedElasticcacheAutoRenew() bool { return true } func (self *SManagedVirtualizationRegionDriver) RequestElasticcacheSetAutoRenew(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, autoRenew bool, task taskman.ITask) error { iregion, err := ec.GetIRegion(ctx) if err != nil { return errors.Wrap(err, "GetIRegion") } if len(ec.GetExternalId()) == 0 { return errors.Wrap(err, "ExternalId is empty") } iec, err := iregion.GetIElasticcacheById(ec.GetExternalId()) if err != nil { return errors.Wrap(err, "GetIElasticcacheById") } bc := billing.SBillingCycle{} bc.AutoRenew = autoRenew err = iec.SetAutoRenew(bc) if err != nil { return errors.Wrap(err, "SetAutoRenew") } return ec.SetAutoRenew(autoRenew) } func IsInPrivateIpRange(ar netutils.IPV4AddrRange) error { iprs := netutils.GetPrivateIPRanges() match := false for _, ipr := range iprs { if ipr.ContainsRange(ar) { match = true break } } if !match { return httperrors.NewInputParameterError("invalid cidr range %s", ar.String()) } return nil } func (self *SManagedVirtualizationRegionDriver) RequestSyncRdsSecurityGroups(ctx context.Context, userCred mcclient.TokenCredential, rds *models.SDBInstance, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { secgroups, err := rds.GetSecgroups() if err != nil { return nil, errors.Wrapf(err, "GetSecgroups") } vpc, err := rds.GetVpc() if err != nil { return nil, errors.Wrapf(err, "GetVpc") } region, err := vpc.GetRegion() if err != nil { return nil, errors.Wrapf(err, "GetRegion") } driver := region.GetDriver() ownerId := rds.GetOwnerId() secgroupIds := []string{} for i := range secgroups { if secgroups[i].Id == api.SECGROUP_DEFAULT_ID { filter, err := driver.GetSecurityGroupFilter(vpc) if err != nil { return nil, errors.Wrapf(err, "GetSecurityGroupFilter") } group, err := vpc.GetDefaultSecurityGroup(ownerId, filter) if err != nil && errors.Cause(err) != sql.ErrNoRows { return nil, err } if gotypes.IsNil(group) { group, err = driver.CreateDefaultSecurityGroup(ctx, userCred, ownerId, vpc) if err != nil { return nil, errors.Wrapf(err, "CreateDefaultSecurityGroup") } } if !utils.IsInStringArray(group.ExternalId, secgroupIds) { secgroupIds = append(secgroupIds, group.ExternalId) } continue } if !utils.IsInStringArray(secgroups[i].ExternalId, secgroupIds) { secgroupIds = append(secgroupIds, secgroups[i].ExternalId) } } iRds, err := rds.GetIDBInstance(ctx) if err != nil { return nil, errors.Wrapf(err, "GetIDBInstance") } err = iRds.SetSecurityGroups(secgroupIds) if err != nil { return nil, errors.Wrapf(err, "SetSecurityGroups") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, eip *models.SElasticip, input api.ElasticipAssociateInput, obj db.IStatusStandaloneModel, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iEip, err := eip.GetIEip(ctx) if err != nil { return nil, errors.Wrapf(err, "eip.GetIEip") } conf := &cloudprovider.AssociateConfig{ InstanceId: input.InstanceExternalId, Bandwidth: eip.Bandwidth, AssociateType: input.InstanceType, ChargeType: string(eip.ChargeType), } err = iEip.Associate(conf) if err != nil { return nil, errors.Wrapf(err, "iEip.Associate") } err = cloudprovider.WaitStatus(iEip, api.EIP_STATUS_READY, 3*time.Second, 60*time.Second) if err != nil { return nil, errors.Wrap(err, "cloudprovider.WaitStatus") } if obj.GetStatus() != api.INSTANCE_ASSOCIATE_EIP { db.StatusBaseSetStatus(ctx, obj, userCred, api.INSTANCE_ASSOCIATE_EIP, "associate eip") } err = eip.AssociateInstance(ctx, userCred, input.InstanceType, obj) if err != nil { return nil, errors.Wrapf(err, "eip.AssociateVM") } eip.SetStatus(ctx, userCred, api.EIP_STATUS_READY, api.EIP_STATUS_ASSOCIATE) return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateNetwork(ctx context.Context, userCred mcclient.TokenCredential, net *models.SNetwork, task taskman.ITask) error { wire, err := net.GetWire() if err != nil { return errors.Wrapf(err, "GetWire") } iwire, err := wire.GetIWire(ctx) if err != nil { return errors.Wrapf(err, "GetIWire") } prefix, err := net.GetPrefix() if err != nil { return errors.Wrapf(err, "GetPrefix") } opts := cloudprovider.SNetworkCreateOptions{ Name: net.Name, Cidr: prefix.String(), Desc: net.Description, } opts.AssignPublicIp, _ = task.GetParams().Bool("assign_public_ip") provider := wire.GetCloudprovider() opts.ProjectId, err = provider.SyncProject(ctx, userCred, net.ProjectId) if err != nil { if errors.Cause(err) != cloudprovider.ErrNotSupported && errors.Cause(err) != cloudprovider.ErrNotImplemented { logclient.AddSimpleActionLog(net, logclient.ACT_SYNC_CLOUD_PROJECT, err, userCred, false) } } inet, err := iwire.CreateINetwork(&opts) if err != nil { return errors.Wrapf(err, "CreateINetwork") } err = db.SetExternalId(net, userCred, inet.GetGlobalId()) if err != nil { return errors.Wrapf(err, "db.SetExternalId") } err = cloudprovider.WaitStatus(inet, api.NETWORK_STATUS_AVAILABLE, 10*time.Second, 5*time.Minute) if err != nil { return errors.Wrapf(err, "wait network available after 5 minutes, current status: %s", inet.GetStatus()) } return net.SyncWithCloudNetwork(ctx, userCred, inet) } func (self *SManagedVirtualizationRegionDriver) RequestRemoteUpdateElasticSearch(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SElasticSearch, replaceTags bool, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { ies, err := instance.GetIElasticSearch(ctx) if err != nil { return nil, errors.Wrap(err, "instance.GetIESInstance") } oldTags, err := ies.GetTags() if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } return nil, errors.Wrap(err, "ies.GetTags()") } tags, err := instance.GetAllUserMetadata() if err != nil { return nil, errors.Wrapf(err, "instance.GetAllUserMetadata") } tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags} err = cloudprovider.SetTags(ctx, ies, instance.ManagerId, tags, replaceTags) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } logclient.AddActionLogWithStartable(task, instance, logclient.ACT_UPDATE_TAGS, err, userCred, false) return nil, errors.Wrap(err, "ies.SetTags") } logclient.AddActionLogWithStartable(task, instance, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true) return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestRemoteUpdateKafka(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SKafka, replaceTags bool, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { kafka, err := instance.GetIKafka(ctx) if err != nil { return nil, errors.Wrap(err, "instance.GetIKafka") } oldTags, err := kafka.GetTags() if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } return nil, errors.Wrap(err, "ies.GetTags()") } tags, err := instance.GetAllUserMetadata() if err != nil { return nil, errors.Wrapf(err, "instance.GetAllUserMetadata") } tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags} err = cloudprovider.SetTags(ctx, kafka, instance.ManagerId, tags, replaceTags) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } logclient.AddActionLogWithStartable(task, instance, logclient.ACT_UPDATE_TAGS, err, userCred, false) return nil, errors.Wrap(err, "ies.SetTags") } logclient.AddActionLogWithStartable(task, instance, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true) return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) ValidateCreateKubeClusterData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input *api.KubeClusterCreateInput) (*api.KubeClusterCreateInput, error) { return input, nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateKubeCluster(ctx context.Context, userCred mcclient.TokenCredential, cluster *models.SKubeCluster, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { opts := &cloudprovider.KubeClusterCreateOptions{ NAME: cluster.Name, Desc: cluster.Description, Version: cluster.Version, NetworkIds: []string{}, } vpc, err := cluster.GetVpc() if err != nil { return nil, errors.Wrapf(err, "cluster.GetVpc") } opts.VpcId = vpc.ExternalId networks, err := cluster.GetNetworks() if err != nil { return nil, errors.Wrapf(err, "GetNetworks") } for _, net := range networks { opts.NetworkIds = append(opts.NetworkIds, net.ExternalId) } opts.Tags, _ = cluster.GetAllUserMetadata() params := task.GetParams() opts.ServiceCIDR, _ = params.GetString("service_cidr") opts.RoleName, _ = params.GetString("role_name") opts.PrivateAccess, _ = params.Bool("private_access") opts.PublicAccess, _ = params.Bool("public_access") _, opts.PublicKey, _ = sshkeys.GetSshAdminKeypair(ctx) iregion, err := cluster.GetIRegion(ctx) if err != nil { return nil, errors.Wrapf(err, "GetIRegion") } icluster, err := iregion.CreateIKubeCluster(opts) if err != nil { return nil, errors.Wrapf(err, "CreateIKubeCluster") } err = db.SetExternalId(cluster, userCred, icluster.GetGlobalId()) if err != nil { return nil, errors.Wrapf(err, "db.SetExternalId") } err = cloudprovider.WaitStatusWithSync(icluster, api.KUBE_CLUSTER_STATUS_RUNNING, func(status string) { cluster.SetStatus(ctx, userCred, status, "") }, time.Second*30, time.Hour*1) if err != nil { return nil, errors.Wrapf(err, "wait cluster status timeout, current status: %s", icluster.GetStatus()) } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) ValidateCreateKubeNodePoolData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input *api.KubeNodePoolCreateInput) (*api.KubeNodePoolCreateInput, error) { return input, nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateKubeNodePool(ctx context.Context, userCred mcclient.TokenCredential, pool *models.SKubeNodePool, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { opts := &cloudprovider.KubeNodePoolCreateOptions{ NAME: pool.Name, Desc: pool.Description, MinInstanceCount: pool.MinInstanceCount, MaxInstanceCount: pool.MaxInstanceCount, DesiredInstanceCount: pool.DesiredInstanceCount, RootDiskSizeGb: pool.RootDiskSizeGb, NetworkIds: []string{}, InstanceTypes: []string{}, } opts.PublicKey, _ = task.GetParams().GetString("public_key") if pool.InstanceTypes != nil { for _, instanceType := range *pool.InstanceTypes { opts.InstanceTypes = append(opts.InstanceTypes, instanceType) } } networks, err := pool.GetNetworks() if err != nil { return nil, errors.Wrapf(err, "GetNetworks") } for _, net := range networks { opts.NetworkIds = append(opts.NetworkIds, net.ExternalId) } opts.Tags, _ = pool.GetAllUserMetadata() icluster, err := pool.GetIKubeCluster(ctx) if err != nil { return nil, errors.Wrapf(err, "GetIKubeCluster") } ipool, err := icluster.CreateIKubeNodePool(opts) if err != nil { return nil, errors.Wrapf(err, "CreateIKubeNodePool") } err = db.SetExternalId(pool, userCred, ipool.GetGlobalId()) if err != nil { return nil, errors.Wrapf(err, "db.SetExternalId") } err = cloudprovider.WaitStatus(ipool, api.KUBE_CLUSTER_STATUS_RUNNING, time.Second*30, time.Hour*1) if err != nil { return nil, errors.Wrapf(err, "wait node pool status timeout, current status: %s", icluster.GetStatus()) } return nil, pool.SetStatus(ctx, userCred, api.KUBE_CLUSTER_STATUS_RUNNING, "") }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteSecurityGroup(ctx context.Context, userCred mcclient.TokenCredential, secgroup *models.SSecurityGroup, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iGroup, err := secgroup.GetISecurityGroup(ctx) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotFound || errors.Cause(err) == sql.ErrNoRows { return nil, nil } return nil, errors.Wrapf(err, "GetISecurityGroup") } return nil, iGroup.Delete() }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateSecurityGroup( ctx context.Context, userCred mcclient.TokenCredential, secgroup *models.SSecurityGroup, rules api.SSecgroupRuleResourceSet, ) error { vpcId := "" if len(secgroup.VpcId) > 0 { vpc, err := secgroup.GetVpc() if err != nil { return errors.Wrapf(err, "GetVpc") } vpcId = vpc.ExternalId } provider, err := secgroup.GetCloudprovider() if err != nil { return errors.Wrapf(err, "GetCloudprovider") } iRegion, err := secgroup.GetIRegion(ctx) if err != nil { return errors.Wrapf(err, "GetIRegion") } opts := &cloudprovider.SecurityGroupCreateInput{ Name: secgroup.Name, Desc: secgroup.Description, VpcId: vpcId, } opts.Tags, _ = secgroup.GetAllUserMetadata() opts.ProjectId, err = provider.SyncProject(ctx, userCred, secgroup.ProjectId) if err != nil { if errors.Cause(err) != cloudprovider.ErrNotSupported && errors.Cause(err) != cloudprovider.ErrNotImplemented { logclient.AddSimpleActionLog(secgroup, logclient.ACT_SYNC_CLOUD_PROJECT, err, userCred, false) } } iGroup, err := iRegion.CreateISecurityGroup(opts) if err != nil { return errors.Wrapf(err, "CreateISecurityGroup") } _, err = db.Update(secgroup, func() error { secgroup.ExternalId = iGroup.GetGlobalId() if len(iGroup.GetVpcId()) == 0 { secgroup.VpcId = "" } return nil }) if err != nil { return errors.Wrapf(err, "SetExternalId") } for i := range rules { opts := cloudprovider.SecurityGroupRuleCreateOptions{ Desc: rules[i].Description, Direction: secrules.TSecurityRuleDirection(rules[i].Direction), Action: secrules.TSecurityRuleAction(rules[i].Action), Protocol: rules[i].Protocol, CIDR: rules[i].CIDR, Ports: rules[i].Ports, } _, err := iGroup.CreateRule(&opts) if err != nil { return errors.Wrapf(err, "CreateRule") } } iRules, err := iGroup.GetRules() if err != nil { return errors.Wrapf(err, "GetRules") } result := secgroup.SyncRules(ctx, userCred, iRules) if result.IsError() { return result.AllError() } secgroup.SetStatus(ctx, userCred, api.SECGROUP_STATUS_READY, "") return nil } func (self *SManagedVirtualizationRegionDriver) ValidateCreateSecurityGroupInput(ctx context.Context, userCred mcclient.TokenCredential, input *api.SSecgroupCreateInput) (*api.SSecgroupCreateInput, error) { for i := range input.Rules { rule := input.Rules[i] if !utils.IsInStringArray(rule.Action, []string{string(secrules.SecurityRuleAllow), string(secrules.SecurityRuleDeny)}) { return nil, httperrors.NewInputParameterError("invalid action %s", rule.Action) } if !utils.IsInStringArray(rule.Protocol, []string{ secrules.PROTO_ANY, secrules.PROTO_UDP, secrules.PROTO_TCP, secrules.PROTO_ICMP, }) { return nil, httperrors.NewInputParameterError("invalid protocol %s", rule.Protocol) } if len(rule.Ports) > 0 { r := secrules.SecurityRule{} err := r.ParsePorts(rule.Ports) if err != nil { return nil, httperrors.NewInputParameterError("invalid ports %s", rule.Ports) } } if len(rule.CIDR) > 0 && !regutils.MatchCIDR(rule.CIDR) && !regutils.MatchCIDR6(rule.CIDR) && !regutils.MatchIP4Addr(rule.CIDR) && !regutils.MatchIP6Addr(rule.CIDR) { return nil, httperrors.NewInputParameterError("invalid cidr %s", rule.CIDR) } } return input, nil } func (self *SManagedVirtualizationRegionDriver) ValidateUpdateSecurityGroupRuleInput(ctx context.Context, userCred mcclient.TokenCredential, input *api.SSecgroupRuleUpdateInput) (*api.SSecgroupRuleUpdateInput, error) { if input.Action != nil { if !utils.IsInStringArray(*input.Action, []string{string(secrules.SecurityRuleAllow), string(secrules.SecurityRuleDeny)}) { return nil, httperrors.NewInputParameterError("invalid action %s", *input.Action) } } if input.Protocol != nil { if !utils.IsInStringArray(*input.Protocol, []string{ secrules.PROTO_ANY, secrules.PROTO_UDP, secrules.PROTO_TCP, secrules.PROTO_ICMP, }) { return nil, httperrors.NewInputParameterError("invalid protocol %s", *input.Protocol) } } if input.Ports != nil { rule := secrules.SecurityRule{} err := rule.ParsePorts(*input.Ports) if err != nil { return nil, httperrors.NewInputParameterError("invalid ports %s", *input.Ports) } } if input.CIDR != nil && len(*input.CIDR) > 0 && !regutils.MatchCIDR(*input.CIDR) && !regutils.MatchIP4Addr(*input.CIDR) && !regutils.MatchCIDR6(*input.CIDR) && !regutils.MatchIP6Addr(*input.CIDR) { return nil, httperrors.NewInputParameterError("invalid cidr %s", *input.CIDR) } return input, nil } func (self *SManagedVirtualizationRegionDriver) RequestPrepareSecurityGroups( ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, secgroups []models.SSecurityGroup, vpc *models.SVpc, callback func(ids []string) error, task taskman.ITask, ) error { region, err := vpc.GetRegion() if err != nil { return errors.Wrapf(err, "GetRegion") } driver := region.GetDriver() taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { groupIds := []string{} for i := range secgroups { if secgroups[i].Id == api.SECGROUP_DEFAULT_ID { filter, err := driver.GetSecurityGroupFilter(vpc) if err != nil { return nil, errors.Wrapf(err, "GetSecurityGroupFilter") } group, err := vpc.GetDefaultSecurityGroup(ownerId, filter) if err != nil && errors.Cause(err) != sql.ErrNoRows { return nil, err } if gotypes.IsNil(group) { group, err = driver.CreateDefaultSecurityGroup(ctx, userCred, ownerId, vpc) if err != nil { return nil, errors.Wrapf(err, "CreateDefaultSecurityGroup") } } if !utils.IsInStringArray(group.Id, groupIds) { groupIds = append(groupIds, group.Id) } continue } if len(secgroups[i].ExternalId) > 0 && !utils.IsInStringArray(secgroups[i].Id, groupIds) { groupIds = append(groupIds, secgroups[i].Id) } } if callback != nil { return nil, callback(groupIds) } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) GetSecurityGroupFilter(vpc *models.SVpc) (func(q *sqlchemy.SQuery) *sqlchemy.SQuery, error) { return func(q *sqlchemy.SQuery) *sqlchemy.SQuery { return q.Equals("vpc_id", vpc.Id) }, nil } func (self *SManagedVirtualizationRegionDriver) CreateDefaultSecurityGroup( ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, vpc *models.SVpc, ) (*models.SSecurityGroup, error) { region, err := vpc.GetRegion() if err != nil { return nil, errors.Wrapf(err, "GetRegion") } driver := region.GetDriver() newGroup := &models.SSecurityGroup{} newGroup.SetModelManager(models.SecurityGroupManager, newGroup) newGroup.Name = fmt.Sprintf("%s-%d", driver.GetDefaultSecurityGroupNamePrefix(), time.Now().Unix()) newGroup.Description = "auto generage" // 部分云可能不需要vpcId, 创建完安全组后会自动置空 newGroup.VpcId = vpc.Id newGroup.ManagerId = vpc.ManagerId newGroup.CloudregionId = vpc.CloudregionId newGroup.DomainId = ownerId.GetProjectDomainId() newGroup.ProjectId = ownerId.GetProjectId() newGroup.ProjectSrc = string(apis.OWNER_SOURCE_LOCAL) err = models.SecurityGroupManager.TableSpec().Insert(ctx, newGroup) if err != nil { return nil, errors.Wrapf(err, "insert") } err = driver.RequestCreateSecurityGroup(ctx, userCred, newGroup, api.SSecgroupRuleResourceSet{}) if err != nil { return nil, errors.Wrapf(err, "RequestCreateSecurityGroup") } return newGroup, nil } func (self *SManagedVirtualizationRegionDriver) ValidateCreateSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, region *models.SCloudregion, input *api.SSnapshotPolicyCreateInput) (*api.SSnapshotPolicyCreateInput, error) { if len(input.CloudproviderId) == 0 { return nil, httperrors.NewMissingParameterError("cloudprovider_id") } managerObj, err := validators.ValidateModel(ctx, userCred, models.CloudproviderManager, &input.CloudproviderId) if err != nil { return nil, err } input.ManagerId = input.CloudproviderId manager := managerObj.(*models.SCloudprovider) if manager.Provider != region.Provider { return nil, httperrors.NewConflictError("manager %s is not %s cloud", manager.Name, region.Provider) } return input, nil } func (self *SManagedVirtualizationRegionDriver) RequestCreateSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, region *models.SCloudregion, sp *models.SSnapshotPolicy, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iRegion, err := sp.GetIRegion(ctx) if err != nil { return nil, errors.Wrapf(err, "GetIRegion") } opts := &cloudprovider.SnapshotPolicyInput{ Name: sp.Name, Desc: sp.Description, RetentionDays: sp.RetentionDays, TimePoints: sp.TimePoints, RepeatWeekdays: sp.RepeatWeekdays, } opts.Tags, _ = sp.GetAllUserMetadata() id, err := iRegion.CreateSnapshotPolicy(opts) if err != nil { return nil, errors.Wrapf(err, "CreateSnapshotPolicy") } _, err = db.Update(sp, func() error { sp.ExternalId = id sp.Status = apis.STATUS_AVAILABLE return nil }) return nil, err }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestDeleteSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, region *models.SCloudregion, sp *models.SSnapshotPolicy, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iPolicy, err := sp.GetISnapshotPolicy(ctx) if err != nil { if errors.Cause(err) == sql.ErrNoRows || errors.Cause(err) == cloudprovider.ErrNotFound { return nil, nil } return nil, errors.Wrapf(err, "GetISnapshotPolicy") } err = iPolicy.Delete() if err != nil { return nil, errors.Wrapf(err, "Delete") } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestSnapshotPolicyBindDisks(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, diskIds []string, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iPolicy, err := sp.GetISnapshotPolicy(ctx) if err != nil { return nil, errors.Wrapf(err, "GetISnapshotPolicy") } disks, err := sp.GetUnbindDisks(diskIds) if err != nil { return nil, errors.Wrapf(err, "GetUnbindDisks") } externalIds := []string{} for _, disk := range disks { if len(disk.ExternalId) > 0 && !utils.IsInStringArray(disk.ExternalId, externalIds) { externalIds = append(externalIds, disk.ExternalId) } } if len(externalIds) > 0 { err = iPolicy.ApplyDisks(externalIds) if err != nil { return nil, errors.Wrapf(err, "ApplyDisks %s", externalIds) } return nil, sp.BindDisks(ctx, disks) } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestSnapshotPolicyUnbindDisks(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, diskIds []string, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iPolicy, err := sp.GetISnapshotPolicy(ctx) if err != nil { return nil, errors.Wrapf(err, "GetISnapshotPolicy") } disks, err := sp.GetBindDisks(diskIds) if err != nil { return nil, errors.Wrapf(err, "GetBindDisks") } externalIds := []string{} for _, disk := range disks { if len(disk.ExternalId) > 0 && !utils.IsInStringArray(disk.ExternalId, externalIds) { externalIds = append(externalIds, disk.ExternalId) } } if len(externalIds) > 0 { err = iPolicy.CancelDisks(externalIds) if err != nil { return nil, errors.Wrapf(err, "CancelDisks %s", externalIds) } return nil, sp.UnbindDisks(diskIds) } return nil, nil }) return nil } func (self *SManagedVirtualizationRegionDriver) RequestRemoteUpdateNetwork(ctx context.Context, userCred mcclient.TokenCredential, net *models.SNetwork, replaceTags bool, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { iNet, err := net.GetINetwork(ctx) if err != nil { return nil, errors.Wrap(err, "GetINetwork") } vpc, err := net.GetVpc() if err != nil { return nil, errors.Wrapf(err, "GetVpc") } oldTags, err := iNet.GetTags() if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } return nil, errors.Wrap(err, "GetTags()") } tags, err := net.GetAllUserMetadata() if err != nil { return nil, errors.Wrapf(err, "GetAllUserMetadata") } tagsUpdateInfo := cloudprovider.TagsUpdateInfo{OldTags: oldTags, NewTags: tags} err = cloudprovider.SetTags(ctx, iNet, vpc.ManagerId, tags, replaceTags) if err != nil { if errors.Cause(err) == cloudprovider.ErrNotSupported || errors.Cause(err) == cloudprovider.ErrNotImplemented { return nil, nil } logclient.AddActionLogWithStartable(task, net, logclient.ACT_UPDATE_TAGS, err, userCred, false) return nil, errors.Wrap(err, "SetTags") } logclient.AddActionLogWithStartable(task, net, logclient.ACT_UPDATE_TAGS, tagsUpdateInfo, userCred, true) return nil, nil }) return nil }