mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-21 14:19:49 +08:00
Merge pull request #1758 from Mjoycarry/feature/huawei_routetable_sync
huawei cloud vpc route table list and sync finished; huaweicli routet…
This commit is contained in:
@@ -57,6 +57,7 @@ type Client struct {
|
||||
Users *modules.SUserManager
|
||||
Vpcs *modules.SVpcManager
|
||||
Zones *modules.SZoneManager
|
||||
VpcRoutes *modules.SVpcRouteManager
|
||||
}
|
||||
|
||||
func (self *Client) Init() error {
|
||||
@@ -118,6 +119,7 @@ func (self *Client) initManagers() {
|
||||
self.Bandwidths = modules.NewBandwidthManager(self.regionId, self.projectId, self.signer, self.debug)
|
||||
self.Port = modules.NewPortManager(self.regionId, self.projectId, self.signer, self.debug)
|
||||
self.Flavors = modules.NewFlavorManager(self.regionId, self.projectId, self.signer, self.debug)
|
||||
self.VpcRoutes = modules.NewVpcRouteManager(self.regionId, self.projectId, self.signer, self.debug)
|
||||
}
|
||||
|
||||
self.init = true
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// 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 modules
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/huawei/client/auth"
|
||||
)
|
||||
|
||||
type SVpcRouteManager struct {
|
||||
SResourceManager
|
||||
}
|
||||
|
||||
func NewVpcRouteManager(regionId string, projectId string, signer auth.Signer, debug bool) *SVpcRouteManager {
|
||||
return &SVpcRouteManager{SResourceManager: SResourceManager{
|
||||
SBaseManager: NewBaseManager(signer, debug),
|
||||
ServiceName: ServiceNameVPC,
|
||||
Region: regionId,
|
||||
// the url should not include the field "projectid" in huawei cloud api v2.0
|
||||
ProjectId: "",
|
||||
version: "v2.0",
|
||||
Keyword: "route",
|
||||
KeywordPlural: "routes",
|
||||
|
||||
ResourceKeyword: "vpc/routes",
|
||||
}}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
// 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 huawei
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/pkg/errors"
|
||||
)
|
||||
|
||||
// date: 2019.07.15
|
||||
// In Huawei cloud, there are only two routing tables in a vpc, which are
|
||||
// self-defined routing tables and peer-to-peer routing tables.
|
||||
// The routing in these two tables is different, one's NextHop is a IP address and
|
||||
// the other one's NextHop address is a instance ID of peer-to-peer connection.
|
||||
// The former has no id and it's Type is ROUTE_TYPR_IP, and the latter's Type is ROUTE_TYPE_PEER.
|
||||
|
||||
const (
|
||||
ROUTE_TYPR_IP = "IP"
|
||||
ROUTE_TYPE_PEER = "peering"
|
||||
)
|
||||
|
||||
type SRouteEntry struct {
|
||||
routeTable *SRouteTable
|
||||
|
||||
ID string // route ID
|
||||
Type string // route type
|
||||
Destination string // route destination
|
||||
NextHop string // route next hop (ip or id)
|
||||
}
|
||||
|
||||
func (route *SRouteEntry) GetType() string {
|
||||
return route.Type
|
||||
}
|
||||
|
||||
func (route *SRouteEntry) GetCidr() string {
|
||||
return route.Destination
|
||||
}
|
||||
|
||||
func (route *SRouteEntry) GetNextHopType() string {
|
||||
// In Huawei Cloud, NextHopType is same with itself
|
||||
return route.GetType()
|
||||
}
|
||||
|
||||
func (route *SRouteEntry) GetNextHop() string {
|
||||
return route.NextHop
|
||||
}
|
||||
|
||||
// SRouteTable has no ID and Name because there is no id or name of route table in huawei cloud.
|
||||
// And some method such as GetId and GetName of ICloudRouteTable has no practical meaning
|
||||
type SRouteTable struct {
|
||||
region *SRegion
|
||||
vpc *SVpc
|
||||
|
||||
VpcId string
|
||||
Description string
|
||||
Type string
|
||||
Routes []cloudprovider.ICloudRoute
|
||||
}
|
||||
|
||||
func NewSRouteTable(vpc *SVpc, Type string) SRouteTable {
|
||||
return SRouteTable{
|
||||
region: vpc.region,
|
||||
vpc: vpc,
|
||||
Type: Type,
|
||||
VpcId: vpc.GetId(),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (self *SRouteTable) GetId() string {
|
||||
return self.GetGlobalId()
|
||||
}
|
||||
|
||||
func (self *SRouteTable) GetName() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SRouteTable) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s-%s", self.GetVpcId(), self.GetType())
|
||||
}
|
||||
|
||||
func (self *SRouteTable) GetStatus() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SRouteTable) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRouteTable) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SRouteTable) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRouteTable) GetDescription() string {
|
||||
return self.Description
|
||||
}
|
||||
|
||||
func (self *SRouteTable) GetRegionId() string {
|
||||
return self.region.GetId()
|
||||
}
|
||||
|
||||
func (self *SRouteTable) GetVpcId() string {
|
||||
return self.VpcId
|
||||
}
|
||||
|
||||
func (self *SRouteTable) GetType() string {
|
||||
return self.Type
|
||||
}
|
||||
|
||||
func (self *SRouteTable) GetIRoutes() ([]cloudprovider.ICloudRoute, error) {
|
||||
if self.Routes == nil {
|
||||
err := self.fetchRoutes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return self.Routes, nil
|
||||
}
|
||||
|
||||
// fetchRoutes fetch Routes
|
||||
func (self *SRouteTable) fetchRoutes() error {
|
||||
if self.Type == ROUTE_TYPR_IP {
|
||||
return self.fetchRoutesForIP()
|
||||
}
|
||||
return self.fetchRoutesForPeer()
|
||||
}
|
||||
|
||||
// fetchRoutesForIP fetch the Routes which Type is ROUTE_TYPR_IP through vpc's get api
|
||||
func (self *SRouteTable) fetchRoutesForIP() error {
|
||||
ret, err := self.region.ecsClient.Vpcs.Get(self.GetVpcId(), map[string]string{})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get vpc info error")
|
||||
}
|
||||
routeArray, err := ret.GetArray("routes")
|
||||
routes := make([]cloudprovider.ICloudRoute, 0, len(routeArray))
|
||||
for i := range routeArray {
|
||||
destination, err := routeArray[i].GetString("destination")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get destination of route error")
|
||||
}
|
||||
nextHop, err := routeArray[i].GetString("nexthop")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get nexthop of route error")
|
||||
}
|
||||
routes = append(routes, &SRouteEntry{
|
||||
routeTable: self,
|
||||
ID: "",
|
||||
Type: ROUTE_TYPR_IP,
|
||||
Destination: destination,
|
||||
NextHop: nextHop,
|
||||
})
|
||||
}
|
||||
self.Routes = routes
|
||||
return nil
|
||||
}
|
||||
|
||||
// fetchRoutesForPeer fetch the routes which Type is ROUTE_TYPE_PEER through vpcRoute's list api
|
||||
func (self *SRouteTable) fetchRoutesForPeer() error {
|
||||
retPeer, err := self.region.ecsClient.VpcRoutes.List(map[string]string{"vpc_id": self.GetVpcId()})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get peer route error")
|
||||
}
|
||||
routesPeer := make([]cloudprovider.ICloudRoute, 0, retPeer.Total)
|
||||
for i := range retPeer.Data {
|
||||
route := retPeer.Data[i]
|
||||
id, err := route.GetString("id")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get id of peer route error")
|
||||
}
|
||||
destination, err := route.GetString("destination")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get destination of peer route error")
|
||||
}
|
||||
nextHop, err := route.GetString("nexthop")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get nexthop of peer route error")
|
||||
}
|
||||
routesPeer = append(routesPeer, &SRouteEntry{
|
||||
routeTable: self,
|
||||
ID: id,
|
||||
Type: ROUTE_TYPE_PEER,
|
||||
Destination: destination,
|
||||
NextHop: nextHop,
|
||||
})
|
||||
}
|
||||
self.Routes = routesPeer
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRouteTables return []SRouteTable of self
|
||||
func (self *SVpc) getRouteTables() ([]SRouteTable, error) {
|
||||
// every Vpc has two route table in Huawei Cloud
|
||||
routeTableIp := NewSRouteTable(self, ROUTE_TYPR_IP)
|
||||
routeTablePeer := NewSRouteTable(self, ROUTE_TYPE_PEER)
|
||||
if err := routeTableIp.fetchRoutesForIP(); err != nil {
|
||||
return nil, errors.Wrap(err, `get route table whilc type is "ip" error`)
|
||||
}
|
||||
if err := routeTablePeer.fetchRoutesForPeer(); err != nil {
|
||||
return nil, errors.Wrap(err, `get route table whilc type is "peering" error`)
|
||||
}
|
||||
ret := make([]SRouteTable, 0, 2)
|
||||
if len(routeTableIp.Routes) != 0 {
|
||||
ret = append(ret, routeTableIp)
|
||||
}
|
||||
if len(routeTablePeer.Routes) != 0 {
|
||||
ret = append(ret, routeTablePeer)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// GetRouteTables return []SRouteTable of vpc which id is vpcId if vpcId is no-nil,
|
||||
// otherwise return []SRouteTable of all vpc in this SRegion
|
||||
func (self *SRegion) GetRouteTables(vpcId string) ([]SRouteTable, error) {
|
||||
vpcs, err := self.GetVpcs()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Get Vpcs error")
|
||||
}
|
||||
if vpcId != "" {
|
||||
for i := range vpcs {
|
||||
if vpcs[i].GetId() == vpcId {
|
||||
vpcs = vpcs[i : i+1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
ret := make([]SRouteTable, 0, 2*len(vpcs))
|
||||
for _, vpc := range vpcs {
|
||||
routetables, err := vpc.getRouteTables()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "get vpc's route tables whilch id is %s error", vpc.GetId())
|
||||
}
|
||||
ret = append(ret, routetables...)
|
||||
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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 shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/huawei"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type RouteTableListOption struct {
|
||||
VpcId string `help:"Vpc ID"`
|
||||
}
|
||||
shellutils.R(&RouteTableListOption{}, "routetable-list", "List vpc route tables", func(cli *huawei.SRegion, args *RouteTableListOption) error {
|
||||
routetables, err := cli.GetRouteTables(args.VpcId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(routetables, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
+16
-4
@@ -16,6 +16,7 @@ package huawei
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
@@ -30,8 +31,9 @@ type SVpc struct {
|
||||
|
||||
region *SRegion
|
||||
|
||||
iwires []cloudprovider.ICloudWire
|
||||
secgroups []cloudprovider.ICloudSecurityGroup
|
||||
iwires []cloudprovider.ICloudWire
|
||||
secgroups []cloudprovider.ICloudSecurityGroup
|
||||
routeTables []cloudprovider.ICloudRouteTable
|
||||
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
@@ -169,8 +171,18 @@ func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, err
|
||||
}
|
||||
|
||||
func (self *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) {
|
||||
rts := []cloudprovider.ICloudRouteTable{}
|
||||
return rts, nil
|
||||
if self.routeTables == nil {
|
||||
routeTables, err := self.getRouteTables()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get route table error")
|
||||
}
|
||||
ret := make([]cloudprovider.ICloudRouteTable, len(routeTables))
|
||||
for i := range routeTables {
|
||||
ret[i] = &routeTables[i]
|
||||
}
|
||||
self.routeTables = ret
|
||||
}
|
||||
return self.routeTables, nil
|
||||
}
|
||||
|
||||
func (self *SVpc) Delete() error {
|
||||
|
||||
Reference in New Issue
Block a user