yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/apsara/routetable.go (about)

     1  // Copyright 2019 Yunion
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package apsara
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  	"time"
    21  
    22  	"yunion.io/x/log"
    23  
    24  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    25  	"yunion.io/x/cloudmux/pkg/multicloud"
    26  )
    27  
    28  // {"CreationTime":"2017-03-19T13:37:40Z","RouteEntrys":{"RouteEntry":[{"DestinationCidrBlock":"172.31.32.0/20","InstanceId":"","NextHopType":"local","NextHops":{"NextHop":[]},"RouteTableId":"vtb-j6c60lectdi80rk5xz43g","Status":"Available","Type":"System"},{"DestinationCidrBlock":"100.64.0.0/10","InstanceId":"","NextHopType":"service","NextHops":{"NextHop":[]},"RouteTableId":"vtb-j6c60lectdi80rk5xz43g","Status":"Available","Type":"System"}]},"RouteTableId":"vtb-j6c60lectdi80rk5xz43g","RouteTableType":"System","VRouterId":"vrt-j6c00qrol733dg36iq4qj"}
    29  
    30  type SNextHops struct {
    31  	NextHop []string
    32  }
    33  
    34  type SRouteEntry struct {
    35  	multicloud.SResourceBase
    36  	ApsaraTags
    37  	routeTable *SRouteTable
    38  
    39  	RouteTableId         string
    40  	Type                 string
    41  	DestinationCidrBlock string
    42  	NextHopType          string
    43  	InstanceId           string
    44  	RouteEntryId         string
    45  	RouteEntryName       string
    46  	NextHops             SNextHops
    47  }
    48  
    49  func (route *SRouteEntry) GetId() string {
    50  	return route.RouteEntryId
    51  }
    52  
    53  func (route *SRouteEntry) GetName() string {
    54  	return route.RouteEntryName
    55  }
    56  
    57  func (route *SRouteEntry) GetGlobalId() string {
    58  	return route.GetId()
    59  }
    60  
    61  func (route *SRouteEntry) GetStatus() string {
    62  	return ""
    63  }
    64  
    65  func (route *SRouteEntry) Refresh() error {
    66  	return nil
    67  }
    68  
    69  func (route *SRouteEntry) IsEmulated() bool {
    70  	return false
    71  }
    72  
    73  // Custom:自定义路由。 System:系统路由。
    74  func (route *SRouteEntry) GetType() string {
    75  	return route.Type
    76  }
    77  
    78  func (route *SRouteEntry) GetCidr() string {
    79  	return route.DestinationCidrBlock
    80  }
    81  
    82  func (route *SRouteEntry) GetNextHopType() string {
    83  	return route.NextHopType
    84  }
    85  
    86  func (route *SRouteEntry) GetNextHop() string {
    87  	return route.InstanceId
    88  }
    89  
    90  type SRouteEntrys struct {
    91  	RouteEntry []*SRouteEntry
    92  }
    93  
    94  type SRouteTable struct {
    95  	multicloud.SResourceBase
    96  	ApsaraTags
    97  	region *SRegion
    98  	vpc    *SVpc
    99  	routes []cloudprovider.ICloudRoute
   100  
   101  	VpcId        string
   102  	CreationTime time.Time
   103  	RouteEntrys  SRouteEntrys
   104  	VRouterId    string
   105  	Description  string
   106  
   107  	RouteTableId   string
   108  	RouteTableName string
   109  	RouteTableType string
   110  	RouterId       string
   111  	RouterType     string
   112  	VSwitchIds     SRouteTableVSwitchIds
   113  }
   114  
   115  type SRouteTableVSwitchIds struct {
   116  	VSwitchId []string
   117  }
   118  
   119  type sDescribeRouteTablesResponseRouteTables struct {
   120  	RouteTable []SRouteTable
   121  }
   122  
   123  type sDescribeRouteTablesResponse struct {
   124  	RouteTables sDescribeRouteTablesResponseRouteTables
   125  	TotalCount  int
   126  }
   127  
   128  func (self *SRouteTable) GetDescription() string {
   129  	return self.Description
   130  }
   131  
   132  func (self *SRouteTable) GetId() string {
   133  	return self.GetGlobalId()
   134  }
   135  
   136  func (self *SRouteTable) GetGlobalId() string {
   137  	return self.RouteTableId
   138  }
   139  
   140  func (self *SRouteTable) GetName() string {
   141  	return self.RouteTableName
   142  }
   143  
   144  func (self *SRouteTable) GetRegionId() string {
   145  	return self.region.RegionId
   146  }
   147  
   148  // VRouter:VPC路由器。 VBR:边界路由器。
   149  func (self *SRouteTable) GetType() cloudprovider.RouteTableType {
   150  	switch self.RouteTableType {
   151  	case "System":
   152  		return cloudprovider.RouteTableTypeSystem
   153  	case "Custom":
   154  		return cloudprovider.RouteTableTypeCustom
   155  	default:
   156  		return cloudprovider.RouteTableTypeSystem
   157  	}
   158  }
   159  
   160  func (self *SRouteTable) GetVpcId() string {
   161  	return self.VpcId
   162  }
   163  
   164  func (self *SRouteTable) GetIRoutes() ([]cloudprovider.ICloudRoute, error) {
   165  	if self.routes == nil {
   166  		err := self.fetchRoutes()
   167  		if err != nil {
   168  			return nil, err
   169  		}
   170  	}
   171  	return self.routes, nil
   172  }
   173  
   174  func (self *SRouteTable) GetStatus() string {
   175  	return ""
   176  }
   177  
   178  func (self *SRouteTable) IsEmulated() bool {
   179  	return false
   180  }
   181  
   182  func (self *SRouteTable) Refresh() error {
   183  	return nil
   184  }
   185  
   186  func (self *SRouteTable) fetchRoutes() error {
   187  	routes := make([]*SRouteEntry, 0)
   188  	for {
   189  		parts, total, err := self.RemoteGetRoutes(len(routes), 50)
   190  		if err != nil {
   191  			return err
   192  		}
   193  		routes = append(routes, parts...)
   194  		if len(routes) >= total {
   195  			break
   196  		}
   197  	}
   198  	self.routes = make([]cloudprovider.ICloudRoute, len(routes))
   199  	for i := 0; i < len(routes); i++ {
   200  		routes[i].routeTable = self
   201  		self.routes[i] = routes[i]
   202  	}
   203  	return nil
   204  }
   205  
   206  func (self *SRouteTable) GetAssociations() []cloudprovider.RouteTableAssociation {
   207  	result := []cloudprovider.RouteTableAssociation{}
   208  	switch self.RouterType {
   209  	case "VRouter":
   210  		for i := range self.VSwitchIds.VSwitchId {
   211  			association := cloudprovider.RouteTableAssociation{
   212  				AssociationId:        self.RouteTableId + ":" + self.VSwitchIds.VSwitchId[i],
   213  				AssociationType:      cloudprovider.RouteTableAssociaToSubnet,
   214  				AssociatedResourceId: self.VSwitchIds.VSwitchId[i],
   215  			}
   216  			result = append(result, association)
   217  		}
   218  	case "VBR":
   219  		association := cloudprovider.RouteTableAssociation{
   220  			AssociationId:        self.RouteTableId + ":" + self.RouterId,
   221  			AssociationType:      cloudprovider.RouteTableAssociaToRouter,
   222  			AssociatedResourceId: self.RouterId,
   223  		}
   224  		result = append(result, association)
   225  	}
   226  
   227  	return result
   228  }
   229  
   230  func (self *SRouteTable) CreateRoute(route cloudprovider.RouteSet) error {
   231  	return cloudprovider.ErrNotSupported
   232  }
   233  
   234  func (self *SRouteTable) UpdateRoute(route cloudprovider.RouteSet) error {
   235  	return cloudprovider.ErrNotSupported
   236  }
   237  
   238  func (self *SRouteTable) RemoveRoute(route cloudprovider.RouteSet) error {
   239  	return cloudprovider.ErrNotSupported
   240  }
   241  
   242  func (self *SRouteTable) RemoteGetRoutes(offset int, limit int) ([]*SRouteEntry, int, error) {
   243  	if limit > 50 || limit <= 0 {
   244  		limit = 50
   245  	}
   246  	params := make(map[string]string)
   247  	params["RouteTableId"] = self.RouteTableId
   248  	params["PageSize"] = fmt.Sprintf("%d", limit)
   249  	params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
   250  
   251  	body, err := self.region.ecsRequest("DescribeRouteTables", params)
   252  	if err != nil {
   253  		log.Errorf("RemoteGetRoutes fail %s", err)
   254  		return nil, 0, err
   255  	}
   256  
   257  	resp := sDescribeRouteTablesResponse{}
   258  	err = body.Unmarshal(&resp)
   259  	if err != nil {
   260  		log.Errorf("Unmarshal routeEntrys fail %s", err)
   261  		return nil, 0, err
   262  	}
   263  	routeTables := resp.RouteTables.RouteTable
   264  	if len(routeTables) != 1 {
   265  		return nil, 0, fmt.Errorf("expecting 1 route table, got %d", len(routeTables))
   266  	}
   267  	routeTable := routeTables[0]
   268  	return routeTable.RouteEntrys.RouteEntry, resp.TotalCount, nil
   269  }
   270  
   271  func (self *SVpc) RemoteGetRouteTableList(offset int, limit int) ([]*SRouteTable, int, error) {
   272  	if limit > 50 || limit <= 0 {
   273  		limit = 50
   274  	}
   275  	params := make(map[string]string)
   276  	params["VpcId"] = self.VpcId
   277  	params["PageSize"] = fmt.Sprintf("%d", limit)
   278  	params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
   279  
   280  	body, err := self.region.vpcRequest("DescribeRouteTableList", params)
   281  	if err != nil {
   282  		log.Errorf("RemoteGetRouteTableList fail %s", err)
   283  		return nil, 0, err
   284  	}
   285  
   286  	routeTables := make([]*SRouteTable, 0)
   287  	err = body.Unmarshal(&routeTables, "RouterTableList", "RouterTableListType")
   288  	if err != nil {
   289  		log.Errorf("Unmarshal routeTables fail %s", err)
   290  		return nil, 0, err
   291  	}
   292  	for _, routeTable := range routeTables {
   293  		routeTable.region = self.region
   294  	}
   295  	total, _ := body.Int("TotalCount")
   296  	return routeTables, int(total), nil
   297  }
   298  
   299  func (region *SRegion) AssociateRouteTable(rtableId string, vswitchId string) error {
   300  	params := make(map[string]string)
   301  	params["RegionId"] = region.RegionId
   302  	params["RouteTableId"] = rtableId
   303  	params["VSwitchId"] = vswitchId
   304  	_, err := region.vpcRequest("AssociateRouteTable", params)
   305  	return err
   306  }
   307  
   308  func (region *SRegion) UnassociateRouteTable(rtableId string, vswitchId string) error {
   309  	params := make(map[string]string)
   310  	params["RegionId"] = region.RegionId
   311  	params["RouteTableId"] = rtableId
   312  	params["VSwitchId"] = vswitchId
   313  	_, err := region.vpcRequest("UnassociateRouteTable", params)
   314  	return err
   315  }
   316  
   317  func (routeTable *SRouteTable) IsSystem() bool {
   318  	return strings.ToLower(routeTable.RouteTableType) == "system"
   319  }