yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/huawei/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 huawei
    16  
    17  import (
    18  	"strings"
    19  
    20  	"yunion.io/x/jsonutils"
    21  	"yunion.io/x/pkg/errors"
    22  
    23  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    24  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    25  	"yunion.io/x/cloudmux/pkg/multicloud"
    26  )
    27  
    28  // https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090625.html
    29  type SVpc struct {
    30  	multicloud.SVpc
    31  	HuaweiTags
    32  
    33  	region *SRegion
    34  
    35  	iwires    []cloudprovider.ICloudWire
    36  	secgroups []cloudprovider.ICloudSecurityGroup
    37  
    38  	ID                  string `json:"id"`
    39  	Name                string `json:"name"`
    40  	CIDR                string `json:"cidr"`
    41  	Status              string `json:"status"`
    42  	EnterpriseProjectID string `json:"enterprise_project_id"`
    43  }
    44  
    45  func (self *SVpc) addWire(wire *SWire) {
    46  	if self.iwires == nil {
    47  		self.iwires = make([]cloudprovider.ICloudWire, 0)
    48  	}
    49  	self.iwires = append(self.iwires, wire)
    50  }
    51  
    52  func (self *SVpc) getWireByRegionId(regionId string) *SWire {
    53  	if len(regionId) == 0 {
    54  		return nil
    55  	}
    56  
    57  	for i := 0; i < len(self.iwires); i++ {
    58  		wire := self.iwires[i].(*SWire)
    59  
    60  		if wire.region.GetId() == regionId {
    61  			return wire
    62  		}
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  func (self *SVpc) fetchNetworks() error {
    69  	networks, err := self.region.GetNetwroks(self.ID)
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	// ???????
    75  	if len(networks) == 0 {
    76  		self.iwires = append(self.iwires, &SWire{region: self.region, vpc: self})
    77  		return nil
    78  	}
    79  
    80  	for i := 0; i < len(networks); i += 1 {
    81  		wire := self.getWireByRegionId(self.region.GetId())
    82  		networks[i].wire = wire
    83  		wire.addNetwork(&networks[i])
    84  	}
    85  	return nil
    86  }
    87  
    88  // 华为云安全组可以被同region的VPC使用
    89  func (self *SVpc) fetchSecurityGroups() error {
    90  	secgroups, err := self.region.GetSecurityGroups("", "")
    91  	if err != nil {
    92  		return err
    93  	}
    94  
    95  	self.secgroups = make([]cloudprovider.ICloudSecurityGroup, len(secgroups))
    96  	for i := 0; i < len(secgroups); i++ {
    97  		self.secgroups[i] = &secgroups[i]
    98  	}
    99  	return nil
   100  }
   101  
   102  func (self *SVpc) GetId() string {
   103  	return self.ID
   104  }
   105  
   106  func (self *SVpc) GetName() string {
   107  	if len(self.Name) > 0 {
   108  		return self.Name
   109  	}
   110  	return self.ID
   111  }
   112  
   113  func (self *SVpc) GetGlobalId() string {
   114  	return self.ID
   115  }
   116  
   117  func (self *SVpc) GetStatus() string {
   118  	return api.VPC_STATUS_AVAILABLE
   119  }
   120  
   121  func (self *SVpc) Refresh() error {
   122  	new, err := self.region.getVpc(self.GetId())
   123  	if err != nil {
   124  		return err
   125  	}
   126  	return jsonutils.Update(self, new)
   127  }
   128  
   129  func (self *SVpc) IsEmulated() bool {
   130  	return false
   131  }
   132  
   133  func (self *SVpc) GetRegion() cloudprovider.ICloudRegion {
   134  	return self.region
   135  }
   136  
   137  func (self *SVpc) GetIsDefault() bool {
   138  	// 华为云没有default vpc.
   139  	return false
   140  }
   141  
   142  func (self *SVpc) GetCidrBlock() string {
   143  	return self.CIDR
   144  }
   145  
   146  func (self *SVpc) GetIWires() ([]cloudprovider.ICloudWire, error) {
   147  	if self.iwires == nil {
   148  		err := self.fetchNetworks()
   149  		if err != nil {
   150  			return nil, err
   151  		}
   152  	}
   153  	return self.iwires, nil
   154  }
   155  
   156  func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) {
   157  	if self.secgroups == nil {
   158  		err := self.fetchSecurityGroups()
   159  		if err != nil {
   160  			return nil, err
   161  		}
   162  	}
   163  	return self.secgroups, nil
   164  }
   165  
   166  func (self *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) {
   167  	rtbs, err := self.region.GetRouteTables(self.ID)
   168  	if err != nil {
   169  		return nil, err
   170  	}
   171  	ret := []cloudprovider.ICloudRouteTable{}
   172  	for i := range rtbs {
   173  		rtbs[i].vpc = self
   174  		ret = append(ret, &rtbs[i])
   175  	}
   176  	return ret, nil
   177  }
   178  
   179  func (self *SVpc) GetIRouteTableById(routeTableId string) (cloudprovider.ICloudRouteTable, error) {
   180  	rtb, err := self.region.GetRouteTable(routeTableId)
   181  	if err != nil {
   182  		return nil, err
   183  	}
   184  	rtb.vpc = self
   185  	return rtb, nil
   186  }
   187  
   188  func (self *SVpc) Delete() error {
   189  	// todo: 确定删除VPC的逻辑
   190  	return self.region.DeleteVpc(self.GetId())
   191  }
   192  
   193  func (self *SVpc) GetIWireById(wireId string) (cloudprovider.ICloudWire, error) {
   194  	if self.iwires == nil {
   195  		err := self.fetchNetworks()
   196  		if err != nil {
   197  			return nil, err
   198  		}
   199  	}
   200  	for i := 0; i < len(self.iwires); i += 1 {
   201  		if self.iwires[i].GetGlobalId() == wireId {
   202  			return self.iwires[i], nil
   203  		}
   204  	}
   205  	return nil, cloudprovider.ErrNotFound
   206  }
   207  
   208  func (self *SVpc) GetINatGateways() ([]cloudprovider.ICloudNatGateway, error) {
   209  	nats, err := self.region.GetNatGateways(self.GetId(), "")
   210  	if err != nil {
   211  		return nil, err
   212  	}
   213  	ret := make([]cloudprovider.ICloudNatGateway, len(nats))
   214  	for i := 0; i < len(nats); i++ {
   215  		ret[i] = &nats[i]
   216  	}
   217  	return ret, nil
   218  }
   219  
   220  func (self *SVpc) GetICloudVpcPeeringConnections() ([]cloudprovider.ICloudVpcPeeringConnection, error) {
   221  	svpcPCs, err := self.getVpcPeeringConnections()
   222  	if err != nil {
   223  		return nil, errors.Wrap(err, "self.getVpcPeeringConnections()")
   224  	}
   225  	ivpcPCs := []cloudprovider.ICloudVpcPeeringConnection{}
   226  	for i := range svpcPCs {
   227  		ivpcPCs = append(ivpcPCs, &svpcPCs[i])
   228  	}
   229  	return ivpcPCs, nil
   230  }
   231  
   232  func (self *SVpc) GetICloudAccepterVpcPeeringConnections() ([]cloudprovider.ICloudVpcPeeringConnection, error) {
   233  	svpcPCs, err := self.getAccepterVpcPeeringConnections()
   234  	if err != nil {
   235  		return nil, errors.Wrap(err, "self.getAccepterVpcPeeringConnections()")
   236  	}
   237  	ivpcPCs := []cloudprovider.ICloudVpcPeeringConnection{}
   238  	for i := range svpcPCs {
   239  		ivpcPCs = append(ivpcPCs, &svpcPCs[i])
   240  	}
   241  	return ivpcPCs, nil
   242  }
   243  
   244  func (self *SVpc) GetICloudVpcPeeringConnectionById(id string) (cloudprovider.ICloudVpcPeeringConnection, error) {
   245  	svpcPC, err := self.getVpcPeeringConnectionById(id)
   246  	if err != nil {
   247  		return nil, errors.Wrapf(err, "self.getVpcPeeringConnectionById(%s)", id)
   248  	}
   249  	return svpcPC, nil
   250  }
   251  
   252  func (self *SVpc) CreateICloudVpcPeeringConnection(opts *cloudprovider.VpcPeeringConnectionCreateOptions) (cloudprovider.ICloudVpcPeeringConnection, error) {
   253  	svpcPC, err := self.region.CreateVpcPeering(self.GetId(), opts)
   254  	if err != nil {
   255  		return nil, errors.Wrapf(err, "self.region.CreateVpcPeering(%s,%s)", self.GetId(), jsonutils.Marshal(opts).String())
   256  	}
   257  	svpcPC.vpc = self
   258  	return svpcPC, nil
   259  }
   260  func (self *SVpc) AcceptICloudVpcPeeringConnection(id string) error {
   261  	vpcPC, err := self.getVpcPeeringConnectionById(id)
   262  	if err != nil {
   263  		return errors.Wrapf(err, "self.getVpcPeeringConnectionById(%s)", id)
   264  	}
   265  	if vpcPC.GetStatus() == api.VPC_PEERING_CONNECTION_STATUS_ACTIVE {
   266  		return nil
   267  	}
   268  	if vpcPC.GetStatus() == api.VPC_PEERING_CONNECTION_STATUS_UNKNOWN {
   269  		return errors.Wrapf(cloudprovider.ErrInvalidStatus, "vpcPC: %s", jsonutils.Marshal(vpcPC).String())
   270  	}
   271  	err = self.region.AcceptVpcPeering(id)
   272  	if err != nil {
   273  		return errors.Wrapf(err, "self.region.AcceptVpcPeering(%s)", id)
   274  	}
   275  	return nil
   276  }
   277  
   278  func (self *SVpc) GetAuthorityOwnerId() string {
   279  	return self.region.client.projectId
   280  }
   281  
   282  func (self *SVpc) getVpcPeeringConnections() ([]SVpcPeering, error) {
   283  	svpcPeerings, err := self.region.GetVpcPeerings(self.GetId())
   284  	if err != nil {
   285  		return nil, errors.Wrapf(err, "self.region.GetVpcPeerings(%s)", self.GetId())
   286  	}
   287  	vpcPCs := []SVpcPeering{}
   288  	for i := range svpcPeerings {
   289  		if svpcPeerings[i].GetVpcId() == self.GetId() {
   290  			svpcPeerings[i].vpc = self
   291  			vpcPCs = append(vpcPCs, svpcPeerings[i])
   292  		}
   293  	}
   294  	return vpcPCs, nil
   295  }
   296  
   297  func (self *SVpc) getAccepterVpcPeeringConnections() ([]SVpcPeering, error) {
   298  	svpcPeerings, err := self.region.GetVpcPeerings(self.GetId())
   299  	if err != nil {
   300  		return nil, errors.Wrapf(err, "self.region.GetVpcPeerings(%s)", self.GetId())
   301  	}
   302  	vpcPCs := []SVpcPeering{}
   303  	for i := range svpcPeerings {
   304  		if svpcPeerings[i].GetPeerVpcId() == self.GetId() {
   305  			svpcPeerings[i].vpc = self
   306  			vpcPCs = append(vpcPCs, svpcPeerings[i])
   307  		}
   308  	}
   309  	return vpcPCs, nil
   310  }
   311  
   312  func (self *SVpc) getVpcPeeringConnectionById(id string) (*SVpcPeering, error) {
   313  	svpcPC, err := self.region.GetVpcPeering(id)
   314  	if err != nil {
   315  		return nil, errors.Wrapf(err, "self.region.GetVpcPeering(%s)", id)
   316  	}
   317  	svpcPC.vpc = self
   318  	return svpcPC, nil
   319  }
   320  
   321  func (self *SRegion) getVpc(vpcId string) (*SVpc, error) {
   322  	vpc := SVpc{}
   323  	err := DoGet(self.ecsClient.Vpcs.Get, vpcId, nil, &vpc)
   324  	if err != nil && strings.Contains(err.Error(), "RouterNotFound") {
   325  		return nil, cloudprovider.ErrNotFound
   326  	}
   327  	vpc.region = self
   328  	return &vpc, err
   329  }
   330  
   331  func (self *SRegion) DeleteVpc(vpcId string) error {
   332  	if vpcId != "default" {
   333  		secgroups, err := self.GetSecurityGroups(vpcId, "")
   334  		if err != nil {
   335  			return errors.Wrap(err, "GetSecurityGroups")
   336  		}
   337  		for _, secgroup := range secgroups {
   338  			err = self.DeleteSecurityGroup(secgroup.ID)
   339  			if err != nil {
   340  				return errors.Wrapf(err, "DeleteSecurityGroup(%s)", secgroup.ID)
   341  			}
   342  		}
   343  	}
   344  	return DoDelete(self.ecsClient.Vpcs.Delete, vpcId, nil, nil)
   345  }
   346  
   347  // https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090625.html
   348  func (self *SRegion) GetVpcs() ([]SVpc, error) {
   349  	querys := make(map[string]string)
   350  
   351  	vpcs := make([]SVpc, 0)
   352  	err := doListAllWithMarker(self.ecsClient.Vpcs.List, querys, &vpcs)
   353  	if err != nil {
   354  		return nil, err
   355  	}
   356  
   357  	for i := range vpcs {
   358  		vpcs[i].region = self
   359  	}
   360  	return vpcs, err
   361  }