| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package models
- import (
- "context"
- "database/sql"
- "fmt"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/compare"
- "yunion.io/x/pkg/util/netutils"
- "yunion.io/x/pkg/util/rand"
- "yunion.io/x/pkg/util/rbacscope"
- "yunion.io/x/pkg/utils"
- "yunion.io/x/sqlchemy"
- api "yunion.io/x/onecloud/pkg/apis/compute"
- "yunion.io/x/onecloud/pkg/cloudcommon/db"
- "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
- "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
- "yunion.io/x/onecloud/pkg/cloudcommon/validators"
- "yunion.io/x/onecloud/pkg/httperrors"
- "yunion.io/x/onecloud/pkg/mcclient"
- "yunion.io/x/onecloud/pkg/util/stringutils2"
- )
- // +onecloud:swagger-gen-model-singular=loadbalancerbackend
- // +onecloud:swagger-gen-model-plural=loadbalancerbackends
- type SLoadbalancerBackendManager struct {
- SLoadbalancerLogSkipper
- db.SStatusStandaloneResourceBaseManager
- db.SExternalizedResourceBaseManager
- SLoadbalancerBackendgroupResourceBaseManager
- }
- var LoadbalancerBackendManager *SLoadbalancerBackendManager
- func init() {
- LoadbalancerBackendManager = &SLoadbalancerBackendManager{
- SStatusStandaloneResourceBaseManager: db.NewStatusStandaloneResourceBaseManager(
- SLoadbalancerBackend{},
- "loadbalancerbackends_tbl",
- "loadbalancerbackend",
- "loadbalancerbackends",
- ),
- }
- LoadbalancerBackendManager.SetVirtualObject(LoadbalancerBackendManager)
- }
- type SLoadbalancerBackend struct {
- db.SStatusStandaloneResourceBase
- db.SExternalizedResourceBase
- SLoadbalancerBackendgroupResourceBase `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional"`
- BackendId string `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional"`
- BackendType string `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional"`
- BackendRole string `width:"36" charset:"ascii" nullable:"false" list:"user" default:"default" create:"optional"`
- Weight int `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional" update:"user"`
- Address string `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional"`
- Port int `nullable:"false" list:"user" create:"required" update:"user"`
- SendProxy string `width:"16" charset:"ascii" nullable:"false" list:"user" create:"optional" update:"user" default:"off"`
- Ssl string `width:"16" charset:"ascii" nullable:"true" list:"user" create:"optional" update:"user" default:"off"`
- }
- func (manager *SLoadbalancerBackendManager) ResourceScope() rbacscope.TRbacScope {
- return rbacscope.ScopeProject
- }
- func (self *SLoadbalancerBackend) GetOwnerId() mcclient.IIdentityProvider {
- lbbg, err := self.GetLoadbalancerBackendGroup()
- if err != nil {
- return nil
- }
- return lbbg.GetOwnerId()
- }
- func (manager *SLoadbalancerBackendManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
- lbbgId, _ := data.GetString("backend_group_id")
- if len(lbbgId) > 0 {
- lbbg, err := db.FetchById(LoadbalancerBackendGroupManager, lbbgId)
- if err != nil {
- return nil, errors.Wrapf(err, "db.FetchById(LoadbalancerBackendGroupManager, %s)", lbbgId)
- }
- return lbbg.(*SLoadbalancerBackendGroup).GetOwnerId(), nil
- }
- return db.FetchProjectInfo(ctx, data)
- }
- func (man *SLoadbalancerBackendManager) FilterByOwner(ctx context.Context, q *sqlchemy.SQuery, manager db.FilterByOwnerProvider, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, scope rbacscope.TRbacScope) *sqlchemy.SQuery {
- if ownerId != nil {
- sq := LoadbalancerBackendGroupManager.Query("id")
- lb := LoadbalancerManager.Query().SubQuery()
- sq = sq.Join(lb, sqlchemy.Equals(sq.Field("loadbalancer_id"), lb.Field("id")))
- switch scope {
- case rbacscope.ScopeProject:
- sq = sq.Filter(sqlchemy.Equals(lb.Field("tenant_id"), ownerId.GetProjectId()))
- return q.In("backend_group_id", sq.SubQuery())
- case rbacscope.ScopeDomain:
- sq = sq.Filter(sqlchemy.Equals(lb.Field("domain_id"), ownerId.GetProjectDomainId()))
- return q.In("backend_group_id", sq.SubQuery())
- }
- }
- return q
- }
- // 负载均衡后端列表
- func (man *SLoadbalancerBackendManager) ListItemFilter(
- ctx context.Context,
- q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential,
- query api.LoadbalancerBackendListInput,
- ) (*sqlchemy.SQuery, error) {
- q, err := man.SStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.StatusStandaloneResourceListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.ListItemFilter")
- }
- q, err = man.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
- }
- q, err = man.SLoadbalancerBackendgroupResourceBaseManager.ListItemFilter(ctx, q, userCred, query.LoadbalancerBackendGroupFilterListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SLoadbalancerBackendgroupResourceBaseManager.ListItemFilter")
- }
- data := jsonutils.Marshal(query).(*jsonutils.JSONDict)
- q, err = validators.ApplyModelFilters(ctx, q, data, []*validators.ModelFilterOptions{
- {Key: "backend", ModelKeyword: "server", OwnerId: userCred}, // NOTE extend this when new backend_type was added
- })
- if err != nil {
- return nil, err
- }
- if len(query.BackendType) > 0 {
- q = q.In("backend_type", query.BackendType)
- }
- if len(query.BackendRole) > 0 {
- q = q.In("backend_role", query.BackendRole)
- }
- if len(query.Address) > 0 {
- q = q.In("address", query.Address)
- }
- if len(query.SendProxy) > 0 {
- q = q.In("send_proxy", query.SendProxy)
- }
- if len(query.Ssl) > 0 {
- q = q.In("ssl", query.Ssl)
- }
- return q, nil
- }
- func (man *SLoadbalancerBackendManager) OrderByExtraFields(
- ctx context.Context,
- q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential,
- query api.LoadbalancerBackendListInput,
- ) (*sqlchemy.SQuery, error) {
- var err error
- q, err = man.SStatusStandaloneResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StatusStandaloneResourceListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.OrderByExtraFields")
- }
- q, err = man.SLoadbalancerBackendgroupResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.LoadbalancerBackendGroupFilterListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SLoadbalancerBackendgroupResourceBaseManager.OrderByExtraFields")
- }
- return q, nil
- }
- func (man *SLoadbalancerBackendManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
- var err error
- q, err = man.SStatusStandaloneResourceBaseManager.QueryDistinctExtraField(q, field)
- if err == nil {
- return q, nil
- }
- q, err = man.SLoadbalancerBackendgroupResourceBaseManager.QueryDistinctExtraField(q, field)
- if err == nil {
- return q, nil
- }
- return q, httperrors.ErrNotFound
- }
- func (man *SLoadbalancerBackendManager) ValidateBackendVpc(lb *SLoadbalancer, guest *SGuest, backendgroup *SLoadbalancerBackendGroup) error {
- region, err := lb.GetRegion()
- if err != nil {
- return err
- }
- requireStatus := region.GetDriver().GetBackendStatusForAdd()
- if !utils.IsInStringArray(guest.Status, requireStatus) {
- return httperrors.NewUnsupportOperationError("%s requires the virtual machine state to be %s before it can be added backendgroup, but current state of the virtual machine is %s", region.GetDriver().GetProvider(), requireStatus, guest.Status)
- }
- vpc, err := guest.GetVpc()
- if err != nil {
- return httperrors.NewBadRequestError("%s", err)
- }
- if len(lb.VpcId) > 0 {
- lbVpc, err := lb.GetVpc()
- if err != nil {
- return err
- }
- if lbVpc != nil && !lbVpc.IsEmulated && vpc.Id != lb.VpcId {
- return httperrors.NewBadRequestError("guest %s(%s) vpc %s(%s) not same as loadbalancer vpc %s", guest.Name, guest.Id, vpc.Name, vpc.Id, lb.VpcId)
- }
- return nil
- }
- backends, err := backendgroup.GetBackends()
- if err != nil {
- return err
- }
- for _, backend := range backends {
- _server, err := GuestManager.FetchById(backend.BackendId)
- if err != nil {
- return httperrors.NewBadRequestError("failed getting guest %s", backend.BackendId)
- }
- server := _server.(*SGuest)
- _vpc, err := server.GetVpc()
- if err != nil {
- return httperrors.NewBadRequestError("%s", err)
- }
- if _vpc.Id != vpc.Id {
- return httperrors.NewBadRequestError("guest %s(%s) vpc %s(%s) not same as vpc %s(%s)", guest.Name, guest.Id, vpc.Name, vpc.Id, _vpc.Name, _vpc.Id)
- }
- if _server.GetId() == guest.Id {
- return httperrors.NewBadRequestError("guest %s(%s) is already in the backendgroup %s(%s)", guest.Name, guest.Id, backendgroup.Name, backendgroup.Id)
- }
- }
- return nil
- }
- func (man *SLoadbalancerBackendManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential,
- ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject,
- input *api.LoadbalancerBackendCreateInput) (*api.LoadbalancerBackendCreateInput, error) {
- lbbgObj, err := validators.ValidateModel(ctx, userCred, LoadbalancerBackendGroupManager, &input.BackendGroupId)
- if err != nil {
- return nil, err
- }
- lbbg := lbbgObj.(*SLoadbalancerBackendGroup)
- if input.Port < 1 || input.Port > 65535 {
- return input, httperrors.NewInputParameterError("invalid port %d", input.Port)
- }
- if input.Weight < 0 || input.Weight > 100 {
- return input, httperrors.NewInputParameterError("invalid weight %d", input.Weight)
- }
- if len(input.SendProxy) == 0 {
- input.SendProxy = api.LB_SENDPROXY_OFF
- }
- if !utils.IsInStringArray(input.SendProxy, api.LB_SENDPROXY_CHOICES) {
- return input, httperrors.NewInputParameterError("invalid send_proxy %s", input.SendProxy)
- }
- if len(input.Ssl) > 0 && !utils.IsInStringArray(input.Ssl, []string{api.LB_BOOL_ON, api.LB_BOOL_OFF}) {
- return input, httperrors.NewInputParameterError("invalid ssl %s", input.Ssl)
- }
- lb, err := lbbg.GetLoadbalancer()
- if err != nil {
- return nil, errors.Wrapf(err, "GetLoadbalancer")
- }
- if len(input.BackendId) == 0 && input.BackendType != api.LB_BACKEND_ADDRESS {
- return nil, httperrors.NewMissingParameterError("backend_id")
- }
- region, err := lb.GetRegion()
- if err != nil {
- return nil, err
- }
- baseName := ""
- switch input.BackendType {
- case api.LB_BACKEND_GUEST:
- guestObj, err := validators.ValidateModel(ctx, userCred, GuestManager, &input.BackendId)
- if err != nil {
- return nil, err
- }
- guest := guestObj.(*SGuest)
- input.Address, err = guest.GetAddress()
- if err != nil {
- return nil, err
- }
- baseName = guest.Name
- host, err := guest.GetHost()
- if err != nil {
- return nil, errors.Wrapf(err, "GetHost")
- }
- hRegion, err := host.GetRegion()
- if err != nil {
- return nil, err
- }
- if hRegion.Id != region.Id {
- return nil, httperrors.NewInputParameterError("region of host %q (%s) != region of loadbalancer %q (%s))",
- host.Name, host.ZoneId, lb.Name, lb.ZoneId)
- }
- if len(lb.ManagerId) == 0 {
- if !utils.IsInStringArray(host.HostType, []string{api.HOST_TYPE_HYPERVISOR, api.HOST_TYPE_ESXI, api.HOST_TYPE_BAREMETAL}) {
- return nil, httperrors.NewInputParameterError("host type of host %q (%s) should be either hypervisor, baremetal or esxi",
- host.Name, host.HostType)
- }
- } else if host.ManagerId != lb.ManagerId {
- return nil, httperrors.NewInputParameterError("manager of host %q (%s) != manager of loadbalancer %q (%s))",
- host.Name, host.ManagerId, lb.Name, lb.ManagerId)
- }
- case api.LB_BACKEND_HOST:
- hostObj, err := validators.ValidateModel(ctx, userCred, HostManager, &input.BackendId)
- if err != nil {
- return nil, err
- }
- host := hostObj.(*SHost)
- if len(host.AccessIp) == 0 {
- return nil, fmt.Errorf("host %s has no access ip", host.GetId())
- }
- hRegion, err := host.GetRegion()
- if err != nil {
- return nil, err
- }
- if hRegion.Id != region.Id {
- return nil, httperrors.NewInputParameterError("region of host %q (%s) != region of loadbalancer %q (%s))",
- host.Name, host.ZoneId, lb.Name, lb.ZoneId)
- }
- if host.ManagerId != lb.ManagerId {
- return nil, httperrors.NewInputParameterError("manager of host %q (%s) != manager of loadbalancer %q (%s))",
- host.Name, host.ManagerId, lb.Name, lb.ManagerId)
- }
- input.Address = host.AccessIp
- baseName = host.Name
- case api.LB_BACKEND_IP:
- _, err := netutils.NewIPV4Addr(input.BackendId)
- if err != nil {
- return nil, err
- }
- input.Address = input.BackendId
- baseName = input.Address
- case api.LB_BACKEND_ADDRESS:
- if len(input.Address) == 0 {
- return nil, httperrors.NewMissingParameterError("address")
- }
- default:
- return input, httperrors.NewInputParameterError("invalid backend_type %s", input.BackendType)
- }
- if len(input.Name) == 0 {
- input.Name = fmt.Sprintf("%s-%s-%s-%s", lbbg.Name, input.BackendType, baseName, rand.String(4))
- }
- input.StatusStandaloneResourceCreateInput, err = man.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusStandaloneResourceCreateInput)
- if err != nil {
- return nil, err
- }
- return region.GetDriver().ValidateCreateLoadbalancerBackendData(ctx, userCred, lb, lbbg, input)
- }
- func (lbb *SLoadbalancerBackend) GetCloudproviderId() string {
- lbbg, _ := lbb.GetLoadbalancerBackendGroup()
- if lbbg != nil {
- return lbbg.GetCloudproviderId()
- }
- return ""
- }
- func (lbb *SLoadbalancerBackend) GetLoadbalancerBackendGroup() (*SLoadbalancerBackendGroup, error) {
- backendgroup, err := LoadbalancerBackendGroupManager.FetchById(lbb.BackendGroupId)
- if err != nil {
- return nil, errors.Wrapf(err, "GetLoadbalancerBackendGroup(%s)", lbb.BackendGroupId)
- }
- return backendgroup.(*SLoadbalancerBackendGroup), nil
- }
- func (lbb *SLoadbalancerBackend) GetGuest() *SGuest {
- guest, err := GuestManager.FetchById(lbb.BackendId)
- if err != nil {
- return nil
- }
- return guest.(*SGuest)
- }
- func (lbb *SLoadbalancerBackend) GetRegion() (*SCloudregion, error) {
- backendgroup, err := lbb.GetLoadbalancerBackendGroup()
- if err != nil {
- return nil, err
- }
- return backendgroup.GetRegion()
- }
- func (lbb *SLoadbalancerBackend) GetIRegion(ctx context.Context) (cloudprovider.ICloudRegion, error) {
- backendgroup, err := lbb.GetLoadbalancerBackendGroup()
- if err != nil {
- return nil, err
- }
- return backendgroup.GetIRegion(ctx)
- }
- func (lbb *SLoadbalancerBackend) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.LoadbalancerBackendUpdateInput) (*api.LoadbalancerBackendUpdateInput, error) {
- var err error
- input.StatusStandaloneResourceBaseUpdateInput, err = lbb.SStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.StatusStandaloneResourceBaseUpdateInput)
- if err != nil {
- return nil, errors.Wrap(err, "SStatusStandaloneResourceBase.ValidateUpdateData")
- }
- region, err := lbb.GetRegion()
- if err != nil {
- return nil, err
- }
- lbbg, err := lbb.GetLoadbalancerBackendGroup()
- if err != nil {
- return nil, err
- }
- return region.GetDriver().ValidateUpdateLoadbalancerBackendData(ctx, userCred, lbbg, input)
- }
- func (lbb *SLoadbalancerBackend) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
- lbb.SStatusStandaloneResourceBase.PostUpdate(ctx, userCred, query, data)
- if data.Contains("port") || data.Contains("weight") || data.Contains("enabled") {
- params := data.(*jsonutils.JSONDict)
- if !params.Contains("enabled") {
- params.Add(jsonutils.NewBool(lbb.Status == api.LB_STATUS_ENABLED), "enabled")
- }
- lbb.StartLoadBalancerBackendSyncTask(ctx, userCred, params, "")
- }
- }
- func (lbb *SLoadbalancerBackend) StartLoadBalancerBackendSyncTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error {
- lbb.SetStatus(ctx, userCred, api.LB_SYNC_CONF, "")
- task, err := taskman.TaskManager.NewTask(ctx, "LoadbalancerBackendSyncTask", lbb, userCred, params, parentTaskId, "", nil)
- if err != nil {
- return err
- }
- return task.ScheduleRun(nil)
- }
- func (lbb *SLoadbalancerBackend) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
- lbb.SStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
- lbb.SetStatus(ctx, userCred, api.LB_CREATING, "")
- err := lbb.StartLoadBalancerBackendCreateTask(ctx, userCred, "")
- if err != nil {
- log.Errorf("Failed to create loadbalancer backend error: %v", err)
- }
- }
- func (lbb *SLoadbalancerBackend) getVpc(ctx context.Context) (*SVpc, error) {
- if lbb.BackendType != api.LB_BACKEND_GUEST {
- return nil, nil
- }
- guestM, err := GuestManager.FetchById(lbb.BackendId)
- if err != nil {
- return nil, errors.Wrapf(err, "find guest %s", lbb.BackendId)
- }
- guest := guestM.(*SGuest)
- return guest.GetVpc()
- }
- func (manager *SLoadbalancerBackendManager) FetchCustomizeColumns(
- ctx context.Context,
- userCred mcclient.TokenCredential,
- query jsonutils.JSONObject,
- objs []interface{},
- fields stringutils2.SSortedStrings,
- isList bool,
- ) []api.LoadbalancerBackendDetails {
- rows := make([]api.LoadbalancerBackendDetails, len(objs))
- stdRows := manager.SStatusStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
- lbbgRows := manager.SLoadbalancerBackendgroupResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
- lbIds := make([]string, len(objs))
- for i := range rows {
- rows[i] = api.LoadbalancerBackendDetails{
- StatusStandaloneResourceDetails: stdRows[i],
- LoadbalancerBackendGroupResourceInfo: lbbgRows[i],
- }
- lbIds[i] = rows[i].LoadbalancerId
- }
- lbs := map[string]SLoadbalancer{}
- err := db.FetchStandaloneObjectsByIds(LoadbalancerManager, lbIds, &lbs)
- if err != nil {
- return rows
- }
- virObjs := make([]interface{}, len(objs))
- for i := range rows {
- if lb, ok := lbs[lbIds[i]]; ok {
- virObjs[i] = &lb
- rows[i].ProjectId = lb.ProjectId
- }
- }
- return rows
- }
- func (lbb *SLoadbalancerBackend) StartLoadBalancerBackendCreateTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
- task, err := taskman.TaskManager.NewTask(ctx, "LoadbalancerBackendCreateTask", lbb, userCred, nil, parentTaskId, "", nil)
- if err != nil {
- return errors.Wrapf(err, "NewTask")
- }
- return task.ScheduleRun(nil)
- }
- func (lbb *SLoadbalancerBackend) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
- return nil
- }
- func (self *SLoadbalancerBackend) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
- return self.SStatusStandaloneResourceBase.Delete(ctx, userCred)
- }
- func (lbb *SLoadbalancerBackend) PerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
- parasm := jsonutils.NewDict()
- parasm.Add(jsonutils.JSONTrue, "purge")
- return nil, lbb.StartLoadBalancerBackendDeleteTask(ctx, userCred, parasm, "")
- }
- func (lbb *SLoadbalancerBackend) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
- lbb.SetStatus(ctx, userCred, api.LB_STATUS_DELETING, "")
- return lbb.StartLoadBalancerBackendDeleteTask(ctx, userCred, jsonutils.NewDict(), "")
- }
- func (lbb *SLoadbalancerBackend) StartLoadBalancerBackendDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error {
- task, err := taskman.TaskManager.NewTask(ctx, "LoadbalancerBackendDeleteTask", lbb, userCred, params, parentTaskId, "", nil)
- if err != nil {
- return err
- }
- task.ScheduleRun(nil)
- return nil
- }
- func (lbb *SLoadbalancerBackend) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
- return lbb.SStatusStandaloneResourceBase.ValidateDeleteCondition(ctx, nil)
- }
- func (lbbg *SLoadbalancerBackendGroup) SyncLoadbalancerBackends(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, exts []cloudprovider.ICloudLoadbalancerBackend) compare.SyncResult {
- lockman.LockRawObject(ctx, LoadbalancerBackendManager.Keyword(), lbbg.Id)
- defer lockman.ReleaseRawObject(ctx, LoadbalancerBackendManager.Keyword(), lbbg.Id)
- result := compare.SyncResult{}
- dbRes, err := lbbg.GetBackends()
- if err != nil {
- result.Error(err)
- return result
- }
- removed := []SLoadbalancerBackend{}
- commondb := []SLoadbalancerBackend{}
- commonext := []cloudprovider.ICloudLoadbalancerBackend{}
- added := []cloudprovider.ICloudLoadbalancerBackend{}
- err = compare.CompareSets(dbRes, exts, &removed, &commondb, &commonext, &added)
- if err != nil {
- result.Error(err)
- return result
- }
- for i := 0; i < len(removed); i++ {
- err = removed[i].syncRemove(ctx, userCred)
- if err != nil {
- result.DeleteError(err)
- continue
- }
- result.Delete()
- }
- for i := 0; i < len(commondb); i++ {
- err = commondb[i].SyncWithCloudLoadbalancerBackend(ctx, userCred, commonext[i], provider)
- if err != nil {
- result.UpdateError(err)
- continue
- }
- result.Update()
- }
- for i := 0; i < len(added); i++ {
- _, err := lbbg.newFromCloudLoadbalancerBackend(ctx, userCred, added[i], provider)
- if err != nil {
- result.AddError(err)
- continue
- }
- result.Add()
- }
- return result
- }
- func (lbb *SLoadbalancerBackend) constructFieldsFromCloudLoadbalancerBackend(ext cloudprovider.ICloudLoadbalancerBackend, managerId string) error {
- lbb.Status = ext.GetStatus()
- lbb.Weight = ext.GetWeight()
- lbb.Port = ext.GetPort()
- lbb.BackendType = ext.GetBackendType()
- lbb.BackendRole = ext.GetBackendRole()
- ipAddr := ext.GetIpAddress()
- if len(lbb.Address) == 0 || ipAddr != lbb.Address {
- lbb.Address = ipAddr
- }
- if lbb.BackendType == api.LB_BACKEND_GUEST {
- instance, err := db.FetchByExternalIdAndManagerId(GuestManager, ext.GetBackendId(), func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
- sq := HostManager.Query().SubQuery()
- return q.Join(sq, sqlchemy.Equals(sq.Field("id"), q.Field("host_id"))).Filter(sqlchemy.Equals(sq.Field("manager_id"), managerId))
- })
- if err != nil {
- // 部分弹性伸缩组实例未同步, 忽略找不到实例错误
- if errors.Cause(err) == sql.ErrNoRows {
- return nil
- }
- return errors.Wrapf(err, "FetchByExternalIdAndManagerId %s", ext.GetBackendId())
- }
- guest := instance.(*SGuest)
- lbb.BackendId = guest.Id
- if len(lbb.Address) == 0 {
- lbb.Address, _ = guest.GetAddress()
- }
- }
- return nil
- }
- func (lbb *SLoadbalancerBackend) syncRemove(ctx context.Context, userCred mcclient.TokenCredential) error {
- lockman.LockObject(ctx, lbb)
- defer lockman.ReleaseObject(ctx, lbb)
- err := lbb.ValidateDeleteCondition(ctx, nil)
- if err != nil { // cannot delete
- lbb.SetStatus(ctx, userCred, api.LB_STATUS_UNKNOWN, "sync to delete")
- return errors.Wrapf(err, "ValidateDeleteCondition")
- }
- return lbb.RealDelete(ctx, userCred)
- }
- func (lbb *SLoadbalancerBackend) SyncWithCloudLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudLoadbalancerBackend, provider *SCloudprovider) error {
- diff, err := db.UpdateWithLock(ctx, lbb, func() error {
- return lbb.constructFieldsFromCloudLoadbalancerBackend(ext, provider.Id)
- })
- if err != nil {
- return err
- }
- db.OpsLog.LogSyncUpdate(lbb, diff, userCred)
- return nil
- }
- func (lbbg *SLoadbalancerBackendGroup) newFromCloudLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudLoadbalancerBackend, provider *SCloudprovider) (*SLoadbalancerBackend, error) {
- lbb := &SLoadbalancerBackend{}
- lbb.SetModelManager(LoadbalancerBackendManager, lbb)
- lbb.BackendGroupId = lbbg.Id
- lbb.ExternalId = ext.GetGlobalId()
- err := lbb.constructFieldsFromCloudLoadbalancerBackend(ext, provider.Id)
- if err != nil {
- return nil, errors.Wrapf(err, "constructFieldsFromCloudLoadbalancerBackend")
- }
- lbb.Name = ext.GetName()
- err = LoadbalancerBackendManager.TableSpec().Insert(ctx, lbb)
- if err != nil {
- return nil, errors.Wrapf(err, "Insert")
- }
- db.OpsLog.LogEvent(lbb, db.ACT_CREATE, lbb.GetShortDesc(ctx), userCred)
- return lbb, nil
- }
- func (manager *SLoadbalancerBackendManager) ListItemExportKeys(ctx context.Context,
- q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential,
- keys stringutils2.SSortedStrings,
- ) (*sqlchemy.SQuery, error) {
- var err error
- q, err = manager.SStatusStandaloneResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
- if err != nil {
- return nil, errors.Wrap(err, "SStatusStandaloneResourceBaseManager.ListItemExportKeys")
- }
- if keys.ContainsAny(manager.SLoadbalancerBackendgroupResourceBaseManager.GetExportKeys()...) {
- q, err = manager.SLoadbalancerBackendgroupResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
- if err != nil {
- return nil, errors.Wrap(err, "SLoadbalancerBackendgroupResourceBaseManager.ListItemExportKeys")
- }
- }
- return q, nil
- }
- func (manager *SLoadbalancerBackendManager) InitializeData() error {
- return nil
- }
|