yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/qcloud/vpc_peering_connection.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  	"strings"
    20  	"time"
    21  
    22  	"yunion.io/x/jsonutils"
    23  	"yunion.io/x/pkg/errors"
    24  
    25  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    26  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    27  	"yunion.io/x/cloudmux/pkg/multicloud"
    28  )
    29  
    30  type SVpcPC struct {
    31  	multicloud.SResourceBase
    32  	QcloudTags
    33  	vpc                   *SVpc
    34  	VpcID                 string `json:"vpcId"`
    35  	UnVpcID               string `json:"unVpcId"`
    36  	PeerVpcID             string `json:"peerVpcId"`
    37  	UnPeerVpcID           string `json:"unPeerVpcId"`
    38  	AppID                 string `json:"appId"`
    39  	PeeringConnectionID   string `json:"peeringConnectionId"`
    40  	PeeringConnectionName string `json:"peeringConnectionName"`
    41  	State                 int    `json:"state"`
    42  	CreateTime            string `json:"createTime"`
    43  	Uin                   string `json:"uin"`
    44  	PeerUin               string `json:"peerUin"`
    45  	Region                string `json:"region"`
    46  	PeerRegion            string `json:"peerRegion"`
    47  }
    48  
    49  func (region *SRegion) DescribeVpcPeeringConnections(vpcId string, peeringConnectionId string, offset int, limit int) ([]SVpcPC, int, error) {
    50  	if limit > 50 || limit <= 0 {
    51  		limit = 50
    52  	}
    53  	params := make(map[string]string)
    54  	params["offset"] = fmt.Sprintf("%d", offset)
    55  	params["limit"] = fmt.Sprintf("%d", limit)
    56  	if len(vpcId) > 0 {
    57  		params["vpcId"] = vpcId
    58  	}
    59  	if len(peeringConnectionId) > 0 {
    60  		params["peeringConnectionId"] = peeringConnectionId
    61  	}
    62  	body, err := region.vpc2017Request("DescribeVpcPeeringConnections", params)
    63  	if err != nil {
    64  		return nil, 0, errors.Wrapf(err, `region.vpcRequest("DescribeVpcPeeringConnections", %s)`, jsonutils.Marshal(params).String())
    65  	}
    66  
    67  	total, _ := body.Float("totalCount")
    68  	if total <= 0 {
    69  		return nil, int(total), nil
    70  	}
    71  
    72  	vpcPCs := make([]SVpcPC, 0)
    73  	err = body.Unmarshal(&vpcPCs, "data")
    74  	if err != nil {
    75  		return nil, 0, errors.Wrapf(err, "body.Unmarshal(&vpcPCs,%s)", body.String())
    76  	}
    77  	return vpcPCs, int(total), nil
    78  }
    79  
    80  func (region *SRegion) GetAllVpcPeeringConnections(vpcId string) ([]SVpcPC, error) {
    81  	result := []SVpcPC{}
    82  	for {
    83  		vpcPCS, total, err := region.DescribeVpcPeeringConnections(vpcId, "", len(result), 50)
    84  		if err != nil {
    85  			return nil, errors.Wrapf(err, `client.DescribeVpcPeeringConnections(%s,"",%d,50)`, vpcId, len(result))
    86  		}
    87  		result = append(result, vpcPCS...)
    88  		if total <= len(result) {
    89  			break
    90  		}
    91  	}
    92  	return result, nil
    93  }
    94  
    95  func (region *SRegion) GetVpcPeeringConnectionbyId(vpcPCId string) (*SVpcPC, error) {
    96  	vpcPCs, _, err := region.DescribeVpcPeeringConnections("", vpcPCId, 0, 50)
    97  	if err != nil {
    98  		return nil, errors.Wrapf(err, `client.DescribeVpcPeeringConnections("", %s, 0, 50)`, vpcPCId)
    99  	}
   100  	if len(vpcPCs) < 1 {
   101  		return nil, errors.Wrapf(cloudprovider.ErrNotFound, "GetVpcPeeringConnectionbyId(%s)", vpcPCId)
   102  	}
   103  	if len(vpcPCs) > 1 {
   104  		return nil, errors.Wrapf(cloudprovider.ErrDuplicateId, "GetVpcPeeringConnectionbyId(%s)", vpcPCId)
   105  	}
   106  	return &vpcPCs[0], nil
   107  }
   108  
   109  func (region *SRegion) CreateVpcPeeringConnection(vpcId string, opts *cloudprovider.VpcPeeringConnectionCreateOptions) (string, error) {
   110  	params := make(map[string]string)
   111  	params["vpcId"] = vpcId
   112  	params["peerVpcId"] = opts.PeerVpcId
   113  	params["peerUin"] = opts.PeerAccountId
   114  	params["peeringConnectionName"] = opts.Name
   115  	body, err := region.vpc2017Request("CreateVpcPeeringConnection", params)
   116  	if err != nil {
   117  		return "", errors.Wrapf(err, `client.vpc2017Request("CreateVpcPeeringConnection", %s)`, jsonutils.Marshal(params).String())
   118  	}
   119  	peeringId, err := body.GetString("peeringConnectionId")
   120  	if err != nil {
   121  		return "", errors.Wrapf(err, `%s body.GetString("peeringConnectionId")`, body.String())
   122  	}
   123  	return peeringId, nil
   124  }
   125  
   126  func (region *SRegion) AcceptVpcPeeringConnection(peeringId string) error {
   127  	params := make(map[string]string)
   128  	params["peeringConnectionId"] = peeringId
   129  	_, err := region.vpc2017Request("AcceptVpcPeeringConnection", params)
   130  	if err != nil {
   131  		return errors.Wrapf(err, `client.vpc2017Request("AcceptVpcPeeringConnection",%s)`, jsonutils.Marshal(params).String())
   132  	}
   133  	return nil
   134  }
   135  
   136  func (region *SRegion) DeleteVpcPeeringConnection(peeringId string) error {
   137  	params := make(map[string]string)
   138  	params["peeringConnectionId"] = peeringId
   139  	_, err := region.vpc2017Request("DeleteVpcPeeringConnection", params)
   140  	if err != nil {
   141  		return errors.Wrapf(err, `client.vpc2017Request("DeleteVpcPeeringConnection",%s)`, jsonutils.Marshal(params).String())
   142  	}
   143  	return nil
   144  }
   145  
   146  func (region *SRegion) CreateVpcPeeringConnectionEx(vpcId string, opts *cloudprovider.VpcPeeringConnectionCreateOptions) (int64, error) {
   147  	params := make(map[string]string)
   148  	params["vpcId"] = vpcId
   149  	params["peerVpcId"] = opts.PeerVpcId
   150  	params["peerUin"] = opts.PeerAccountId
   151  	params["peeringConnectionName"] = opts.Name
   152  	params["peerRegion"] = opts.PeerRegionId
   153  	params["bandwidth"] = fmt.Sprintf("%d", opts.Bandwidth)
   154  	body, err := region.vpc2017Request("CreateVpcPeeringConnectionEx", params)
   155  	if err != nil {
   156  		return 0, errors.Wrapf(err, `client.vpc2017Request("CreateVpcPeeringConnectionEx", %s)`, jsonutils.Marshal(params).String())
   157  	}
   158  	taskId, err := body.Int("taskId")
   159  	if err != nil {
   160  		return 0, errors.Wrapf(err, `%s body.Int("taskId")`, body.String())
   161  	}
   162  	return taskId, nil
   163  }
   164  
   165  func (region *SRegion) DescribeVpcTaskResult(taskId string) (int, error) {
   166  	params := make(map[string]string)
   167  	params["taskId"] = taskId
   168  	body, err := region.vpc2017Request("DescribeVpcTaskResult", params)
   169  	if err != nil {
   170  		return 0, errors.Wrapf(err, `client.vpc2017Request("DescribeVpcTaskResult",%s)`, taskId)
   171  	}
   172  	status, err := body.Float("data", "status")
   173  	if err != nil {
   174  		return 0, errors.Wrapf(err, `%s body.Int("data.status")`, body.String())
   175  	}
   176  	return int(status), nil
   177  }
   178  
   179  func (region *SRegion) AcceptVpcPeeringConnectionEx(peeringId string) (int64, error) {
   180  	params := make(map[string]string)
   181  	params["peeringConnectionId"] = peeringId
   182  	body, err := region.vpc2017Request("AcceptVpcPeeringConnectionEx", params)
   183  	if err != nil {
   184  		return 0, errors.Wrapf(err, `client.vpc2017Request("AcceptVpcPeeringConnectionEx", %s)`, jsonutils.Marshal(params).String())
   185  	}
   186  	taskId, err := body.Int("taskId")
   187  	if err != nil {
   188  		return 0, errors.Wrapf(err, `%s body.Int("taskId")`, body.String())
   189  	}
   190  	return taskId, nil
   191  }
   192  
   193  func (region *SRegion) DeleteVpcPeeringConnectionEx(peeringId string) (int64, error) {
   194  	params := make(map[string]string)
   195  	params["peeringConnectionId"] = peeringId
   196  	body, err := region.vpc2017Request("DeleteVpcPeeringConnectionEx", params)
   197  	if err != nil {
   198  		return 0, errors.Wrapf(err, `client.vpc2017Request("DeleteVpcPeeringConnectionEx",%s)`, jsonutils.Marshal(params).String())
   199  	}
   200  	taskId, err := body.Int("taskId")
   201  	if err != nil {
   202  		return 0, errors.Wrapf(err, `%s body.Int("taskId")`, body.String())
   203  	}
   204  	return taskId, nil
   205  }
   206  
   207  func (self *SVpcPC) GetId() string {
   208  	return self.PeeringConnectionID
   209  }
   210  
   211  func (self *SVpcPC) GetName() string {
   212  	return self.PeeringConnectionName
   213  }
   214  
   215  func (self *SVpcPC) GetGlobalId() string {
   216  	return self.GetId()
   217  }
   218  
   219  func (self *SVpcPC) GetStatus() string {
   220  	switch self.State {
   221  	case 1:
   222  		return api.VPC_PEERING_CONNECTION_STATUS_ACTIVE
   223  	case 0:
   224  		return api.VPC_PEERING_CONNECTION_STATUS_PENDING_ACCEPT
   225  	default:
   226  		return api.VPC_PEERING_CONNECTION_STATUS_UNKNOWN
   227  	}
   228  }
   229  
   230  func (self *SVpcPC) Refresh() error {
   231  	svpcPC, err := self.vpc.region.GetVpcPeeringConnectionbyId(self.GetId())
   232  	if err != nil {
   233  		return errors.Wrapf(err, "self.vpc.region.GetVpcPeeringConnectionbyId(%s)", self.GetId())
   234  	}
   235  	return jsonutils.Update(self, svpcPC)
   236  }
   237  
   238  func (self *SVpcPC) GetPeerVpcId() string {
   239  	return self.UnPeerVpcID
   240  }
   241  
   242  func (self *SVpcPC) GetPeerAccountId() string {
   243  	if strings.Contains(self.PeerUin, ".") {
   244  		return strings.Split(self.PeerUin, ".")[0]
   245  	}
   246  	return self.PeerUin
   247  }
   248  
   249  func (self *SVpcPC) GetEnabled() bool {
   250  	return true
   251  }
   252  
   253  func (self *SVpcPC) Delete() error {
   254  	if !self.IsCrossRegion() {
   255  		return self.vpc.region.DeleteVpcPeeringConnection(self.GetId())
   256  	}
   257  	taskId, err := self.vpc.region.DeleteVpcPeeringConnectionEx(self.GetId())
   258  	if err != nil {
   259  		return errors.Wrapf(err, "self.vpc.region.DeleteVpcPeeringConnection(%s)", self.GetId())
   260  	}
   261  	//err = self.vpc.region.WaitVpcTask(fmt.Sprintf("%d", taskId), time.Second*5, time.Minute*10)
   262  	err = cloudprovider.Wait(time.Second*5, time.Minute*6, func() (bool, error) {
   263  		status, err := self.vpc.region.DescribeVpcTaskResult(fmt.Sprintf("%d", taskId))
   264  		if err != nil {
   265  			return false, errors.Wrap(err, "self.vpc.region.DescribeVpcTaskResult")
   266  		}
   267  		//任务的当前状态。0:成功,1:失败,2:进行中。
   268  		if status == 1 {
   269  			return false, errors.Wrap(fmt.Errorf("taskfailed,taskId=%d", taskId), "client.DescribeVpcTaskResult(taskId)")
   270  		}
   271  		if status == 0 {
   272  			return true, nil
   273  		}
   274  		return false, nil
   275  	})
   276  	if err != nil {
   277  		return errors.Wrapf(err, "self.region.WaitTask(%d)", taskId)
   278  	}
   279  	return nil
   280  }
   281  
   282  func (self *SVpcPC) IsCrossRegion() bool {
   283  	if len(self.Region) == 0 {
   284  		return false
   285  	}
   286  	return self.Region != self.PeerRegion
   287  }