routetable.go 8.2 KB

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