routetable.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  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. package aliyun
  15. import (
  16. "fmt"
  17. "strings"
  18. "time"
  19. "yunion.io/x/log"
  20. api "yunion.io/x/cloudmux/pkg/apis/compute"
  21. "yunion.io/x/cloudmux/pkg/cloudprovider"
  22. "yunion.io/x/cloudmux/pkg/multicloud"
  23. )
  24. // {"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"}
  25. type SNextHops struct {
  26. NextHop []string
  27. }
  28. type SRouteEntry struct {
  29. multicloud.SResourceBase
  30. AliyunTags
  31. routeTable *SRouteTable
  32. RouteTableId string
  33. Type string
  34. DestinationCidrBlock string
  35. NextHopType string
  36. InstanceId string
  37. RouteEntryId string
  38. RouteEntryName string
  39. NextHops SNextHops
  40. }
  41. func (route *SRouteEntry) GetId() string {
  42. return fmt.Sprintf("%s-%s-%s", route.RouteTableId, route.DestinationCidrBlock, route.NextHopType)
  43. }
  44. func (route *SRouteEntry) GetName() string {
  45. return route.RouteEntryName
  46. }
  47. func (route *SRouteEntry) GetGlobalId() string {
  48. return route.GetId()
  49. }
  50. func (route *SRouteEntry) GetStatus() string {
  51. return api.ROUTE_ENTRY_STATUS_AVAILIABLE
  52. }
  53. func (route *SRouteEntry) Refresh() error {
  54. return nil
  55. }
  56. func (route *SRouteEntry) IsEmulated() bool {
  57. return false
  58. }
  59. // Custom:自定义路由。 System:系统路由。
  60. func (route *SRouteEntry) GetType() string {
  61. return route.Type
  62. }
  63. func (route *SRouteEntry) GetCidr() string {
  64. return route.DestinationCidrBlock
  65. }
  66. func (route *SRouteEntry) GetNextHopType() string {
  67. switch route.NextHopType {
  68. case "Instance":
  69. return api.NEXT_HOP_TYPE_INSTANCE
  70. case "HaVip":
  71. return api.NEXT_HOP_TYPE_HAVIP
  72. case "VpnGateway":
  73. return api.NEXT_HOP_TYPE_VPN
  74. case "NatGateway":
  75. return api.NEXT_HOP_TYPE_NAT
  76. case "NetworkInterface":
  77. return api.NEXT_HOP_TYPE_NETWORK
  78. case "RouterInterface":
  79. return api.NEXT_HOP_TYPE_ROUTER
  80. case "IPv6Gateway":
  81. return api.NEXT_HOP_TYPE_IPV6
  82. case "InternetGateway":
  83. return api.NEXT_HOP_TYPE_INTERNET
  84. case "Next_HOP_TYPE_EGRESS_INTERNET":
  85. return api.NEXT_HOP_TYPE_EGRESS_INTERNET
  86. default:
  87. return ""
  88. }
  89. }
  90. func (route *SRouteEntry) GetNextHop() string {
  91. return route.InstanceId
  92. }
  93. type SRouteEntrys struct {
  94. RouteEntry []*SRouteEntry
  95. }
  96. type SRouteTable struct {
  97. multicloud.SResourceBase
  98. AliyunTags
  99. region *SRegion
  100. vpc *SVpc
  101. routes []cloudprovider.ICloudRoute
  102. VpcId string
  103. CreationTime time.Time
  104. RouteEntrys SRouteEntrys
  105. VRouterId string
  106. Description string
  107. RouteTableId string
  108. RouteTableName string
  109. RouteTableType string
  110. RouterId string
  111. RouterType string
  112. VSwitchIds SRouteTableVSwitchIds
  113. }
  114. type SRouteTableVSwitchIds struct {
  115. VSwitchId []string
  116. }
  117. type sDescribeRouteTablesResponseRouteTables struct {
  118. RouteTable []SRouteTable
  119. }
  120. type sDescribeRouteTablesResponse struct {
  121. RouteTables sDescribeRouteTablesResponseRouteTables
  122. TotalCount int
  123. }
  124. func (self *SRouteTable) GetDescription() string {
  125. return self.Description
  126. }
  127. func (self *SRouteTable) GetId() string {
  128. return self.RouteTableId
  129. }
  130. func (self *SRouteTable) GetGlobalId() string {
  131. return self.RouteTableId
  132. }
  133. func (self *SRouteTable) GetName() string {
  134. return self.RouteTableName
  135. }
  136. func (self *SRouteTable) GetRegionId() string {
  137. return self.region.RegionId
  138. }
  139. // VRouter:VPC路由器。 VBR:边界路由器。
  140. func (self *SRouteTable) GetType() cloudprovider.RouteTableType {
  141. switch self.RouteTableType {
  142. case "System":
  143. return cloudprovider.RouteTableTypeSystem
  144. case "Custom":
  145. return cloudprovider.RouteTableTypeCustom
  146. default:
  147. return cloudprovider.RouteTableTypeSystem
  148. }
  149. }
  150. func (self *SRouteTable) GetVpcId() string {
  151. return self.VpcId
  152. }
  153. func (self *SRouteTable) GetIRoutes() ([]cloudprovider.ICloudRoute, error) {
  154. if self.routes == nil {
  155. err := self.fetchRoutes()
  156. if err != nil {
  157. return nil, err
  158. }
  159. }
  160. return self.routes, nil
  161. }
  162. func (self *SRouteTable) GetStatus() string {
  163. return api.ROUTE_TABLE_AVAILABLE
  164. }
  165. func (self *SRouteTable) IsEmulated() bool {
  166. return false
  167. }
  168. func (self *SRouteTable) Refresh() error {
  169. return nil
  170. }
  171. func (self *SRouteTable) fetchRoutes() error {
  172. routes := []*SRouteEntry{}
  173. for {
  174. parts, total, err := self.RemoteGetRoutes(len(routes), 50)
  175. if err != nil {
  176. return err
  177. }
  178. routes = append(routes, parts...)
  179. if len(routes) >= total {
  180. break
  181. }
  182. }
  183. self.routes = make([]cloudprovider.ICloudRoute, len(routes))
  184. for i := 0; i < len(routes); i++ {
  185. routes[i].routeTable = self
  186. self.routes[i] = routes[i]
  187. }
  188. return nil
  189. }
  190. func (self *SRouteTable) RemoteGetRoutes(offset int, limit int) ([]*SRouteEntry, int, error) {
  191. if limit > 50 || limit <= 0 {
  192. limit = 50
  193. }
  194. params := make(map[string]string)
  195. params["RouteTableId"] = self.RouteTableId
  196. params["PageSize"] = fmt.Sprintf("%d", limit)
  197. params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
  198. body, err := self.region.ecsRequest("DescribeRouteTables", params)
  199. if err != nil {
  200. log.Errorf("RemoteGetRoutes fail %s", err)
  201. return nil, 0, err
  202. }
  203. resp := sDescribeRouteTablesResponse{}
  204. err = body.Unmarshal(&resp)
  205. if err != nil {
  206. log.Errorf("Unmarshal routeEntrys fail %s", err)
  207. return nil, 0, err
  208. }
  209. routeTables := resp.RouteTables.RouteTable
  210. if len(routeTables) != 1 {
  211. return nil, 0, fmt.Errorf("expecting 1 route table, got %d", len(routeTables))
  212. }
  213. routeTable := routeTables[0]
  214. return routeTable.RouteEntrys.RouteEntry, resp.TotalCount, nil
  215. }
  216. func (self *SRouteTable) GetAssociations() []cloudprovider.RouteTableAssociation {
  217. result := []cloudprovider.RouteTableAssociation{}
  218. switch self.RouterType {
  219. case "VRouter":
  220. for i := range self.VSwitchIds.VSwitchId {
  221. association := cloudprovider.RouteTableAssociation{
  222. AssociationId: self.RouteTableId + ":" + self.VSwitchIds.VSwitchId[i],
  223. AssociationType: cloudprovider.RouteTableAssociaToSubnet,
  224. AssociatedResourceId: self.VSwitchIds.VSwitchId[i],
  225. }
  226. result = append(result, association)
  227. }
  228. case "VBR":
  229. association := cloudprovider.RouteTableAssociation{
  230. AssociationId: self.RouteTableId + ":" + self.RouterId,
  231. AssociationType: cloudprovider.RouteTableAssociaToRouter,
  232. AssociatedResourceId: self.RouterId,
  233. }
  234. result = append(result, association)
  235. }
  236. return result
  237. }
  238. func (self *SRouteTable) CreateRoute(route cloudprovider.RouteSet) error {
  239. return cloudprovider.ErrNotSupported
  240. }
  241. func (self *SRouteTable) UpdateRoute(route cloudprovider.RouteSet) error {
  242. return cloudprovider.ErrNotSupported
  243. }
  244. func (self *SRouteTable) RemoveRoute(route cloudprovider.RouteSet) error {
  245. return cloudprovider.ErrNotSupported
  246. }
  247. func (self *SVpc) RemoteGetRouteTableList(offset int, limit int) ([]*SRouteTable, int, error) {
  248. if limit > 50 || limit <= 0 {
  249. limit = 50
  250. }
  251. params := make(map[string]string)
  252. params["VpcId"] = self.VpcId
  253. params["PageSize"] = fmt.Sprintf("%d", limit)
  254. params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1)
  255. body, err := self.region.vpcRequest("DescribeRouteTableList", params)
  256. if err != nil {
  257. log.Errorf("RemoteGetRouteTableList fail %s", err)
  258. return nil, 0, err
  259. }
  260. routeTables := make([]*SRouteTable, 0)
  261. err = body.Unmarshal(&routeTables, "RouterTableList", "RouterTableListType")
  262. if err != nil {
  263. log.Errorf("Unmarshal routeTables fail %s", err)
  264. return nil, 0, err
  265. }
  266. for _, routeTable := range routeTables {
  267. routeTable.region = self.region
  268. }
  269. total, _ := body.Int("TotalCount")
  270. return routeTables, int(total), nil
  271. }
  272. func (region *SRegion) AssociateRouteTable(rtableId string, vswitchId string) error {
  273. params := make(map[string]string)
  274. params["RegionId"] = region.RegionId
  275. params["RouteTableId"] = rtableId
  276. params["VSwitchId"] = vswitchId
  277. _, err := region.vpcRequest("AssociateRouteTable", params)
  278. return err
  279. }
  280. func (region *SRegion) UnassociateRouteTable(rtableId string, vswitchId string) error {
  281. params := make(map[string]string)
  282. params["RegionId"] = region.RegionId
  283. params["RouteTableId"] = rtableId
  284. params["VSwitchId"] = vswitchId
  285. _, err := region.vpcRequest("UnassociateRouteTable", params)
  286. return err
  287. }
  288. func (routeTable *SRouteTable) IsSystem() bool {
  289. return strings.ToLower(routeTable.RouteTableType) == "system"
  290. }