yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aliyun/cloud_enterprise_network.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 "strconv" 19 "strings" 20 21 "yunion.io/x/jsonutils" 22 "yunion.io/x/pkg/errors" 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 type SCen struct { 30 multicloud.SResourceBase 31 AliyunTags 32 client *SAliyunClient 33 Status string `json:"Status"` 34 ProtectionLevel string `json:"ProtectionLevel"` 35 CenID string `json:"CenId"` 36 CreationTime string `json:"CreationTime"` 37 CenBandwidthPackageIds CenBandwidthPackageIds `json:"CenBandwidthPackageIds"` 38 Name string `json:"Name"` 39 } 40 41 type SCens struct { 42 TotalCount int `json:"TotalCount"` 43 RequestID string `json:"RequestId"` 44 PageSize int `json:"PageSize"` 45 PageNumber int `json:"PageNumber"` 46 Cens sCens `json:"Cens"` 47 } 48 49 type CenBandwidthPackageIds struct { 50 CenBandwidthPackageID []string `json:"CenBandwidthPackageId"` 51 } 52 53 type sCens struct { 54 Cen []SCen `json:"Cen"` 55 } 56 57 type SCenChildInstances struct { 58 PageNumber int `json:"PageNumber"` 59 ChildInstances sCenChildInstances `json:"ChildInstances"` 60 TotalCount int `json:"TotalCount"` 61 PageSize int `json:"PageSize"` 62 RequestID string `json:"RequestId"` 63 } 64 65 type SCenChildInstance struct { 66 Status string `json:"Status"` 67 ChildInstanceOwnerID string `json:"ChildInstanceOwnerId"` 68 ChildInstanceID string `json:"ChildInstanceId"` 69 ChildInstanceRegionID string `json:"ChildInstanceRegionId"` 70 CenID string `json:"CenId"` 71 ChildInstanceType string `json:"ChildInstanceType"` 72 } 73 74 type sCenChildInstances struct { 75 ChildInstance []SCenChildInstance `json:"ChildInstance"` 76 } 77 78 type SCenAttachInstanceInput struct { 79 InstanceType string 80 InstanceId string 81 InstanceRegion string 82 ChildInstanceOwnerId string 83 } 84 85 func (client *SAliyunClient) DescribeCens(pageNumber int, pageSize int) (SCens, error) { 86 scens := SCens{} 87 params := map[string]string{} 88 params["Action"] = "DescribeCens" 89 params["PageNumber"] = strconv.Itoa(pageNumber) 90 params["PageSize"] = strconv.Itoa(pageSize) 91 resp, err := client.cbnRequest("DescribeCens", params) 92 if err != nil { 93 return scens, errors.Wrap(err, "DescribeCens") 94 } 95 err = resp.Unmarshal(&scens) 96 if err != nil { 97 return scens, errors.Wrap(err, "resp.Unmarshal") 98 } 99 return scens, nil 100 } 101 102 func (client *SAliyunClient) GetAllCens() ([]SCen, error) { 103 pageNumber := 0 104 sCen := []SCen{} 105 for { 106 pageNumber++ 107 cens, err := client.DescribeCens(pageNumber, 20) 108 if err != nil { 109 return nil, errors.Wrapf(err, "client.DescribeCens(%d, 20)", pageNumber) 110 } 111 sCen = append(sCen, cens.Cens.Cen...) 112 if len(sCen) >= cens.TotalCount { 113 break 114 } 115 } 116 for i := 0; i < len(sCen); i++ { 117 sCen[i].client = client 118 } 119 return sCen, nil 120 } 121 122 func (client *SAliyunClient) CreateCen(opts *cloudprovider.SInterVpcNetworkCreateOptions) (string, error) { 123 params := map[string]string{} 124 params["Name"] = opts.Name 125 params["Description"] = opts.Desc 126 resp, err := client.cbnRequest("CreateCen", params) 127 if err != nil { 128 return "", errors.Wrap(err, "CreateCen") 129 } 130 type CentId struct { 131 CenId string `json:"CenId"` 132 } 133 centId := CentId{} 134 err = resp.Unmarshal(¢Id) 135 if err != nil { 136 return "", errors.Wrap(err, "resp.Unmarshal") 137 } 138 return centId.CenId, nil 139 } 140 141 func (client *SAliyunClient) DeleteCen(id string) error { 142 params := map[string]string{} 143 params["CenId"] = id 144 _, err := client.cbnRequest("DeleteCen", params) 145 if err != nil { 146 return errors.Wrap(err, "DeleteCen") 147 } 148 return nil 149 } 150 151 func (client *SAliyunClient) DescribeCenAttachedChildInstances(cenId string, pageNumber int, pageSize int) (SCenChildInstances, error) { 152 scenChilds := SCenChildInstances{} 153 params := map[string]string{} 154 params["CenId"] = cenId 155 params["PageNumber"] = strconv.Itoa(pageNumber) 156 params["PageSize"] = strconv.Itoa(pageSize) 157 resp, err := client.cbnRequest("DescribeCenAttachedChildInstances", params) 158 if err != nil { 159 return scenChilds, errors.Wrap(err, "DescribeCenAttachedChildInstances") 160 } 161 err = resp.Unmarshal(&scenChilds) 162 if err != nil { 163 return scenChilds, errors.Wrap(err, "resp.Unmarshal") 164 } 165 return scenChilds, nil 166 } 167 168 func (client *SAliyunClient) GetAllCenAttachedChildInstances(cenId string) ([]SCenChildInstance, error) { 169 pageNumber := 0 170 scenChilds := []SCenChildInstance{} 171 for { 172 pageNumber++ 173 cenChilds, err := client.DescribeCenAttachedChildInstances(cenId, pageNumber, 20) 174 if err != nil { 175 return nil, errors.Wrapf(err, "client.DescribeCens(%d, 20)", pageNumber) 176 } 177 scenChilds = append(scenChilds, cenChilds.ChildInstances.ChildInstance...) 178 if len(scenChilds) >= cenChilds.TotalCount { 179 break 180 } 181 } 182 return scenChilds, nil 183 } 184 185 func (client *SAliyunClient) AttachCenChildInstance(cenId string, instance SCenAttachInstanceInput) error { 186 params := map[string]string{} 187 params["CenId"] = cenId 188 params["ChildInstanceId"] = instance.InstanceId 189 params["ChildInstanceRegionId"] = instance.InstanceRegion 190 params["ChildInstanceType"] = instance.InstanceType 191 params["ChildInstanceOwnerId"] = instance.ChildInstanceOwnerId 192 _, err := client.cbnRequest("AttachCenChildInstance", params) 193 if err != nil { 194 return errors.Wrap(err, "AttachCenChildInstance") 195 } 196 return nil 197 } 198 199 func (client *SAliyunClient) DetachCenChildInstance(cenId string, instance SCenAttachInstanceInput) error { 200 params := map[string]string{} 201 params["CenId"] = cenId 202 params["ChildInstanceId"] = instance.InstanceId 203 params["ChildInstanceRegionId"] = instance.InstanceRegion 204 params["ChildInstanceType"] = instance.InstanceType 205 params["ChildInstanceOwnerId"] = instance.ChildInstanceOwnerId 206 _, err := client.cbnRequest("DetachCenChildInstance", params) 207 if err != nil { 208 return errors.Wrap(err, "DetachCenChildInstance") 209 } 210 return nil 211 } 212 213 func (self *SCen) GetId() string { 214 return self.CenID 215 } 216 217 func (self *SCen) GetName() string { 218 return self.Name 219 } 220 221 func (self *SCen) GetGlobalId() string { 222 return self.GetId() 223 } 224 225 func (self *SCen) GetStatus() string { 226 switch self.Status { 227 case "Creating": 228 return api.INTER_VPC_NETWORK_STATUS_CREATING 229 case "Active": 230 return api.INTER_VPC_NETWORK_STATUS_AVAILABLE 231 case "Deleting": 232 return api.INTER_VPC_NETWORK_STATUS_DELETING 233 default: 234 return api.INTER_VPC_NETWORK_STATUS_UNKNOWN 235 } 236 } 237 238 func (self *SCen) Refresh() error { 239 scens, err := self.client.GetAllCens() 240 if err != nil { 241 return errors.Wrap(err, "self.client.GetAllCens()") 242 } 243 for i := range scens { 244 if scens[i].CenID == self.CenID { 245 return jsonutils.Update(self, scens[i]) 246 } 247 } 248 return cloudprovider.ErrNotFound 249 } 250 251 func (self *SCen) GetAuthorityOwnerId() string { 252 return self.client.ownerId 253 } 254 255 func (self *SCen) GetICloudVpcIds() ([]string, error) { 256 childs, err := self.client.GetAllCenAttachedChildInstances(self.GetId()) 257 if err != nil { 258 return nil, errors.Wrap(err, "self.client.GetAllCenAttachedChildInstances(self.GetId())") 259 } 260 vpcIds := []string{} 261 for i := range childs { 262 if childs[i].ChildInstanceType == "VPC" { 263 vpcIds = append(vpcIds, childs[i].ChildInstanceID) 264 } 265 } 266 return vpcIds, nil 267 } 268 269 func (self *SCen) AttachVpc(opts *cloudprovider.SInterVpcNetworkAttachVpcOption) error { 270 instance := SCenAttachInstanceInput{ 271 InstanceType: "VPC", 272 InstanceId: opts.VpcId, 273 InstanceRegion: opts.VpcRegionId, 274 ChildInstanceOwnerId: opts.VpcAuthorityOwnerId, 275 } 276 err := self.client.AttachCenChildInstance(self.GetId(), instance) 277 if err != nil { 278 return errors.Wrapf(err, "self.client.AttachCenChildInstance(%s,%s)", self.GetId(), jsonutils.Marshal(opts).String()) 279 } 280 return nil 281 } 282 283 func (self *SCen) DetachVpc(opts *cloudprovider.SInterVpcNetworkDetachVpcOption) error { 284 instance := SCenAttachInstanceInput{ 285 InstanceType: "VPC", 286 InstanceId: opts.VpcId, 287 InstanceRegion: opts.VpcRegionId, 288 ChildInstanceOwnerId: opts.VpcAuthorityOwnerId, 289 } 290 err := self.client.DetachCenChildInstance(self.GetId(), instance) 291 if err != nil { 292 return errors.Wrapf(err, "self.client.DetachCenChildInstance(%s,%s)", self.GetId(), jsonutils.Marshal(opts).String()) 293 } 294 return nil 295 } 296 297 func (self *SCen) Delete() error { 298 err := self.client.DeleteCen(self.GetId()) 299 if err != nil { 300 return errors.Wrapf(err, "self.client.DeleteCen(%s)", self.GetId()) 301 } 302 return nil 303 } 304 305 func (self *SCen) GetInstanceRouteEntries() ([]SCenRouteEntry, error) { 306 childInstance, err := self.client.GetAllCenAttachedChildInstances(self.GetId()) 307 if err != nil { 308 return nil, errors.Wrap(err, "self.client.GetAllCenAttachedChildInstances(self.GetId())") 309 } 310 result := []SCenRouteEntry{} 311 for i := range childInstance { 312 routes, err := self.client.GetAllCenChildInstanceRouteEntries(self.GetId(), childInstance[i].ChildInstanceID, childInstance[i].ChildInstanceRegionID, childInstance[i].ChildInstanceType) 313 if err != nil { 314 return nil, errors.Wrap(err, "self.client.GetAllCenChildInstanceRouteEntries(self.GetId(), childInstance[i].ChildInstanceID, childInstance[i].ChildInstanceRegionID, childInstance[i].ChildInstanceType)") 315 } 316 for j := range routes { 317 // CEN 类型的路由是通过CEN从其他vpc/vbr的路由表中传播过来的 318 // 只关注路由的发源 319 if routes[j].Type != "CEN" { 320 routes[j].ChildInstance = &childInstance[i] 321 result = append(result, routes[j]) 322 } 323 } 324 } 325 return result, nil 326 } 327 328 func (self *SCen) GetIRoutes() ([]cloudprovider.ICloudInterVpcNetworkRoute, error) { 329 result := []cloudprovider.ICloudInterVpcNetworkRoute{} 330 routeEntries, err := self.GetInstanceRouteEntries() 331 if err != nil { 332 return nil, errors.Wrap(err, "self.GetInstanceRouteEntries()") 333 } 334 for i := range routeEntries { 335 result = append(result, &routeEntries[i]) 336 } 337 return result, nil 338 } 339 340 func (self *SCen) EnableRouteEntry(routeId string) error { 341 idContent := strings.Split(routeId, ":") 342 if len(idContent) != 2 { 343 return errors.Wrapf(cloudprovider.ErrNotSupported, "invalid aliyun generated cenRouteId %s", routeId) 344 } 345 routeTable := idContent[0] 346 cidr := idContent[1] 347 routeEntries, err := self.GetInstanceRouteEntries() 348 if err != nil { 349 return errors.Wrap(err, "self.GetInstanceRouteEntries()") 350 } 351 routeEntry := SCenRouteEntry{} 352 for i := range routeEntries { 353 if routeEntries[i].RouteTableID == routeTable && routeEntries[i].DestinationCidrBlock == cidr { 354 routeEntry = routeEntries[i] 355 break 356 } 357 } 358 if routeEntry.GetEnabled() { 359 return nil 360 } 361 err = self.client.PublishRouteEntries(self.GetId(), routeEntry.GetInstanceId(), routeTable, routeEntry.GetInstanceRegionId(), routeEntry.GetInstanceType(), cidr) 362 if err != nil { 363 return errors.Wrap(err, "self.client.PublishRouteEntries()") 364 } 365 return nil 366 } 367 368 func (self *SCen) DisableRouteEntry(routeId string) error { 369 idContent := strings.Split(routeId, ":") 370 if len(idContent) != 2 { 371 return errors.Wrapf(cloudprovider.ErrNotSupported, "invalid aliyun generated cenRouteId %s", routeId) 372 } 373 routeTable := idContent[0] 374 cidr := idContent[1] 375 routeEntries, err := self.GetInstanceRouteEntries() 376 if err != nil { 377 return errors.Wrap(err, "self.GetInstanceRouteEntries()") 378 } 379 routeEntry := SCenRouteEntry{} 380 for i := range routeEntries { 381 if routeEntries[i].RouteTableID == routeTable && routeEntries[i].DestinationCidrBlock == cidr { 382 routeEntry = routeEntries[i] 383 break 384 } 385 } 386 if !routeEntry.GetEnabled() { 387 return nil 388 } 389 err = self.client.WithdrawPublishedRouteEntries(self.GetId(), routeEntry.GetInstanceId(), routeTable, routeEntry.GetInstanceRegionId(), routeEntry.GetInstanceType(), cidr) 390 if err != nil { 391 return errors.Wrap(err, "self.client.PublishRouteEntries()") 392 } 393 return nil 394 }