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