yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/qcloud/vpc.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 qcloud 16 17 import ( 18 "fmt" 19 "time" 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 SVpc struct { 30 multicloud.SVpc 31 QcloudTags 32 33 region *SRegion 34 35 iwires []cloudprovider.ICloudWire 36 37 secgroups []cloudprovider.ICloudSecurityGroup 38 39 CidrBlock string 40 CreatedTime time.Time 41 DhcpOptionsId string 42 DnsServerSet []string 43 DomainName string 44 EnableMulticast bool 45 IsDefault bool 46 VpcId string 47 VpcName string 48 } 49 50 func (self *SVpc) GetId() string { 51 return self.VpcId 52 } 53 54 func (self *SVpc) GetName() string { 55 if len(self.VpcName) > 0 { 56 return self.VpcName 57 } 58 return self.VpcId 59 } 60 61 func (self *SVpc) GetGlobalId() string { 62 return self.VpcId 63 } 64 65 func (self *SVpc) IsEmulated() bool { 66 return false 67 } 68 69 func (self *SVpc) GetIsDefault() bool { 70 return self.IsDefault 71 } 72 73 func (self *SVpc) GetCidrBlock() string { 74 return self.CidrBlock 75 } 76 77 func (self *SVpc) GetStatus() string { 78 return api.VPC_STATUS_AVAILABLE 79 } 80 81 func (self *SVpc) Delete() error { 82 return self.region.DeleteVpc(self.VpcId) 83 } 84 85 func (self *SVpc) SetTags(tags map[string]string, replace bool) error { 86 return self.region.SetResourceTags("vpc", "vpc", []string{self.VpcId}, tags, replace) 87 } 88 89 func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) { 90 secgroups := make([]SSecurityGroup, 0) 91 for { 92 parts, total, err := self.region.GetSecurityGroups([]string{}, self.VpcId, "", len(secgroups), 50) 93 if err != nil { 94 return nil, err 95 } 96 secgroups = append(secgroups, parts...) 97 if len(secgroups) >= total { 98 break 99 } 100 } 101 isecgroups := make([]cloudprovider.ICloudSecurityGroup, len(secgroups)) 102 for i := 0; i < len(secgroups); i++ { 103 secgroups[i].region = self.region 104 isecgroups[i] = &secgroups[i] 105 } 106 return isecgroups, nil 107 } 108 109 func (self *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) { 110 rts := []cloudprovider.ICloudRouteTable{} 111 routetables, err := self.region.GetAllRouteTables(self.GetId(), []string{}) 112 if err != nil { 113 return nil, errors.Wrapf(err, "self.region.GetAllRouteTables(%s, []string{})", self.GetId()) 114 } 115 for i := range routetables { 116 routetables[i].vpc = self 117 rts = append(rts, &routetables[i]) 118 } 119 return rts, nil 120 } 121 122 func (self *SVpc) GetIRouteTableById(routeTableId string) (cloudprovider.ICloudRouteTable, error) { 123 routetables, err := self.region.GetAllRouteTables(self.GetId(), []string{routeTableId}) 124 if err != nil { 125 return nil, errors.Wrapf(err, "self.region.GetAllRouteTables(%s, []string{})", self.GetId()) 126 } 127 if len(routetables) == 0 { 128 return nil, cloudprovider.ErrNotFound 129 } 130 if len(routetables) > 1 { 131 return nil, cloudprovider.ErrDuplicateId 132 } 133 routetables[0].vpc = self 134 return &routetables[0], nil 135 } 136 137 func (self *SVpc) getWireByZoneId(zoneId string) *SWire { 138 for i := 0; i <= len(self.iwires); i++ { 139 wire := self.iwires[i].(*SWire) 140 if wire.zone.Zone == zoneId { 141 return wire 142 } 143 } 144 return nil 145 } 146 147 func (self *SVpc) GetINatGateways() ([]cloudprovider.ICloudNatGateway, error) { 148 nats := []SNatGateway{} 149 for { 150 part, total, err := self.region.GetNatGateways(self.VpcId, len(nats), 50) 151 if err != nil { 152 return nil, err 153 } 154 nats = append(nats, part...) 155 if len(nats) >= total { 156 break 157 } 158 } 159 inats := []cloudprovider.ICloudNatGateway{} 160 for i := 0; i < len(nats); i++ { 161 nats[i].vpc = self 162 inats = append(inats, &nats[i]) 163 } 164 return inats, nil 165 } 166 167 func (self *SVpc) fetchNetworks() error { 168 networks, total, err := self.region.GetNetworks(nil, self.VpcId, 0, 50) 169 if err != nil { 170 return err 171 } 172 if total > len(networks) { 173 networks, _, err = self.region.GetNetworks(nil, self.VpcId, 0, total) 174 if err != nil { 175 return err 176 } 177 } 178 for i := 0; i < len(networks); i += 1 { 179 wire := self.getWireByZoneId(networks[i].Zone) 180 networks[i].wire = wire 181 wire.addNetwork(&networks[i]) 182 } 183 return nil 184 } 185 186 func (self *SVpc) GetIWireById(wireId string) (cloudprovider.ICloudWire, error) { 187 if self.iwires == nil { 188 err := self.fetchNetworks() 189 if err != nil { 190 return nil, err 191 } 192 } 193 for i := 0; i < len(self.iwires); i += 1 { 194 if self.iwires[i].GetGlobalId() == wireId { 195 return self.iwires[i], nil 196 } 197 } 198 return nil, cloudprovider.ErrNotFound 199 } 200 201 func (self *SVpc) GetIWires() ([]cloudprovider.ICloudWire, error) { 202 if self.iwires == nil { 203 err := self.fetchNetworks() 204 if err != nil { 205 return nil, err 206 } 207 } 208 return self.iwires, nil 209 } 210 211 func (self *SVpc) GetRegion() cloudprovider.ICloudRegion { 212 return self.region 213 } 214 215 func (self *SVpc) Refresh() error { 216 new, err := self.region.getVpc(self.VpcId) 217 if err != nil { 218 return err 219 } 220 return jsonutils.Update(self, new) 221 } 222 223 func (self *SVpc) addWire(wire *SWire) { 224 if self.iwires == nil { 225 self.iwires = make([]cloudprovider.ICloudWire, 0) 226 } 227 self.iwires = append(self.iwires, wire) 228 } 229 230 func (self *SVpc) GetSVpcPeeringConnections() ([]SVpcPC, error) { 231 svpcPCs, err := self.region.GetAllVpcPeeringConnections(self.GetId()) 232 if err != nil { 233 return nil, errors.Wrapf(err, "self.region.GetAllVpcPeeringConnections(%s)", self.GetId()) 234 } 235 ret := []SVpcPC{} 236 for i := range svpcPCs { 237 if svpcPCs[i].UnVpcID == self.VpcId { 238 svpcPCs[i].vpc = self 239 ret = append(ret, svpcPCs[i]) 240 } 241 } 242 return ret, nil 243 } 244 245 func (self *SVpc) GetAccepterSVpcPeeringConnections() ([]SVpcPC, error) { 246 result := []SVpcPC{} 247 svpcPCs, err := self.region.GetAllVpcPeeringConnections("") 248 if err != nil { 249 return nil, errors.Wrapf(err, "self.region.GetAllVpcPeeringConnections(%s)", self.GetId()) 250 } 251 252 for i := range svpcPCs { 253 if svpcPCs[i].PeerVpcID == self.GetId() { 254 svpcPCs[i].vpc = self 255 result = append(result, svpcPCs[i]) 256 } 257 258 } 259 return result, nil 260 } 261 262 func (self *SVpc) GetSVpcPeeringConnectionById(id string) (*SVpcPC, error) { 263 svpcPC, err := self.region.GetVpcPeeringConnectionbyId(id) 264 if err != nil { 265 return nil, errors.Wrapf(err, "self.region.GetVpcPeeringConnectionbyId(%s)", id) 266 } 267 svpcPC.vpc = self 268 return svpcPC, nil 269 } 270 271 func (self *SVpc) CreateSVpcPeeringConnection(opts *cloudprovider.VpcPeeringConnectionCreateOptions) (*SVpcPC, error) { 272 vpcPCId, err := self.region.CreateVpcPeeringConnection(self.GetId(), opts) 273 if err != nil { 274 return nil, errors.Wrapf(err, "self.region.CreateVpcPeeringConnection(%s, %s)", self.GetId(), jsonutils.Marshal(opts).String()) 275 } 276 SvpcPC, err := self.GetSVpcPeeringConnectionById(vpcPCId) 277 if err != nil { 278 return nil, errors.Wrapf(err, "self.GetSVpcPeeringConnectionById(%s)", vpcPCId) 279 } 280 return SvpcPC, nil 281 } 282 283 func (self *SVpc) CreateCrossRegionSVpcPeeringConnection(opts *cloudprovider.VpcPeeringConnectionCreateOptions) (*SVpcPC, error) { 284 taskId, err := self.region.CreateVpcPeeringConnectionEx(self.GetId(), opts) 285 if err != nil { 286 return nil, errors.Wrapf(err, "self.region.CreateVpcPeeringConnectionEx(%s, %s)", self.GetId(), jsonutils.Marshal(opts).String()) 287 } 288 err = cloudprovider.Wait(time.Second*5, time.Minute*6, func() (bool, error) { 289 status, err := self.region.DescribeVpcTaskResult(fmt.Sprintf("%d", taskId)) 290 if err != nil { 291 return false, errors.Wrap(err, "self.vpc.region.DescribeVpcTaskResult") 292 } 293 //任务的当前状态。0:成功,1:失败,2:进行中。 294 if status == 1 { 295 return false, errors.Wrapf(fmt.Errorf("taskfailed,taskId=%d", taskId), "client.DescribeVpcTaskResult(taskId)") 296 } 297 if status == 0 { 298 return true, nil 299 } 300 return false, nil 301 }) 302 if err != nil { 303 return nil, errors.Wrapf(err, "cloudprovider.Wait %d", taskId) 304 } 305 svpcPCs, err := self.GetSVpcPeeringConnections() 306 if err != nil { 307 return nil, errors.Wrap(err, "self.GetSVpcPeeringConnections()") 308 } 309 for i := range svpcPCs { 310 if svpcPCs[i].GetPeerVpcId() == opts.PeerVpcId { 311 return &svpcPCs[i], nil 312 } 313 } 314 return nil, errors.Wrap(cloudprovider.ErrNotFound, "vpcPeeringConnection not found after createEx") 315 } 316 317 func (self *SVpc) AcceptSVpcPeeringConnection(id string) error { 318 err := self.region.AcceptVpcPeeringConnection(id) 319 if err != nil { 320 return errors.Wrapf(err, "self.region.AcceptVpcPeeringConnection(%s)", id) 321 } 322 return nil 323 } 324 325 func (self *SVpc) AcceptCrossRegionSVpcPeeringConnection(id string) error { 326 taskId, err := self.region.AcceptVpcPeeringConnectionEx(id) 327 if err != nil { 328 return errors.Wrapf(err, "self.region.AcceptVpcPeeringConnectionEx(%s)", id) 329 } 330 err = cloudprovider.Wait(time.Second*5, time.Minute*6, func() (bool, error) { 331 status, err := self.region.DescribeVpcTaskResult(fmt.Sprintf("%d", taskId)) 332 if err != nil { 333 return false, errors.Wrap(err, "self.vpc.region.DescribeVpcTaskResult") 334 } 335 //任务的当前状态。0:成功,1:失败,2:进行中。 336 if status == 1 { 337 return false, errors.Wrap(fmt.Errorf("taskfailed,taskId=%d", taskId), "client.DescribeVpcTaskResult(taskId)") 338 } 339 if status == 0 { 340 return true, nil 341 } 342 return false, nil 343 }) 344 if err != nil { 345 return errors.Wrapf(err, " cloudprovider.Wait %d", taskId) 346 } 347 svpcPC, err := self.GetSVpcPeeringConnectionById(id) 348 if err != nil { 349 return errors.Wrapf(err, "self.GetSVpcPeeringConnectionById(%s)", id) 350 } 351 if svpcPC.GetStatus() != api.VPC_PEERING_CONNECTION_STATUS_ACTIVE { 352 return errors.Wrap(cloudprovider.ErrInvalidStatus, "invalid status after AcceptCrossRegionSVpcPeeringConnection") 353 } 354 return nil 355 } 356 357 func (self *SVpc) GetICloudVpcPeeringConnections() ([]cloudprovider.ICloudVpcPeeringConnection, error) { 358 result := []cloudprovider.ICloudVpcPeeringConnection{} 359 SVpcPCs, err := self.GetSVpcPeeringConnections() 360 if err != nil { 361 return nil, errors.Wrap(err, "self.GetSVpcPeeringConnections()") 362 } 363 for i := range SVpcPCs { 364 result = append(result, &SVpcPCs[i]) 365 } 366 return result, nil 367 } 368 369 func (self *SVpc) GetICloudAccepterVpcPeeringConnections() ([]cloudprovider.ICloudVpcPeeringConnection, error) { 370 result := []cloudprovider.ICloudVpcPeeringConnection{} 371 SVpcPCs, err := self.GetAccepterSVpcPeeringConnections() 372 if err != nil { 373 return nil, errors.Wrap(err, "self.GetSVpcPeeringConnections()") 374 } 375 for i := range SVpcPCs { 376 result = append(result, &SVpcPCs[i]) 377 } 378 return result, nil 379 } 380 381 func (self *SVpc) GetICloudVpcPeeringConnectionById(id string) (cloudprovider.ICloudVpcPeeringConnection, error) { 382 svpcPC, err := self.GetSVpcPeeringConnectionById(id) 383 if err != nil { 384 return nil, errors.Wrapf(err, "self.GetSVpcPeeringConnectionById(%s)", id) 385 } 386 return svpcPC, nil 387 } 388 389 func (self *SVpc) CreateICloudVpcPeeringConnection(opts *cloudprovider.VpcPeeringConnectionCreateOptions) (cloudprovider.ICloudVpcPeeringConnection, error) { 390 if self.GetRegion().GetId() == opts.PeerRegionId { 391 return self.CreateSVpcPeeringConnection(opts) 392 } else { 393 return self.CreateCrossRegionSVpcPeeringConnection(opts) 394 } 395 } 396 397 func (self *SVpc) AcceptICloudVpcPeeringConnection(id string) error { 398 svpcPC, err := self.GetSVpcPeeringConnectionById(id) 399 if err != nil { 400 return errors.Wrapf(err, "self.GetSVpcPeeringConnectionById(%s)", id) 401 } 402 if svpcPC.GetStatus() == api.VPC_PEERING_CONNECTION_STATUS_ACTIVE { 403 return nil 404 } 405 406 if !svpcPC.IsCrossRegion() { 407 return self.AcceptSVpcPeeringConnection(id) 408 } else { 409 return self.AcceptCrossRegionSVpcPeeringConnection(id) 410 } 411 } 412 413 func (self *SVpc) GetAuthorityOwnerId() string { 414 return self.region.client.ownerName 415 } 416 417 func (self *SVpc) ProposeJoinICloudInterVpcNetwork(opts *cloudprovider.SVpcJointInterVpcNetworkOption) error { 418 instance := SCcnAttachInstanceInput{ 419 InstanceType: "VPC", 420 InstanceId: self.GetId(), 421 InstanceRegion: self.region.GetId(), 422 } 423 err := self.region.AttachCcnInstances(opts.InterVpcNetworkId, opts.NetworkAuthorityOwnerId, []SCcnAttachInstanceInput{instance}) 424 if err != nil { 425 return errors.Wrapf(err, "self.region.AttachCcnInstance(%s,%s,%s)", jsonutils.Marshal(opts).String(), self.GetId(), self.region.GetId()) 426 } 427 return nil 428 }