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  }