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