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 }