diff --git a/pkg/apis/compute/routetable_routesets.go b/pkg/apis/compute/routetable_routesets.go index 1a5f128c39..ec0acd26cc 100644 --- a/pkg/apis/compute/routetable_routesets.go +++ b/pkg/apis/compute/routetable_routesets.go @@ -38,6 +38,8 @@ const ( Next_HOP_TYPE_DIRECTCONNECTION = "DirectConnection" //专线 Next_HOP_TYPE_VPC = "VPC" Next_HOP_TYPE_VBR = "VBR" // 边界路由器 + + Next_HOP_TYPE_IP = "IP" ) const ( diff --git a/pkg/vpcagent/models/models.go b/pkg/vpcagent/models/models.go index a59c64ffc2..6011fde0bb 100644 --- a/pkg/vpcagent/models/models.go +++ b/pkg/vpcagent/models/models.go @@ -21,6 +21,8 @@ import ( type Vpc struct { compute_models.SVpc + RouteTable *RouteTable `json:"-"` + Wire *Wire `json:"-"` Networks Networks `json:"-"` } @@ -31,6 +33,18 @@ func (el *Vpc) Copy() *Vpc { } } +type RouteTable struct { + compute_models.SRouteTable + + Vpc *Vpc +} + +func (el *RouteTable) Copy() *RouteTable { + return &RouteTable{ + SRouteTable: el.SRouteTable, + } +} + type Wire struct { compute_models.SWire @@ -93,6 +107,7 @@ type Guest struct { Host *Host `json:"-"` AdminSecurityGroup *SecurityGroup `json:"-"` SecurityGroups SecurityGroups `json:"-"` + Guestnetworks Guestnetworks `json:"-"` } func (el *Guest) Copy() *Guest { diff --git a/pkg/vpcagent/models/modelset.go b/pkg/vpcagent/models/modelset.go index b88fbd8e8e..2bc38c7012 100644 --- a/pkg/vpcagent/models/modelset.go +++ b/pkg/vpcagent/models/modelset.go @@ -41,6 +41,8 @@ type ( Guestsecgroups map[string]*Guestsecgroup // key: guestId/secgroupId DnsRecords map[string]*DnsRecord + + RouteTables map[string]*RouteTable ) func (set Vpcs) ModelManager() mcclient_modulebase.IBaseManager { @@ -80,6 +82,28 @@ func (ms Vpcs) joinWires(subEntries Wires) bool { return correct } +func (ms Vpcs) joinRouteTables(subEntries RouteTables) bool { + correct := true + for _, subEntry := range subEntries { + vpcId := subEntry.VpcId + m, ok := ms[vpcId] + if !ok { + log.Warningf("vpc_id %s of route table %s(%s) is not present", vpcId, subEntry.Name, subEntry.Id) + correct = false + continue + } + subEntry.Vpc = m + if m.RouteTable != nil { + log.Warningf("vpc %s has more than 1 route table available, skipping %s(%s)", + m.Name, m.Id, subEntry.Name, subEntry.Id) + correct = false + continue + } + m.RouteTable = subEntry + } + return correct +} + func (ms Vpcs) joinNetworks(subEntries Networks) bool { for _, m := range ms { m.Networks = Networks{} @@ -377,6 +401,11 @@ func (set Guestnetworks) joinGuests(subEntries Guests) bool { continue } gn.Guest = g + if g.Guestnetworks == nil { + g.Guestnetworks = Guestnetworks{} + } + rowIdStr := fmt.Sprintf("%d", gn.RowId) + g.Guestnetworks[rowIdStr] = gn } return true } @@ -631,3 +660,24 @@ func (set DnsRecords) Copy() apihelper.IModelSet { } return setCopy } + +func (set RouteTables) ModelManager() mcclient_modulebase.IBaseManager { + return &mcclient_modules.RouteTables +} + +func (set RouteTables) NewModel() db.IModel { + return &RouteTable{} +} + +func (set RouteTables) AddModel(i db.IModel) { + m := i.(*RouteTable) + set[m.Id] = m +} + +func (set RouteTables) Copy() apihelper.IModelSet { + setCopy := RouteTables{} + for id, el := range set { + setCopy[id] = el.Copy() + } + return setCopy +} diff --git a/pkg/vpcagent/models/modelsets.go b/pkg/vpcagent/models/modelsets.go index aeeb498d68..c60da70394 100644 --- a/pkg/vpcagent/models/modelsets.go +++ b/pkg/vpcagent/models/modelsets.go @@ -34,6 +34,8 @@ type ModelSetsMaxUpdatedAt struct { NetworkAddresses time.Time DnsRecords time.Time + + RouteTables time.Time } func NewModelSetsMaxUpdatedAt() *ModelSetsMaxUpdatedAt { @@ -51,6 +53,8 @@ func NewModelSetsMaxUpdatedAt() *ModelSetsMaxUpdatedAt { NetworkAddresses: apihelper.PseudoZeroTime, DnsRecords: apihelper.PseudoZeroTime, + + RouteTables: apihelper.PseudoZeroTime, } } @@ -68,6 +72,8 @@ type ModelSets struct { NetworkAddresses NetworkAddresses DnsRecords DnsRecords + + RouteTables RouteTables } func NewModelSets() *ModelSets { @@ -85,6 +91,8 @@ func NewModelSets() *ModelSets { NetworkAddresses: NetworkAddresses{}, DnsRecords: DnsRecords{}, + + RouteTables: RouteTables{}, } } @@ -104,6 +112,8 @@ func (mss *ModelSets) ModelSetList() []apihelper.IModelSet { mss.NetworkAddresses, mss.DnsRecords, + + mss.RouteTables, } } @@ -126,6 +136,8 @@ func (mss *ModelSets) copy_() *ModelSets { NetworkAddresses: mss.NetworkAddresses.Copy().(NetworkAddresses), DnsRecords: mss.DnsRecords.Copy().(DnsRecords), + + RouteTables: mss.RouteTables.Copy().(RouteTables), } return mssCopy } @@ -164,6 +176,7 @@ func (mss *ModelSets) join() bool { mss.Guests.initJoin() var p []bool p = append(p, mss.Vpcs.joinWires(mss.Wires)) + p = append(p, mss.Vpcs.joinRouteTables(mss.RouteTables)) p = append(p, mss.Wires.joinNetworks(mss.Networks)) p = append(p, mss.Vpcs.joinNetworks(mss.Networks)) p = append(p, mss.Networks.joinGuestnetworks(mss.Guestnetworks)) diff --git a/pkg/vpcagent/ovn/keeper.go b/pkg/vpcagent/ovn/keeper.go index 14fd15ffaf..6dcacabf58 100644 --- a/pkg/vpcagent/ovn/keeper.go +++ b/pkg/vpcagent/ovn/keeper.go @@ -640,6 +640,32 @@ func (keeper *OVNNorthboundKeeper) ClaimGuestnetwork(ctx context.Context, guestn return keeper.cli.Must(ctx, "ClaimGuestnetwork", args) } +func (keeper *OVNNorthboundKeeper) ClaimRoutes(ctx context.Context, vpc *agentmodels.Vpc, routes resolvedRoutes) error { + var irows []types.IRow + for _, route := range routes { + irows = append(irows, &ovn_nb.LogicalRouterStaticRoute{ + Policy: ptr("dst-ip"), + IpPrefix: route.Cidr, + Nexthop: route.NextHop, + }) + } + ocVersion := fmt.Sprintf("%s.%d", vpc.UpdatedAt, vpc.UpdateVersion) + allFound, args := cmp(&keeper.DB, ocVersion, irows...) + if allFound { + return nil + } + lrName := vpcLrName(vpc.Id) + for i, irow := range irows { + ref := fmt.Sprintf("r%d", i) + args = append(args, ovnCreateArgs(irow, ref)...) + args = append(args, "--", "add", "Logical_Router", lrName, "static_routes", "@"+ref) + } + if len(args) > 0 { + return keeper.cli.Must(ctx, "ClaimGuestnetwork", args) + } + return nil +} + func (keeper *OVNNorthboundKeeper) ClaimVpcGuestDnsRecords(ctx context.Context, vpc *agentmodels.Vpc) error { var ( grs = map[string][]string{} diff --git a/pkg/vpcagent/ovn/routes.go b/pkg/vpcagent/ovn/routes.go new file mode 100644 index 0000000000..ede9bd3c66 --- /dev/null +++ b/pkg/vpcagent/ovn/routes.go @@ -0,0 +1,69 @@ +// 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 ovn + +import ( + computeapis "yunion.io/x/onecloud/pkg/apis/compute" + agentmodels "yunion.io/x/onecloud/pkg/vpcagent/models" +) + +type resolvedRoutes []resolvedRoute + +type resolvedRoute struct { + Cidr string + NextHop string + Network *agentmodels.Network + Guestnetwork *agentmodels.Guestnetwork +} + +func resolveRoutes(vpc *agentmodels.Vpc, mss *agentmodels.ModelSets) resolvedRoutes { + if vpc.RouteTable == nil || vpc.RouteTable.Routes == nil { + return nil + } + var r resolvedRoutes + + routesModel := *vpc.RouteTable.Routes + for _, routeModel := range routesModel { + switch routeModel.NextHopType { + case computeapis.Next_HOP_TYPE_IP: + r = append(r, resolvedRoute{ + Cidr: routeModel.Cidr, + NextHop: routeModel.NextHopId, + }) + case computeapis.Next_HOP_TYPE_INSTANCE: + guestId := routeModel.NextHopId + guest, ok := mss.Guests[guestId] + if !ok { + break + } + for _, gn := range guest.Guestnetworks { + network := gn.Network + gnVpc := network.Vpc + if gnVpc.Id != vpc.Id { + continue + } + r = append(r, resolvedRoute{ + Cidr: routeModel.Cidr, + NextHop: gn.IpAddr, + Network: network, + Guestnetwork: gn, + }) + } + default: + return nil + } + } + return r +} diff --git a/pkg/vpcagent/ovn/worker.go b/pkg/vpcagent/ovn/worker.go index 3e2b5a09ec..7dc0496da6 100644 --- a/pkg/vpcagent/ovn/worker.go +++ b/pkg/vpcagent/ovn/worker.go @@ -164,6 +164,8 @@ func (w *Worker) run(ctx context.Context, mss *agentmodels.ModelSets) (err error ovndb.ClaimGuestnetwork(ctx, guestnetwork) } } + routes := resolveRoutes(vpc, mss) + ovndb.ClaimRoutes(ctx, vpc, routes) } for _, vpc := range mss.Vpcs { if vpc.Id == apis.DEFAULT_VPC_ID {