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