yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/huawei/wire.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  	"fmt"
    19  	"time"
    20  
    21  	"yunion.io/x/jsonutils"
    22  	"yunion.io/x/log"
    23  	"yunion.io/x/pkg/errors"
    24  	"yunion.io/x/pkg/util/netutils"
    25  
    26  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    27  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    28  	"yunion.io/x/cloudmux/pkg/multicloud"
    29  )
    30  
    31  // 华为云的子网有点特殊。子网在整个region可用。
    32  type SWire struct {
    33  	multicloud.SResourceBase
    34  	HuaweiTags
    35  	region *SRegion
    36  	vpc    *SVpc
    37  
    38  	inetworks []cloudprovider.ICloudNetwork
    39  }
    40  
    41  func (self *SWire) GetId() string {
    42  	return fmt.Sprintf("%s-%s", self.vpc.GetId(), self.region.GetId())
    43  }
    44  
    45  func (self *SWire) GetName() string {
    46  	return self.GetId()
    47  }
    48  
    49  func (self *SWire) GetGlobalId() string {
    50  	return fmt.Sprintf("%s-%s", self.vpc.GetGlobalId(), self.region.GetGlobalId())
    51  }
    52  
    53  func (self *SWire) GetStatus() string {
    54  	return api.WIRE_STATUS_AVAILABLE
    55  }
    56  
    57  func (self *SWire) Refresh() error {
    58  	return nil
    59  }
    60  
    61  func (self *SWire) IsEmulated() bool {
    62  	return true
    63  }
    64  
    65  func (self *SWire) GetIVpc() cloudprovider.ICloudVpc {
    66  	return self.vpc
    67  }
    68  
    69  func (self *SWire) GetIZone() cloudprovider.ICloudZone {
    70  	return nil
    71  }
    72  
    73  func (self *SWire) GetINetworks() ([]cloudprovider.ICloudNetwork, error) {
    74  	if self.inetworks == nil {
    75  		err := self.vpc.fetchNetworks()
    76  		if err != nil {
    77  			return nil, err
    78  		}
    79  	}
    80  	return self.inetworks, nil
    81  }
    82  
    83  func (self *SWire) GetBandwidth() int {
    84  	return 10000
    85  }
    86  
    87  func (self *SWire) GetINetworkById(netid string) (cloudprovider.ICloudNetwork, error) {
    88  	networks, err := self.GetINetworks()
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	for i := 0; i < len(networks); i += 1 {
    93  		if networks[i].GetGlobalId() == netid {
    94  			return networks[i], nil
    95  		}
    96  	}
    97  	return nil, cloudprovider.ErrNotFound
    98  }
    99  
   100  /*
   101  华为云子网可用区,类似一个zone标签。即使指定了zone子网在整个region依然是可用。
   102  通过华为web控制台创建子网需要指定可用区。这里是不指定的。
   103  */
   104  func (self *SWire) CreateINetwork(opts *cloudprovider.SNetworkCreateOptions) (cloudprovider.ICloudNetwork, error) {
   105  	networkId, err := self.region.createNetwork(self.vpc.GetId(), opts.Name, opts.Cidr, opts.Desc)
   106  	if err != nil {
   107  		log.Errorf("createNetwork error %s", err)
   108  		return nil, err
   109  	}
   110  
   111  	var network *SNetwork
   112  	err = cloudprovider.WaitCreated(5*time.Second, 60*time.Second, func() bool {
   113  		self.inetworks = nil
   114  		network = self.getNetworkById(networkId)
   115  		if network == nil {
   116  			return false
   117  		} else {
   118  			return true
   119  		}
   120  	})
   121  
   122  	if err != nil {
   123  		log.Errorf("cannot find network after create????")
   124  		return nil, err
   125  	}
   126  
   127  	network.wire = self
   128  	return network, nil
   129  }
   130  
   131  func (self *SWire) addNetwork(network *SNetwork) {
   132  	if self.inetworks == nil {
   133  		self.inetworks = make([]cloudprovider.ICloudNetwork, 0)
   134  	}
   135  	find := false
   136  	for i := 0; i < len(self.inetworks); i += 1 {
   137  		if self.inetworks[i].GetId() == network.ID {
   138  			find = true
   139  			break
   140  		}
   141  	}
   142  	if !find {
   143  		self.inetworks = append(self.inetworks, network)
   144  	}
   145  }
   146  
   147  func (self *SWire) getNetworkById(networkId string) *SNetwork {
   148  	networks, err := self.GetINetworks()
   149  	if err != nil {
   150  		return nil
   151  	}
   152  	log.Debugf("search for networks %d", len(networks))
   153  	for i := 0; i < len(networks); i += 1 {
   154  		log.Debugf("search %s", networks[i].GetName())
   155  		network := networks[i]
   156  		if network.GetId() == networkId {
   157  			return network.(*SNetwork)
   158  		}
   159  	}
   160  	return nil
   161  }
   162  
   163  func getDefaultGateWay(cidr string) (string, error) {
   164  	pref, err := netutils.NewIPV4Prefix(cidr)
   165  	if err != nil {
   166  		return "", errors.Wrap(err, "getDefaultGateWay.NewIPV4Prefix")
   167  	}
   168  	startIp := pref.Address.NetAddr(pref.MaskLen) // 0
   169  	startIp = startIp.StepUp()                    // 1
   170  	return startIp.String(), nil
   171  }
   172  
   173  // https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090590.html
   174  // cidr 掩码长度不能大于28
   175  func (self *SRegion) createNetwork(vpcId string, name string, cidr string, desc string) (string, error) {
   176  	gateway, err := getDefaultGateWay(cidr)
   177  	if err != nil {
   178  		return "", err
   179  	}
   180  
   181  	params := jsonutils.NewDict()
   182  	subnetObj := jsonutils.NewDict()
   183  	subnetObj.Add(jsonutils.NewString(name), "name")
   184  	subnetObj.Add(jsonutils.NewString(vpcId), "vpc_id")
   185  	subnetObj.Add(jsonutils.NewString(cidr), "cidr")
   186  	subnetObj.Add(jsonutils.NewString(gateway), "gateway_ip")
   187  	params.Add(subnetObj, "subnet")
   188  
   189  	subnet := SNetwork{}
   190  	err = DoCreate(self.ecsClient.Subnets.Create, params, &subnet)
   191  	return subnet.ID, err
   192  }