yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/huawei/natgateway.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 "time" 20 21 "yunion.io/x/jsonutils" 22 "yunion.io/x/pkg/errors" 23 24 billing_api "yunion.io/x/cloudmux/pkg/apis/billing" 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 SNatGateway struct { 31 multicloud.SNatGatewayBase 32 HuaweiTags 33 region *SRegion 34 35 ID string 36 Name string 37 Description string 38 Spec string 39 Status string 40 InternalNetworkId string 41 CreatedTime string `json:"created_at"` 42 } 43 44 func (gateway *SNatGateway) GetId() string { 45 return gateway.ID 46 } 47 48 func (gateway *SNatGateway) GetName() string { 49 return gateway.Name 50 } 51 52 func (gateway *SNatGateway) GetGlobalId() string { 53 return gateway.GetId() 54 } 55 56 func (gateway *SNatGateway) GetStatus() string { 57 return NatResouceStatusTransfer(gateway.Status) 58 } 59 60 func (self *SNatGateway) Delete() error { 61 return self.region.DeleteNatGateway(self.ID) 62 } 63 64 func (self *SNatGateway) Refresh() error { 65 nat, err := self.region.GetNatGateway(self.ID) 66 if err != nil { 67 return errors.Wrapf(err, "GetNatGateway(%s)", self.ID) 68 } 69 return jsonutils.Update(self, nat) 70 } 71 72 func (self *SNatGateway) GetINetworkId() string { 73 return self.InternalNetworkId 74 } 75 76 func (gateway *SNatGateway) GetNatSpec() string { 77 switch gateway.Spec { 78 case "1": 79 return api.NAT_SPEC_SMALL 80 case "2": 81 return api.NAT_SPEC_MIDDLE 82 case "3": 83 return api.NAT_SPEC_LARGE 84 case "4": 85 return api.NAT_SPEC_XLARGE 86 } 87 return gateway.Spec 88 } 89 90 func (gateway *SNatGateway) GetDescription() string { 91 return gateway.Description 92 } 93 94 func (gateway *SNatGateway) GetBillingType() string { 95 // Up to 2019.07.17, only support post pay 96 return billing_api.BILLING_TYPE_POSTPAID 97 } 98 99 func (gateway *SNatGateway) GetCreatedAt() time.Time { 100 t, _ := time.Parse("2006-01-02 15:04:05.000000", gateway.CreatedTime) 101 return t 102 } 103 104 func (gateway *SNatGateway) GetExpiredAt() time.Time { 105 // no support for expired time 106 return time.Time{} 107 } 108 109 func (gateway *SNatGateway) GetIEips() ([]cloudprovider.ICloudEIP, error) { 110 IEips, err := gateway.region.GetIEips() 111 if err != nil { 112 return nil, errors.Wrapf(err, `get all Eips of region %q error`, gateway.region.GetId()) 113 } 114 dNatTables, err := gateway.GetINatDTable() 115 if err != nil { 116 return nil, errors.Wrapf(err, `get all DNatTable of gateway %q error`, gateway.GetId()) 117 } 118 sNatTables, err := gateway.GetINatSTable() 119 if err != nil { 120 return nil, errors.Wrapf(err, `get all SNatTable of gateway %q error`, gateway.GetId()) 121 } 122 123 // Get natIPSet of nat rules 124 natIPSet := make(map[string]struct{}) 125 for _, snat := range sNatTables { 126 natIPSet[snat.GetIP()] = struct{}{} 127 } 128 for _, dnat := range dNatTables { 129 natIPSet[dnat.GetExternalIp()] = struct{}{} 130 } 131 132 // Add Eip whose GetIpAddr() in natIPSet to ret 133 ret := make([]cloudprovider.ICloudEIP, 0, 2) 134 for i := range IEips { 135 if _, ok := natIPSet[IEips[i].GetIpAddr()]; ok { 136 ret = append(ret, IEips[i]) 137 } 138 } 139 return ret, nil 140 } 141 142 func (gateway *SNatGateway) GetINatDTable() ([]cloudprovider.ICloudNatDEntry, error) { 143 dNatTable, err := gateway.getNatDTable() 144 if err != nil { 145 return nil, errors.Wrapf(err, `get dnat table of nat gateway %q`, gateway.GetId()) 146 } 147 ret := make([]cloudprovider.ICloudNatDEntry, len(dNatTable)) 148 for i := range dNatTable { 149 ret[i] = &dNatTable[i] 150 } 151 return ret, nil 152 } 153 154 func (gateway *SNatGateway) GetINatSTable() ([]cloudprovider.ICloudNatSEntry, error) { 155 sNatTable, err := gateway.getNatSTable() 156 if err != nil { 157 return nil, errors.Wrapf(err, `get dnat table of nat gateway %q`, gateway.GetId()) 158 } 159 ret := make([]cloudprovider.ICloudNatSEntry, len(sNatTable)) 160 for i := range sNatTable { 161 ret[i] = &sNatTable[i] 162 } 163 return ret, nil 164 } 165 166 func (gateway *SNatGateway) CreateINatDEntry(rule cloudprovider.SNatDRule) (cloudprovider.ICloudNatDEntry, error) { 167 dnat, err := gateway.region.CreateNatDEntry(rule, gateway.GetId()) 168 if err != nil { 169 return nil, err 170 } 171 dnat.gateway = gateway 172 return &dnat, nil 173 } 174 175 func (gateway *SNatGateway) CreateINatSEntry(rule cloudprovider.SNatSRule) (cloudprovider.ICloudNatSEntry, error) { 176 snat, err := gateway.region.CreateNatSEntry(rule, gateway.GetId()) 177 if err != nil { 178 return nil, err 179 } 180 snat.gateway = gateway 181 return &snat, nil 182 } 183 184 func (gateway *SNatGateway) GetINatDEntryByID(id string) (cloudprovider.ICloudNatDEntry, error) { 185 dnat, err := gateway.region.GetNatDEntryByID(id) 186 if err != nil { 187 return nil, err 188 } 189 dnat.gateway = gateway 190 return &dnat, nil 191 } 192 193 func (gateway *SNatGateway) GetINatSEntryByID(id string) (cloudprovider.ICloudNatSEntry, error) { 194 snat, err := gateway.region.GetNatSEntryByID(id) 195 if err != nil { 196 return nil, err 197 } 198 snat.gateway = gateway 199 return &snat, nil 200 } 201 202 func (region *SRegion) GetNatGateways(vpcID, natGatewayID string) ([]SNatGateway, error) { 203 queues := make(map[string]string) 204 if len(natGatewayID) != 0 { 205 queues["id"] = natGatewayID 206 } 207 if len(vpcID) != 0 { 208 queues["router_id"] = vpcID 209 } 210 natGateways := make([]SNatGateway, 0, 2) 211 err := doListAllWithMarker(region.ecsClient.NatGateways.List, queues, &natGateways) 212 if err != nil { 213 return nil, errors.Wrapf(err, "get nat gateways error by natgatewayid") 214 } 215 for i := range natGateways { 216 natGateways[i].region = region 217 } 218 return natGateways, nil 219 } 220 221 func (region *SRegion) CreateNatDEntry(rule cloudprovider.SNatDRule, gatewayID string) (SNatDEntry, error) { 222 params := make(map[string]interface{}) 223 params["nat_gateway_id"] = gatewayID 224 params["private_ip"] = rule.InternalIP 225 params["internal_service_port"] = rule.InternalPort 226 params["floating_ip_id"] = rule.ExternalIPID 227 params["external_service_port"] = rule.ExternalPort 228 params["protocol"] = rule.Protocol 229 230 packParams := map[string]map[string]interface{}{ 231 "dnat_rule": params, 232 } 233 234 ret := SNatDEntry{} 235 err := DoCreate(region.ecsClient.DNatRules.Create, jsonutils.Marshal(packParams), &ret) 236 if err != nil { 237 return SNatDEntry{}, errors.Wrapf(err, `create dnat rule of nat gateway %q failed`, gatewayID) 238 } 239 return ret, nil 240 } 241 242 func (region *SRegion) CreateNatSEntry(rule cloudprovider.SNatSRule, gatewayID string) (SNatSEntry, error) { 243 params := make(map[string]interface{}) 244 params["nat_gateway_id"] = gatewayID 245 if len(rule.NetworkID) != 0 { 246 params["network_id"] = rule.NetworkID 247 } 248 if len(rule.SourceCIDR) != 0 { 249 params["cidr"] = rule.SourceCIDR 250 } 251 params["floating_ip_id"] = rule.ExternalIPID 252 253 packParams := map[string]map[string]interface{}{ 254 "snat_rule": params, 255 } 256 257 ret := SNatSEntry{} 258 err := DoCreate(region.ecsClient.SNatRules.Create, jsonutils.Marshal(packParams), &ret) 259 if err != nil { 260 return SNatSEntry{}, errors.Wrapf(err, `create snat rule of nat gateway %q failed`, gatewayID) 261 } 262 return ret, nil 263 } 264 265 func (region *SRegion) GetNatDEntryByID(id string) (SNatDEntry, error) { 266 dnat := SNatDEntry{} 267 err := DoGet(region.ecsClient.DNatRules.Get, id, map[string]string{}, &dnat) 268 269 if err != nil { 270 return SNatDEntry{}, err 271 } 272 return dnat, nil 273 } 274 275 func (region *SRegion) GetNatSEntryByID(id string) (SNatSEntry, error) { 276 snat := SNatSEntry{} 277 err := DoGet(region.ecsClient.SNatRules.Get, id, map[string]string{}, &snat) 278 if err != nil { 279 return SNatSEntry{}, cloudprovider.ErrNotFound 280 } 281 return snat, nil 282 } 283 284 func NatResouceStatusTransfer(status string) string { 285 // In Huawei Cloud, there are isx resource status of Nat, "ACTIVE", "PENDING_CREATE", 286 // "PENDING_UPDATE", "PENDING_DELETE", "EIP_FREEZED", "INACTIVE". 287 switch status { 288 case "ACTIVE": 289 return api.NAT_STAUTS_AVAILABLE 290 case "PENDING_CREATE": 291 return api.NAT_STATUS_ALLOCATE 292 case "PENDING_UPDATE", "PENDING_DELETE": 293 return api.NAT_STATUS_DEPLOYING 294 default: 295 return api.NAT_STATUS_UNKNOWN 296 } 297 } 298 299 func (self *SRegion) GetNatGateway(id string) (*SNatGateway, error) { 300 resp, err := self.ecsClient.NatGateways.Get(id, nil) 301 if err != nil { 302 return nil, errors.Wrapf(err, "NatGateways.Get(%s)", id) 303 } 304 nat := &SNatGateway{region: self} 305 err = resp.Unmarshal(nat) 306 return nat, errors.Wrap(err, "resp.Unmarshal") 307 } 308 309 func (self *SVpc) CreateINatGateway(opts *cloudprovider.NatGatewayCreateOptions) (cloudprovider.ICloudNatGateway, error) { 310 nat, err := self.region.CreateNatGateway(opts) 311 if err != nil { 312 return nil, errors.Wrapf(err, "CreateNatGateway") 313 } 314 return nat, nil 315 } 316 317 func (self *SRegion) CreateNatGateway(opts *cloudprovider.NatGatewayCreateOptions) (*SNatGateway, error) { 318 spec := "" 319 switch strings.ToLower(opts.NatSpec) { 320 case api.NAT_SPEC_SMALL: 321 spec = "1" 322 case api.NAT_SPEC_MIDDLE: 323 spec = "2" 324 case api.NAT_SPEC_LARGE: 325 spec = "3" 326 case api.NAT_SPEC_XLARGE: 327 spec = "4" 328 } 329 params := jsonutils.Marshal(map[string]map[string]interface{}{ 330 "nat_gateway": map[string]interface{}{ 331 "name": opts.Name, 332 "description": opts.Desc, 333 "router_id": opts.VpcId, 334 "internal_network_id": opts.NetworkId, 335 "spec": spec, 336 }, 337 }) 338 resp, err := self.ecsClient.NatGateways.Create(params) 339 if err != nil { 340 return nil, errors.Wrap(err, "AsyncCreate") 341 } 342 nat := &SNatGateway{region: self} 343 err = resp.Unmarshal(nat) 344 if err != nil { 345 return nil, errors.Wrapf(err, "resp.Unmarshal") 346 } 347 return nat, nil 348 } 349 350 func (self *SRegion) DeleteNatGateway(id string) error { 351 _, err := self.ecsClient.NatGateways.Delete(id, nil) 352 return errors.Wrapf(err, "NatGateways.Delete(%s)", id) 353 }