| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729 |
- // 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"
- "fmt"
- "strconv"
- "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/util/delayedwork"
- "yunion.io/x/pkg/util/rbacscope"
- "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/httperrors"
- "yunion.io/x/onecloud/pkg/mcclient"
- "yunion.io/x/onecloud/pkg/mcclient/auth"
- ctxutils "yunion.io/x/onecloud/pkg/util/ctx"
- "yunion.io/x/onecloud/pkg/util/stringutils2"
- )
- // +onecloud:swagger-gen-model-singular=networkaddress
- // +onecloud:swagger-gen-model-plural=networkaddresses
- type SNetworkAddressManager struct {
- db.SStandaloneAnonResourceBaseManager
- SNetworkResourceBaseManager
- delayedWorkManager *delayedwork.DelayedWorkManager
- }
- var NetworkAddressManager *SNetworkAddressManager
- func init() {
- NetworkAddressManager = &SNetworkAddressManager{
- SStandaloneAnonResourceBaseManager: db.NewStandaloneAnonResourceBaseManager(
- SNetworkAddress{},
- "networkaddresses_tbl",
- "networkaddress",
- "networkaddresses",
- ),
- }
- NetworkAddressManager.SetVirtualObject(NetworkAddressManager)
- NetworkAddressManager.delayedWorkManager = delayedwork.NewDelayedWorkManager()
- }
- type SNetworkAddress struct {
- db.SStandaloneAnonResourceBase
- Type string `width:"16" charset:"ascii" list:"user" create:"required"`
- ParentType api.TNetworkAddressParentType `width:"16" charset:"ascii" list:"user" create:"required"`
- ParentId string `width:"16" charset:"ascii" list:"user" create:"optional"`
- SNetworkResourceBase
- IpAddr string `width:"16" charset:"ascii" list:"user" create:"optional"`
- SubCtrVid int `create:"optional"`
- }
- func (man *SNetworkAddressManager) InitializeData() error {
- go man.delayedWorkManager.Start(context.Background())
- {
- err := man.cleanDeletedGuestnetworkSubIPs()
- if err != nil {
- return errors.Wrapf(err, "cleanDeletedGuestnetworkSubIPs")
- }
- }
- return nil
- }
- func (man *SNetworkAddressManager) queryByParentTypeId(typ api.TNetworkAddressParentType, id string) *sqlchemy.SQuery {
- q := NetworkAddressManager.Query().
- Equals("parent_type", string(typ)).
- Equals("parent_id", id)
- return q
- }
- func (man *SNetworkAddressManager) queryByGuestnetworkId(rowid int64) *sqlchemy.SQuery {
- id := strconv.FormatInt(rowid, 10)
- return man.queryByParentTypeId(api.NetworkAddressParentTypeGuestnetwork, id)
- }
- func (man *SNetworkAddressManager) fetchByParentTypeId(typ api.TNetworkAddressParentType, id string) ([]SNetworkAddress, error) {
- var (
- q = man.queryByParentTypeId(typ, id)
- nas []SNetworkAddress
- )
- if err := db.FetchModelObjects(man, q, &nas); err != nil {
- return nil, err
- }
- return nas, nil
- }
- func (man *SNetworkAddressManager) fetchByGuestnetworkId(rowid int64) ([]SNetworkAddress, error) {
- id := strconv.FormatInt(rowid, 10)
- return man.fetchByParentTypeId(api.NetworkAddressParentTypeGuestnetwork, id)
- }
- func (man *SNetworkAddressManager) fetchAddressCountByGuestnetworkId(rowid int64) (int, error) {
- q := man.queryByGuestnetworkId(rowid)
- return q.CountWithError()
- }
- func (man *SNetworkAddressManager) fetchAddressesByGuestnetworkId(rowid int64) ([]api.NetworkAddrConf, error) {
- var (
- naq = man.queryByGuestnetworkId(rowid).SubQuery()
- nq = NetworkManager.Query().SubQuery()
- ipnetsq = naq.Query(
- naq.Field("id"),
- naq.Field("type"),
- naq.Field("ip_addr"),
- nq.Field("guest_ip_mask").Label("masklen"),
- nq.Field("guest_gateway").Label("gateway"),
- ).Join(nq, sqlchemy.Equals(
- naq.Field("network_id"),
- nq.Field("id")),
- )
- ipnets []api.NetworkAddrConf
- )
- if err := ipnetsq.All(&ipnets); err != nil {
- return nil, errors.Wrapf(err, "fetch addresses ipnets by guestnetwork row id: %d", rowid)
- }
- return ipnets, nil
- }
- func (man *SNetworkAddressManager) deleteByGuestnetworkId(ctx context.Context, userCred mcclient.TokenCredential, rowid int64) error {
- nas, err := NetworkAddressManager.fetchByGuestnetworkId(rowid)
- if err != nil {
- return errors.Wrap(err, "fetch attached network addresses")
- }
- var errs []error
- for i := range nas {
- na := &nas[i]
- if err := na.remoteUnassignAddress(ctx, userCred); err != nil {
- errs = append(errs, err)
- continue
- }
- if err := db.DeleteModel(ctx, userCred, na); err != nil {
- errs = append(errs, err)
- continue
- }
- }
- return errors.NewAggregate(errs)
- }
- func (man *SNetworkAddressManager) syncGuestnetworkICloudNic(ctx context.Context, userCred mcclient.TokenCredential, guestnetwork *SGuestnetwork, iNic cloudprovider.ICloudNic) error {
- ipAddrs, err := iNic.GetSubAddress()
- if err != nil {
- return errors.Wrap(err, "iNic.GetSubAddress")
- }
- if err := man.syncGuestnetworkSubIPs(ctx, userCred, guestnetwork, ipAddrs); err != nil {
- return errors.Wrap(err, "syncGuestnetworkSubIPs")
- }
- return nil
- }
- func (man *SNetworkAddressManager) syncGuestnetworkSubIPs(ctx context.Context, userCred mcclient.TokenCredential, guestnetwork *SGuestnetwork, ipAddrs []string) error {
- nas, err := man.fetchByGuestnetworkId(guestnetwork.RowId)
- if err != nil {
- return errors.Wrap(err, "fetchByGuestnetworkId")
- }
- existings := stringutils2.NewSortedStrings(nil)
- for i := range nas {
- existings = existings.Append(nas[i].IpAddr)
- }
- probed := stringutils2.NewSortedStrings(ipAddrs)
- removes, _, adds := stringutils2.Split(existings, probed)
- log.Debugf("syncGuestnetworkSubIPs removes: %s add %s", jsonutils.Marshal(removes), jsonutils.Marshal(adds))
- if err := man.removeGuestnetworkSubIPs(ctx, userCred, guestnetwork, removes); err != nil {
- return err
- }
- if _, err := man.addGuestnetworkSubIPs(ctx, userCred, guestnetwork, api.GuestAddSubIpsInfo{
- SubIps: adds,
- Reserved: true,
- }); err != nil {
- return err
- }
- return nil
- }
- func (man *SNetworkAddressManager) removeGuestnetworkSubIPs(ctx context.Context, userCred mcclient.TokenCredential, guestnetwork *SGuestnetwork, ipAddrs []string) error {
- q := man.queryByGuestnetworkId(guestnetwork.RowId)
- q = q.In("ip_addr", ipAddrs)
- var nas []SNetworkAddress
- if err := db.FetchModelObjects(man, q, &nas); err != nil {
- return errors.Wrapf(err, "removeGuestnetworkSubIPs by ipAddrs %s", strings.Join(ipAddrs, ", "))
- }
- for i := range nas {
- na := &nas[i]
- if err := db.DeleteModel(ctx, userCred, na); err != nil {
- return err
- }
- }
- return nil
- }
- func (man *SNetworkAddressManager) addGuestnetworkSubIPs(ctx context.Context, userCred mcclient.TokenCredential, guestnetwork *SGuestnetwork, input api.GuestAddSubIpsInfo) ([]string, error) {
- net, err := guestnetwork.GetNetwork()
- if err != nil {
- return nil, errors.Wrapf(err, "GetNetwork")
- }
- lockman.LockObject(ctx, net)
- defer lockman.ReleaseObject(ctx, net)
- var (
- usedAddrMap = net.GetUsedAddresses(ctx)
- recentUsedAddrTable = GuestnetworkManager.getRecentlyReleasedIPAddresses(net.Id, net.getAllocTimoutDuration())
- )
- if input.Count == 0 {
- input.Count = len(input.SubIps)
- }
- if input.Count == 0 {
- // nil operation
- return nil, nil
- }
- addedIps := make([]string, 0)
- errs := make([]error, 0)
- for i := 0; i < input.Count; i++ {
- var candidate string
- if i < len(input.SubIps) {
- candidate = input.SubIps[i]
- }
- ipAddr, err := net.GetFreeIP(ctx, userCred, usedAddrMap, recentUsedAddrTable, candidate, input.AllocDir, input.Reserved, api.AddressTypeIPv4)
- if err != nil {
- errs = append(errs, errors.Wrap(err, "GetFreeIP"))
- continue
- }
- m, err := db.NewModelObject(man)
- if err != nil {
- errs = append(errs, errors.Wrap(err, "NewModelObject"))
- continue
- }
- na := m.(*SNetworkAddress)
- na.NetworkId = guestnetwork.NetworkId
- na.ParentType = api.NetworkAddressParentTypeGuestnetwork
- na.ParentId = strconv.FormatInt(guestnetwork.RowId, 10)
- na.Type = api.NetworkAddressTypeSubIP
- na.IpAddr = ipAddr
- if err := man.TableSpec().Insert(ctx, na); err != nil {
- errs = append(errs, errors.Wrapf(err, "addGuestnetworkSubIPs"))
- continue
- }
- usedAddrMap[ipAddr] = true
- addedIps = append(addedIps, ipAddr)
- }
- if len(errs) > 0 {
- return addedIps, errors.NewAggregate(errs)
- }
- return addedIps, nil
- }
- func (man *SNetworkAddressManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.NetworkAddressCreateInput) (api.NetworkAddressCreateInput, error) {
- return input, errors.Wrap(httperrors.ErrNotSupported, "no supported")
- }
- func (na *SNetworkAddress) parentIdInt64() int64 {
- r, err := strconv.ParseInt(na.ParentId, 10, 64)
- if err != nil {
- panic(fmt.Sprintf("networkaddress %s: invalid parent_id %s", na.Id, na.ParentId))
- }
- return r
- }
- func (na *SNetworkAddress) getGuestnetwork(ctx context.Context, userCred mcclient.TokenCredential) (*SGuestnetwork, error) {
- if na.ParentType == api.NetworkAddressParentTypeGuestnetwork {
- guestnetwork, err := GuestnetworkManager.fetchByRowId(ctx, userCred, na.parentIdInt64())
- if err != nil {
- return nil, err
- }
- return guestnetwork, nil
- }
- return nil, errors.Errorf("getGuestnetwork: expect parent_type %s, got %s", api.NetworkAddressParentTypeGuestnetwork, na.ParentType)
- }
- func (na *SNetworkAddress) getGuest(ctx context.Context, userCred mcclient.TokenCredential) (*SGuest, error) {
- guestnetwork, err := na.getGuestnetwork(ctx, userCred)
- if err != nil {
- return nil, err
- }
- guest := guestnetwork.GetGuest()
- if guest != nil {
- return guest, nil
- }
- return nil, errors.Wrapf(errors.ErrNotFound, "getGuest: guestnetwork guest_id %s", guestnetwork.GuestId)
- }
- func (na *SNetworkAddress) getIVM(ctx context.Context, userCred mcclient.TokenCredential) (cloudprovider.ICloudVM, error) {
- guest, err := na.getGuest(ctx, userCred)
- if err != nil {
- return nil, err
- }
- if guest.ExternalId == "" {
- return nil, errors.Errorf("getIVM: guest %s(%s) has empty external_id", guest.Name, guest.Id)
- }
- ivm, err := guest.GetIVM(ctx)
- if err != nil {
- return nil, err
- }
- return ivm, nil
- }
- func (na *SNetworkAddress) getICloudNic(ctx context.Context, userCred mcclient.TokenCredential) (cloudprovider.ICloudNic, error) {
- guestnetwork, err := na.getGuestnetwork(ctx, userCred)
- if err != nil {
- return nil, err
- }
- iVM, err := na.getIVM(ctx, userCred)
- if err != nil {
- return nil, err
- }
- iNics, err := iVM.GetINics()
- if err != nil {
- return nil, err
- }
- for _, iNic := range iNics {
- if iNic.GetIP() == guestnetwork.IpAddr && iNic.GetMAC() == guestnetwork.MacAddr {
- return iNic, nil
- }
- }
- return nil, errors.Wrapf(errors.ErrNotFound, "getICloudNic: no cloud nic with ip %s, mac %s", guestnetwork.IpAddr, guestnetwork.MacAddr)
- }
- /*func (na *SNetworkAddress) remoteAssignAddress(ctx context.Context, userCred mcclient.TokenCredential) error {
- if na.ParentType == api.NetworkAddressParentTypeGuestnetwork {
- guest, err := na.getGuest(ctx, userCred)
- if err != nil {
- return err
- }
- if guest.ExternalId != "" {
- iNic, err := na.getICloudNic(ctx, userCred)
- if err != nil {
- return err
- }
- if err := iNic.AssignAddress([]string{na.IpAddr}); err != nil {
- if errors.Cause(err) == cloudprovider.ErrAddressCountExceed {
- return httperrors.NewNotAcceptableError("exceed address count limit: %v", err)
- }
- return err
- }
- } else {
- NetworkAddressManager.submitGuestSyncTask(ctx, userCred, guest)
- }
- }
- return nil
- }*/
- func (na *SNetworkAddress) remoteUnassignAddress(ctx context.Context, userCred mcclient.TokenCredential) error {
- if na.ParentType == api.NetworkAddressParentTypeGuestnetwork {
- guest, err := na.getGuest(ctx, userCred)
- if err != nil {
- if errors.Cause(err) == errors.ErrNotFound {
- return nil
- }
- return err
- }
- if guest.ExternalId != "" {
- iNic, err := na.getICloudNic(ctx, userCred)
- if err != nil {
- if errors.Cause(err) == errors.ErrNotFound {
- return nil
- }
- return err
- }
- if err := iNic.UnassignAddress([]string{na.IpAddr}); err != nil {
- return err
- }
- } else {
- NetworkAddressManager.submitGuestSyncTask(ctx, userCred, guest)
- }
- }
- return nil
- }
- func (na *SNetworkAddress) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
- if err := na.remoteUnassignAddress(ctx, userCred); err != nil {
- return err
- }
- return nil
- }
- func (man *SNetworkAddressManager) ListItemExportKeys(ctx context.Context,
- q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential,
- keys stringutils2.SSortedStrings,
- ) (*sqlchemy.SQuery, error) {
- return db.ApplyListItemExportKeys(ctx, q, userCred, keys,
- &man.SStandaloneAnonResourceBaseManager,
- &man.SNetworkResourceBaseManager,
- )
- }
- func (man *SNetworkAddressManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
- return db.ApplyQueryDistinctExtraField(q, field,
- &man.SStandaloneAnonResourceBaseManager,
- &man.SNetworkResourceBaseManager,
- )
- }
- func (man *SNetworkAddressManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, input api.NetworkAddressListInput) (*sqlchemy.SQuery, error) {
- var err error
- q, err = man.SStandaloneAnonResourceBaseManager.ListItemFilter(ctx, q, userCred, input.StandaloneAnonResourceListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SStandaloneAnonResourceBaseManager.ListItemFilter")
- }
- q, err = man.SNetworkResourceBaseManager.ListItemFilter(ctx, q, userCred, input.NetworkFilterListInput)
- if err != nil {
- return nil, errors.Wrap(err, "SNetworkResourceBaseManager.ListItemFilter")
- }
- if len(input.GuestId) > 0 {
- gnq := GuestnetworkManager.Query().SubQuery()
- gq := GuestManager.Query().
- In("id", input.GuestId).
- SubQuery()
- idq := man.Query("id").
- Equals("parent_type", api.NetworkAddressParentTypeGuestnetwork)
- idq = idq.Join(gnq, sqlchemy.Equals(gnq.Field("row_id"), idq.Field("parent_id")))
- idq = idq.Join(gq, sqlchemy.Equals(gq.Field("id"), gnq.Field("guest_id")))
- q = q.In("id", idq.SubQuery())
- }
- q, err = managedResourceFilterByAccount(
- ctx,
- q, input.ManagedResourceListInput, "network_id", func() *sqlchemy.SQuery {
- networks := NetworkManager.Query()
- wires := WireManager.Query("id", "vpc_id", "manager_id").SubQuery()
- vpcs := VpcManager.Query("id", "manager_id").SubQuery()
- networks = networks.Join(wires, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id")))
- networks = networks.Join(vpcs, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id")))
- networks = networks.AppendField(networks.Field("id"))
- networks = networks.AppendField(sqlchemy.NewFunction(sqlchemy.NewCase().When(sqlchemy.IsNullOrEmpty(wires.Field("manager_id")), vpcs.Field("manager_id")).Else(wires.Field("manager_id")), "manager_id", false))
- subq := networks.SubQuery().Query()
- subq = subq.AppendField(subq.Field("id"))
- return subq
- })
- if err != nil {
- return nil, errors.Wrap(err, "ManagedResourceFilterByAccount")
- }
- return q, nil
- }
- func (man *SNetworkAddressManager) OrderByExtraFields(
- ctx context.Context,
- q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential,
- query api.NetworkAddressListInput,
- ) (*sqlchemy.SQuery, error) {
- var err error
- q, err = man.SNetworkResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.NetworkFilterListInput)
- if err != nil {
- return nil, err
- }
- q, err = man.SStandaloneAnonResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.StandaloneAnonResourceListInput)
- if err != nil {
- return nil, err
- }
- return q, nil
- }
- func (man *SNetworkAddressManager) FetchCustomizeColumns(
- ctx context.Context,
- userCred mcclient.TokenCredential,
- query jsonutils.JSONObject,
- objs []interface{},
- fields stringutils2.SSortedStrings,
- isList bool,
- ) []api.NetworkAddressDetails {
- ret := make([]api.NetworkAddressDetails, len(objs))
- netCols := man.SNetworkResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
- for i := range netCols {
- ret[i].NetworkResourceInfo = netCols[i]
- }
- stdaCols := man.SStandaloneAnonResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
- for i := range stdaCols {
- ret[i].StandaloneAnonResourceDetails = stdaCols[i]
- }
- {
- guestnetworkRowIds := make([]int64, 0, len(objs))
- for i := range objs {
- na := objs[i].(*SNetworkAddress)
- if na.ParentType == api.NetworkAddressParentTypeGuestnetwork {
- rowId, _ := strconv.ParseInt(na.ParentId, 10, 64)
- guestnetworkRowIds = append(guestnetworkRowIds, rowId)
- }
- }
- if len(guestnetworkRowIds) > 0 {
- gns, err := GuestnetworkManager.fetchByRowIds(ctx, userCred, guestnetworkRowIds)
- if err == nil && len(gns) > 0 {
- gnObjs := make([]interface{}, len(gns))
- for i := range gns {
- gnObjs[i] = &gns[i]
- }
- gnds := GuestnetworkManager.FetchCustomizeColumns(ctx, userCred, query, gnObjs, fields, isList)
- for i, j := 0, 0; i < len(objs); i++ {
- na := objs[i].(*SNetworkAddress)
- if na.ParentType == api.NetworkAddressParentTypeGuestnetwork {
- ret[i].Guestnetwork = gnds[j]
- j++
- }
- }
- }
- }
- }
- return ret
- }
- func (man *SNetworkAddressManager) FilterByOwner(ctx context.Context, q *sqlchemy.SQuery, manager db.FilterByOwnerProvider, userCred mcclient.TokenCredential, owner mcclient.IIdentityProvider, scope rbacscope.TRbacScope) *sqlchemy.SQuery {
- q = db.ApplyFilterByOwner(ctx, q, userCred, owner, scope,
- &man.SStandaloneAnonResourceBaseManager,
- )
- if owner != nil {
- var condVar, condVal string
- switch scope {
- case rbacscope.ScopeProject:
- condVar, condVal = "tenant_id", owner.GetProjectId()
- case rbacscope.ScopeDomain:
- condVar, condVal = "domain_id", owner.GetProjectDomainId()
- default:
- return q
- }
- {
- var (
- gnq = GuestnetworkManager.Query().SubQuery()
- gq = GuestManager.Query().SubQuery()
- naq = NetworkAddressManager.Query("id")
- )
- naq = naq.
- Join(gnq, sqlchemy.Equals(naq.Field("parent_id"), gnq.Field("row_id"))).
- Join(gq, sqlchemy.Equals(gnq.Field("guest_id"), gq.Field("id")))
- naq = naq.Equals("parent_type", api.NetworkAddressParentTypeGuestnetwork)
- naq = naq.Filter(sqlchemy.Equals(gq.Field(condVar), condVal))
- q = q.In("id", naq.SubQuery())
- }
- }
- return q
- }
- func (man *SNetworkAddressManager) submitGuestSyncTask(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) {
- man.delayedWorkManager.Submit(ctx, delayedwork.DelayedWorkRequest{
- ID: guest.Id,
- SoftDelay: 2 * time.Second,
- HardDelay: 5 * time.Second,
- Func: func(ctx context.Context) {
- var (
- fwOnly = false
- parentTaskId = ""
- )
- err := guest.StartSyncTask(ctx, userCred, fwOnly, parentTaskId)
- if err != nil {
- log.Errorf("guest StartSyncTask: %v", err)
- }
- },
- })
- }
- func (g *SGuest) PerformUpdateSubIps(
- ctx context.Context,
- userCred mcclient.TokenCredential,
- query jsonutils.JSONObject,
- input api.GuestUpdateSubIpsInput,
- ) (jsonutils.JSONObject, error) {
- gn, err := g.findGuestnetworkByInfo(input.ServerNetworkInfo)
- if err != nil {
- return nil, errors.Wrapf(err, "getGuestnetworkByIpOrMac ip=%s mac=%s", input.IpAddr, input.Mac)
- }
- var iNic cloudprovider.ICloudNic
- if g.ExternalId != "" {
- // sync to cloud
- var err error
- iNic, err = g.getICloudNic(ctx, gn)
- if err != nil {
- return nil, errors.Wrap(err, "getICloudNic")
- }
- }
- errs := make([]error, 0)
- {
- err := NetworkAddressManager.removeGuestnetworkSubIPs(ctx, userCred, gn, input.RemoveSubIps)
- if err != nil {
- errs = append(errs, errors.Wrap(err, "removeGuestnetworkSubIPs"))
- }
- }
- addedIps, err := NetworkAddressManager.addGuestnetworkSubIPs(ctx, userCred, gn, input.GuestAddSubIpsInfo)
- if err != nil {
- errs = append(errs, errors.Wrap(err, "addGuestnetworkSubIPs"))
- }
- if g.ExternalId != "" {
- // sync to cloud
- if len(input.RemoveSubIps) > 0 {
- if err := iNic.UnassignAddress(addedIps); err != nil {
- errs = append(errs, errors.Wrapf(err, "UnassignAddress %s", addedIps))
- }
- }
- if len(addedIps) > 0 {
- if err := iNic.AssignAddress(addedIps); err != nil {
- if errors.Cause(err) == cloudprovider.ErrAddressCountExceed {
- errs = append(errs, httperrors.NewNotAcceptableError("exceed address count limit: %v", err))
- } else {
- errs = append(errs, errors.Wrapf(err, "AssignAddress %s", addedIps))
- }
- }
- }
- } else {
- NetworkAddressManager.submitGuestSyncTask(ctx, userCred, g)
- }
- if len(errs) > 0 {
- return nil, errors.NewAggregate(errs)
- }
- return nil, nil
- }
- func (g *SGuest) PerformAddSubIps(
- ctx context.Context,
- userCred mcclient.TokenCredential,
- query jsonutils.JSONObject,
- input api.GuestAddSubIpsInput,
- ) (jsonutils.JSONObject, error) {
- gn, err := g.findGuestnetworkByInfo(input.ServerNetworkInfo)
- if err != nil {
- return nil, errors.Wrapf(err, "getGuestnetworkByIpOrMac ip=%s mac=%s", input.IpAddr, input.Mac)
- }
- addedIps, err := NetworkAddressManager.addGuestnetworkSubIPs(ctx, userCred, gn, input.GuestAddSubIpsInfo)
- if err != nil {
- return nil, errors.Wrap(err, "addGuestnetworkSubIPs")
- }
- if g.ExternalId != "" && len(addedIps) > 0 {
- // sync to cloud
- iNic, err := g.getICloudNic(ctx, gn)
- if err != nil {
- return nil, errors.Wrap(err, "getICloudNic")
- }
- if err := iNic.AssignAddress(addedIps); err != nil {
- if errors.Cause(err) == cloudprovider.ErrAddressCountExceed {
- return nil, httperrors.NewNotAcceptableError("exceed address count limit: %v", err)
- }
- return nil, errors.Wrapf(err, "AssignAddress %s", addedIps)
- }
- } else {
- NetworkAddressManager.submitGuestSyncTask(ctx, userCred, g)
- }
- return nil, nil
- }
- func (g *SGuest) getICloudNic(ctx context.Context, gn *SGuestnetwork) (cloudprovider.ICloudNic, error) {
- ivm, err := g.GetIVM(ctx)
- if err != nil {
- return nil, errors.Wrap(err, "GetIVM")
- }
- iNics, err := ivm.GetINics()
- if err != nil {
- return nil, errors.Wrap(err, "GetINics %s")
- }
- for _, iNic := range iNics {
- if iNic.GetIP() == gn.IpAddr && iNic.GetMAC() == gn.MacAddr {
- return iNic, nil
- }
- }
- return nil, errors.Wrapf(errors.ErrNotFound, "no nic of ip %s mac %s", gn.IpAddr, gn.MacAddr)
- }
- func (manager *SNetworkAddressManager) fetchSubIpsQuery(parentType api.TNetworkAddressParentType) *sqlchemy.SQuery {
- subIPQ := manager.Query("parent_id").Equals("parent_type", string(parentType))
- subIPQ = subIPQ.AppendField(sqlchemy.GROUP_CONCAT("sub_ips", subIPQ.Field("ip_addr")))
- subIPQ = subIPQ.GroupBy(subIPQ.Field("parent_id"))
- return subIPQ
- }
- func (manager *SNetworkAddressManager) cleanDeletedGuestnetworkSubIPs() error {
- ctx := ctxutils.CtxWithTime()
- userCred := auth.AdminCredential()
- gnQ := GuestnetworkManager.Query("row_id").SubQuery()
- q := manager.Query().Equals("parent_type", api.NetworkAddressParentTypeGuestnetwork)
- q = q.LeftJoin(gnQ, sqlchemy.Equals(q.Field("parent_id"), gnQ.Field("row_id")))
- q = q.Filter(sqlchemy.IsNull(gnQ.Field("row_id")))
- netaddrs := make([]SNetworkAddress, 0)
- err := db.FetchModelObjects(manager, q, &netaddrs)
- if err != nil {
- return errors.Wrapf(err, "FetchModelObjects")
- }
- for i := range netaddrs {
- na := &netaddrs[i]
- if err := db.DeleteModel(ctx, userCred, na); err != nil {
- return errors.Wrapf(err, "DeleteModel")
- }
- }
- return nil
- }
|