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  }