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 }